我正在尝试重现它在维基百科条目中的Gabor变换的例子,我不知道它是否是一个bug或者我错过了什么。例子是计算正弦信号的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例程不能颠倒数组,因为它通常在1D图中完成。有人知道为什么会这样做吗?
谢谢,
Alex
答案 0 :(得分:3)
问题在于W
。或实际上在w
。绘制w
时:
因此pcolormesh
接收非单调Y坐标并感到困惑。如果你看一下pcolor
或pcolormesh
的描述,很明显他们对非单调数据不能做任何合理的事情。
所以,你的gabor
很好:
ax.imshow(gabor)
你可以看到:
如何解决这个问题有多种可能性。其中之一是将W
和gabor
同时馈送到fftshift
,这样频率就会回滚到单调。或者 - 如果您想获得上面的数字(顶部的负频率),只需将最大频率添加到W
的所有负值。
使用pcolormesh
和x
代替w
和T
提供W
也可能更为清晰。
如果你想要性能,你可能会更好地使用imshow
(当数据在两个维度中均衡时,可以使用它。唯一的小问题是范围的计算(实际上可能稍微偏差)在问题中。范围告诉最高,最低,最左边和最右边像素的外部石灰。然而,像素矢量只告诉像素的中心。
我们需要了解以下内容:
num_x
)num_y
)x0
,x1
)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)
给出: