我正在尝试重现Gabor变换在其Wikipedia条目中的示例,但我不知道它是否是错误或缺少什么。该示例是计算正弦信号的Gabor变换:



为了绘制排序的频率,我创建了一个未排序的轴。然后,我使用网格网格创建2D轴并使用pcolormesh进行绘制。这是这段代码:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridsp

dt = 0.05
x = np.arange(-50.0,50.0,dt)
y = np.sin(2.0 * np.pi * x)
Nx = len(x)
w = np.fft.fftfreq(Nx,dt)

sigma = 1.0 / 3.0
neg = np.where (x <= 0.0)
pos = np.where (x > 0.0)

T,W = np.meshgrid(x,w)
func = np.zeros(Nx)
tmp = np.zeros(Nx,dtype='complex64')
gabor = np.zeros((Nx,Nx))

func[neg] = np.sin(2.0 * np.pi * x[neg])
func[pos] = np.sin(4.0 * np.pi * x[pos])

for it in range(Nx):
        tmp[:] = np.fft.fft(func[:] * np.exp( - ( x[it] - x[:] ) * ( x[it] - x[:] ) / 2.0 / sigma / sigma ) )

        gabor[:,it] = np.real(np.conj(tmp) * tmp)

fig = plt.figure(figsize=(20,10),facecolor='white')
gs = gridsp.GridSpec(2, 1)

ax1 = plt.subplot(gs[0,0])
ax1.plot(x,func,'r',linewidth=2)
ax1.axis('tight')
ax1.set_xticks(np.arange(min(x),max(x),1.) )
ax1.set_xlabel('time',fontsize=20)
ax1.set_ylabel(r'$\sin{time}$',fontsize=20)
ax1.set_xlim([-6.0,6.0])


ax2 = plt.subplot(gs[1,0])
surf1 = ax2.pcolormesh(T,W,gabor,shading='gouraud')
ax2.axis('tight')
ax2.set_xticks(np.arange(min(x),max(x),2.) )
ax2.set_yticks(np.arange(min(w),max(w),2.) )
ax2.set_xlabel('time',fontsize=20)
ax2.set_ylabel('frequency',fontsize=20)
ax2.set_xlim([-6.0,6.0])
ax2.set_ylim([-4.0,4.0])

gs.tight_layout(fig)
plt.show()


这是我得到的数字,



似乎该图的上部已减少为零。如果我在创建转换和轴时使用fftshift进行尝试,

for it in range(Nx):
        tmp[:] = np.fft.fftshift(np.fft.fft(func[:] * np.exp( - ( x[it] - x[:] ) * ( x[it] - x[:] ) / 2.0 / sigma / sigma ) ) )


        gabor[:,it] = np.real(np.conj(tmp) * tmp)

T,W = np.meshgrid(x,np.fft.fftshift(w))


然后我得到这个图:



似乎pcolormesh例程无法像通常在一维图中完成的那样上下颠倒数组。有人确切知道为什么要这样做吗?

谢谢,

亚历克斯

最佳答案

问题出在W。或实际上在w中。绘制w时:



因此,pcolormesh接收非单调的Y坐标并感到困惑。如果查看pcolorpcolormesh的描述,很明显,它们不能对非单调数据做任何合理的事情。

因此,您的gabor很好:

ax.imshow(gabor)


如你看到的:



有几种解决方法。其中之一是将Wgabor都馈入fftshift,以使频率回滚到单调。或-如果您想获得上面的数字(顶部为负频率),只需将最大频率添加到W的所有负值。

pcolormesh提供xw而不是TW可能更清洁。



如果需要性能,最好使用imshow(在两个维度上数据均等时可以使用它。唯一的小问题是范围的计算(即使在问题中,实际上也可能略有不同)。范围告诉最高,最低,最左侧和最右侧像素的外部标记,但是像素矢量仅指示像素的中心。

我们需要了解以下内容:


X方向上的点数(num_x
Y方向上的点数(num_y
第一个和最后一个x样本的值(x0x1
第一个和最后一个y样本的值(y0y1


之后,我们可以使用imshow以正确的比例显示数据:

dx = 1. * (x1 - x0) / (num_x-1)
dy = 1. * (y1 - y0) / (num_y-1)

ax.imshow(img, extent=[x0 - dx/2, x1 + dx/2, y0 - dy/2, y1 + dy/2], origin='lower', interpolation='nearest')


因此,将其应用于问题的数据:

gabor_shifted = np.fft.fftshift(gabor, axes=0)
w_shifted = np.fft.fftshift(w)

x0 = x[0]
x1 = x[-1]
w0 = w_shifted[0]
w1 = w_shifted[-1]

dx = 1.*(x1-x0) / (len(x) - 1)
dw = 1.*(w1-w0) / (len(w) - 1)

ax2.imshow(gabor_shifted, extent=[x0-dx/2, x1+dx/2, w0-dw/2, w1+dw/2], interpolation='nearest', origin='lower', aspect='auto')
ax2.grid('on', color='w')
ax2.ylim(-4,4)


这使:

关于python - 带有FFT数组的matplotlib pcolormesh中的 buggy 行为?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24777641/

10-12 18:14