我正在尝试重现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坐标并感到困惑。如果查看pcolor
或pcolormesh
的描述,很明显,它们不能对非单调数据做任何合理的事情。
因此,您的gabor
很好:
ax.imshow(gabor)
如你看到的:
有几种解决方法。其中之一是将
W
和gabor
都馈入fftshift
,以使频率回滚到单调。或-如果您想获得上面的数字(顶部为负频率),只需将最大频率添加到W
的所有负值。为
pcolormesh
提供x
和w
而不是T
和W
可能更清洁。如果需要性能,最好使用
imshow
(在两个维度上数据均等时可以使用它。唯一的小问题是范围的计算(即使在问题中,实际上也可能略有不同)。范围告诉最高,最低,最左侧和最右侧像素的外部标记,但是像素矢量仅指示像素的中心。我们需要了解以下内容:
X方向上的点数(
num_x
)Y方向上的点数(
num_y
)第一个和最后一个x样本的值(
x0
,x1
)第一个和最后一个y样本的值(
y0
,y1
)之后,我们可以使用
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/