Python 如何以pylab';s specgram()有什么作用?

Python 如何以pylab';s specgram()有什么作用?,python,audio,matplotlib,spectrogram,Python,Audio,Matplotlib,Spectrogram,在Pylab中,specgram()函数为给定的振幅列表创建频谱图,并自动为频谱图创建窗口 我想生成光谱图(瞬时功率由Pxx给出),通过在其上运行边缘检测器对其进行修改,然后绘制结果 (Pxx, freqs, bins, im) = pylab.specgram( self.data, Fs=self.rate, ...... ) 问题是,每当我尝试使用imshow或甚至ununiformimage绘制修改后的Pxx时,我都会遇到下面的错误消息 /opt/local/Library/Frame

在Pylab中,
specgram()
函数为给定的振幅列表创建频谱图,并自动为频谱图创建窗口

我想生成光谱图(瞬时功率由
Pxx
给出),通过在其上运行边缘检测器对其进行修改,然后绘制结果

(Pxx, freqs, bins, im) = pylab.specgram( self.data, Fs=self.rate, ...... )
问题是,每当我尝试使用
imshow
或甚至
ununiformimage
绘制修改后的
Pxx
时,我都会遇到下面的错误消息

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site packages/matplotlib/image.py:336:UserWarning:非线性轴上不支持图像。 warnings.warn(“非线性轴上不支持图像”)

例如,下面是我正在编写的代码的一部分

    # how many instantaneous spectra did we calculate
    (numBins, numSpectra) = Pxx.shape

    # how many seconds in entire audio recording
    numSeconds = float(self.data.size) / self.rate


    ax = fig.add_subplot(212)
    im = NonUniformImage(ax, interpolation='bilinear')

    x = np.arange(0, numSpectra)
    y = np.arange(0, numBins)
    z = Pxx
    im.set_data(x, y, z)
    ax.images.append(im) 
    ax.set_xlim(0, numSpectra)
    ax.set_ylim(0, numBins)
    ax.set_yscale('symlog') # see http://matplotlib.org/api/axes_api.html#matplotlib.axes.Axes.set_yscale
    ax.set_title('Spectrogram 2')
实际问题
如何使用matplotlib/pylab以对数轴打印类似图像的数据?

使用
pcolor
pcolormesh
pcolormesh
的速度要快得多,但仅限于直线栅格,因为pcolor可以处理任意形状的单元<代码>specgram使用
pcolormesh
,如果我没记错的话。(它使用
imshow

举个简单的例子:

import numpy as np
import matplotlib.pyplot as plt

z = np.random.random((11,11))
x, y = np.mgrid[:11, :11]

fig, ax = plt.subplots()
ax.set_yscale('symlog')
ax.pcolormesh(x, y, z)
plt.show()

您看到的差异是由于绘制
specgram
返回的“原始”值造成的。
specgram
实际绘制的是缩放版本

import matplotlib.pyplot as plt
import numpy as np

x = np.cumsum(np.random.random(1000) - 0.5)

fig, (ax1, ax2) = plt.subplots(nrows=2)
data, freqs, bins, im = ax1.specgram(x)
ax1.axis('tight')

# "specgram" actually plots 10 * log10(data)...
ax2.pcolormesh(bins, freqs, 10 * np.log10(data))
ax2.axis('tight')

plt.show()

请注意,当我们使用
pcolormesh
绘制东西时,没有插值。(这是
pcolormesh
的一部分——它只是矢量矩形,而不是图像。)

如果您想要在对数范围内进行操作,可以使用
pcolormesh

import matplotlib.pyplot as plt
import numpy as np

x = np.cumsum(np.random.random(1000) - 0.5)

fig, (ax1, ax2) = plt.subplots(nrows=2)
data, freqs, bins, im = ax1.specgram(x)
ax1.axis('tight')

# We need to explictly set the linear threshold in this case...
# Ideally you should calculate this from your bin size...
ax2.set_yscale('symlog', linthreshy=0.01)

ax2.pcolormesh(bins, freqs, 10 * np.log10(data))
ax2.axis('tight')

plt.show()

只是为了补充乔的答案。。。 我发现,
specgram
的视觉输出与
pcolormesh
(NoiseyGeko也是如此)的视觉输出之间的差异很小,这让我感到困扰

结果表明,如果将从
specgram
返回的频率和时间容器传递到
pcolormesh
,它会将这些值视为矩形的中心值,而不是矩形的边缘

稍加摆弄就能让他们变得更好(尽管还不是100%完美)。现在颜色也一样了

x = np.cumsum(np.random.random(1024) - 0.2)
overlap_frac = 0
plt.subplot(3,1,1)
data, freqs, bins, im = pylab.specgram(x, NFFT=128, Fs=44100, noverlap = 128*overlap_frac, cmap='plasma')
plt.title("specgram plot")

plt.subplot(3,1,2)
plt.pcolormesh(bins, freqs, 20 * np.log10(data), cmap='plasma')
plt.title("pcolormesh no adj.")

# bins actually returns middle value of each chunk
# so need to add an extra element at zero, and then add first to all
bins = bins+(bins[0]*(1-overlap_frac))
bins = np.concatenate((np.zeros(1),bins))
max_freq = freqs.max()
diff = (max_freq/freqs.shape[0]) - (max_freq/(freqs.shape[0]-1))
temp_vec = np.arange(freqs.shape[0])
freqs = freqs+(temp_vec*diff)
freqs = np.concatenate((freqs,np.ones(1)*max_freq))

plt.subplot(3,1,3)
plt.pcolormesh(bins, freqs, 20 * np.log10(data), cmap='plasma')
plt.title("pcolormesh post adj.")

你是个巫师!这是可行的,但我不得不说它相当慢。此外,这看起来与
specgram
绘制的光谱图略有不同。你有什么想法吗?用于比较。所发生的是,您正在绘制由
specgram
返回的原始数据。它实际绘制的是
10*np.log10(Pxx)
。我将在一秒钟内添加一个示例。太棒了,这似乎解决了颜色差异问题。现在很明显,y刻度是非常不同的。非常感谢你的帮助!对于pcolormesh版本的情节,我没有得到相同的比例。这里的例子看起来也不一样。它们很接近,但实际上并不相同。specgram图的右上角为深蓝色,但pcolormesh版本的颜色并非如此。我正在用noverlap=0做specgram,所以没有插值,所以我假设它们会绘制相同的图。我如何在这上面得到一个颜色条?