Легенда интенсивности спектрограммы Matplotlib (цветная полоса)

Я использую функцию specgram matplotlib для создания спектрограммы. Я попытался добавить цветную полосу справа от спектрограммы, чтобы показать преобразование дБ в цвет.

Однако по какой-то причине дБ, обозначенные цветной полосой, не имеют смысла.

Возможно, я не правильно сгенерировал цветовую полосу? Возможно, есть какой-то параметр, который мне нужно передать в спектрограмму?

Сигнал, который я генерирую, представляет собой синусоиду 1 кГц, 2 В пик-пик, дискретизированную на частоте 32 кГц.

Я ожидаю, что темно-красный пик на спектрограмме соответствует 0 дБ (это означает, что +1 В является моим эталоном)

Кто-нибудь знает, что не так с моим подходом?

def plot_specgram(data, title='', x_label='', y_label='', fig_size=None):
    fig = plt.figure()
    if fig_size != None:
        fig.set_size_inches(fig_size[0], fig_size[1])
    ax = fig.add_subplot(111)
    ax.set_title(title)
    ax.set_xlabel(x_label)
    ax.set_ylabel(y_label)
    pxx,  freq, t, cax = plt.specgram(data, Fs=32000)
    fig.colorbar(cax).set_label('Intensity [dB]')

plot_specgram(a,title='Spectrogram', x_label='time (in seconds)', y_label='frequency', fig_size=(14,8))

Вот что я получаю в результате спектрограммы:

результирующий сюжет


person brandon kinman    schedule 30.11.2014    source источник
comment
Судя по цветовой карте, темно-красный действительно соответствует 0. Просто 0 не отображается... 0db (темно-красный) соответствует пиковому спектральному компоненту 1 кГц... синий, как и ожидалось, имеет более низкое значение интенсивности ( ‹‹ 0 ), поскольку они являются просто артефактами, разработанными из-за выборки... Честно говоря, я не вижу ничего плохого в вашем коде/графике...   -  person Raghav RV    schedule 01.12.2014
comment
На самом деле, вероятно, то, что вы видите, является результатом работы оконной функции, которую вы не принимаете во внимание. Я почти уверен, что specgram использует окно Ханнинга по умолчанию, что может испортить то, что вы ожидаете от масштабирования.   -  person Ajean    schedule 02.12.2014


Ответы (1)


Прежде всего, предоставьте свой вектор a, так как он, похоже, содержит какие-то гармоники.

Это немного проб и ошибок, но, похоже, это дает правильное масштабирование:

NFFT = 256
ax.specgram(x/(NFFT/2), NFFT=NFFT, Fs=fs, mode='magnitude', window=plt.window_none)

Использование окна, кажется, теряет около 1/2 пиковой мощности, вы, конечно, можете настроить это.

Полный пример, где я ограничил динамический диапазон до 40 дБ (например, если вы хотите скрыть мелкие детали).

import numpy as np
import pylab as plt

# generate a 1kHz sine wave
fs = 32e3
t = np.arange(0, 15, 1.0/fs)
f0 = 1e3
A = 1
x = A*np.sin(2*np.pi*f0*t)

fig, ax = plt.subplots()
cmap = plt.get_cmap('viridis')
vmin = 20*np.log10(np.max(x)) - 40  # hide anything below -40 dBc
cmap.set_under(color='k', alpha=None)

NFFT = 256
pxx,  freq, t, cax = ax.specgram(x/(NFFT/2), Fs=fs, mode='magnitude',
                                 NFFT=NFFT, noverlap=NFFT/2,
                                 vmin=vmin, cmap=cmap,
                                 window=plt.window_none)
fig.colorbar(cax)

print np.max(pxx) # should match A

результирующее изображение

person oystein    schedule 24.12.2015
comment
Что такое NFFT и почему там значение 256? - person Martin Thoma; 14.01.2019
comment
@MartinThoma Это входной аргумент для ax.specgram, который управляет количеством частот для расчета спектрограммы, нам нужно разделить на это число, чтобы правильно масштабировать график. См. документацию спектрограммы для математики. - person oystein; 07.02.2021