当我通过使用以下代码使用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)
但是,如果我通过将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]')
要调试正在发生的事情,我尝试使用由第一种方法生成的Pxx
,freqs
,bins
,然后使用第二种方法来绘制数据: / p>
plt.pcolormesh(bins, freqs, Pxx)
plt.ylabel('Frequency [Hz]')
plt.xlabel('Time [sec]')
生成的图与通过第二种方法生成的图几乎相同。
因此,看来scipy.signal.spectrogram
毕竟没有问题。问题是我们绘制图形的方式。我不知道plt.pcolormesh
是否是绘制频谱图的正确方法,尽管在scipy document
有人问过类似的问题here,但该问题尚未解决。
答案 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。