使用scipy.signal.spectrogram

时间:2018-06-26 12:24:14

标签: python audio scipy spectrogram

当我通过使用以下代码使用matplotlib中的plt.specgram时,生成的光谱图是正确的

import matplotlib.pyplot as plt
from scipy import signal
from scipy.io import wavfile
import numpy as np

sample_rate, samples = wavfile.read('.\\Wav\\test.wav')

Pxx, freqs, bins, im = plt.specgram(samples[:,1], NFFT=1024, Fs=44100, noverlap=900)

spectrogram generated by using matplotlib

但是,如果我通过将scipy page中给出的示例代码与以下代码一起使用来生成频谱图,则会得到类似这样的信息:

import matplotlib.pyplot as plt
from scipy import signal
from scipy.io import wavfile
import numpy as np

sample_rate, samples = wavfile.read('.\\Wav\\test.wav')

frequencies, times, spectrogram = signal.spectrogram(samples[:,1],sample_rate,nfft=1024,noverlap=900, nperseg=1024)

plt.pcolormesh(times, frequencies, spectrogram)
plt.ylabel('Frequency [Hz]')
plt.xlabel('Time [sec]')

enter image description here

要调试正在发生的事情,我尝试使用由第一种方法生成的Pxxfreqsbins,然后使用第二种方法来绘制数据: / p>

plt.pcolormesh(bins, freqs, Pxx)
plt.ylabel('Frequency [Hz]')
plt.xlabel('Time [sec]')

enter image description here

生成的图与通过第二种方法生成的图几乎相同。 因此,看来scipy.signal.spectrogram毕竟没有问题。问题是我们绘制图形的方式。我不知道plt.pcolormesh是否是绘制频谱图的正确方法,尽管在scipy document

中建议使用此方法

有人问过类似的问题here,但该问题尚未解决。

3 个答案:

答案 0 :(得分:7)

频谱图的默认缩放模式为“ dB”(来自频谱图文档)

  

比例尺:[‘默认’| “线性” | ‘dB’]   规格值的缩放。 “线性”是无法缩放的。 “ dB”返回以dB为单位的值。模式为“ psd”时,即为dB功率(10 * log10)。否则,这是dB幅度(20 * log10)。如果模式为“ psd” 或“幅值”,则“默认”为“ dB”,否则为“线性”。如果模式为“角度”或“相位”,则必须为“线性”。

     

模式:[‘默认’| ‘psd’| “幅度” | “角度” | “阶段”]   使用哪种频谱。 默认值为“ psd” ,该参数采用功率谱密度。 “ complex”返回复数值频谱。 “幅度”返回幅度谱。 “角度”可返回相位光谱而无需展开。 “相位”返回展开后的相位频谱。

要使用pcolormesh获得相似的结果,您将需要等效地缩放数据。

plt.pcolormesh(times, frequencies, 10*np.log10(spectrogram))

我认为pcolormesh示例的缩放比例不正确。您可以在示例中清楚地看到载波,但是看不到添加的噪声信号。

答案 1 :(得分:0)

改为使用此:

plt.pcolormesh(times, frequencies, spectrogram, norm = matplotlib.colors.Normalize(0,1))

这将在绘制之前对数据进行归一化,以便您可以正确地可视化颜色。 matplotlib.colors.Colormap上的文档说:“通常使用Colormap实例将数据值(浮点数)从间隔[0,1]转换为相应Colormap表示的RGBA颜色。” 如果您的值超出此范围,则可能会将其绘制为深色(我相信)。

答案 2 :(得分:0)

您应该在 pcolormesh 函数中使用非线性颜色图之一。

尝试设置 norm=matplotlib.colors.LogNorm(vmin=np.amin(spectrogram), vmax=np.amax(spectrogram))

norm=matplotlib.colors.PowerNorm(gamma=0.5)

有关详细信息,请参阅 https://matplotlib.org/stable/tutorials/colors/colormapnorms.html