离散傅立叶变换中的位移定理

时间:2016-04-27 09:39:41

标签: python numpy fft dft

我试图解决python + numpy的一个问题,我需要将$f(x-x_i,y-y_i,z)$类型的某些函数与另一个函数$g(x,y,z,t)$进行卷积。为了优化代码,我执行了f和g的fft,我将它们相乘,然后我执行逆变换以获得结果。

作为进一步的优化,我意识到,由于移位定理,我可以简单地计算一次f(x,y,z)的fft,然后将其乘以取决于$(x_i, y_i)$的相位因子获得$f(x-x_i,y-y_i,z)$的fft。特别是$\mathcal{F}(f(x-x_i,y-y_i,z)) = exp^{-2\pi j (x_i w_1 + y_i w_2)/N} \mathcal{F}(f(x,y,z))$,其中N是x和y的长度。

我尝试用python + numpy来实现这个简单的公式,但由于某些原因我目前无法理解它失败了,所以我要求SO社区帮助弄清楚我和# 39; m失踪。

我还提供了一个简单的例子。

In [1]: import numpy as np
In [2]: x = np.arange(-10, 11)
In [3]: base = np.fft.fft(np.cos(x))
In [4]: shifted = np.fft.fft(np.cos(x-1))
In [5]: w = np.fft.fftfreq(x.size)
In [6]: phase = np.exp(-2*np.pi*1.0j*w/x.size)
In [7]: test = phase * base
In [8]: (test == shifted).all()
Out[8]: False
In [9]: shifted/base
Out[9]:
array([ 0.54030231 -0.j        ,  0.54030231 -0.23216322j,
        0.54030231 -0.47512034j,  0.54030231 -0.7417705j ,
        0.54030231 -1.05016033j,  0.54030231 -1.42919168j,
        0.54030231 -1.931478j  ,  0.54030231 -2.66788185j,
        0.54030231 -3.92462627j,  0.54030231 -6.74850534j,
        0.54030231-20.55390586j,  0.54030231+20.55390586j,
        0.54030231 +6.74850534j,  0.54030231 +3.92462627j,
        0.54030231 +2.66788185j,  0.54030231 +1.931478j  ,
        0.54030231 +1.42919168j,  0.54030231 +1.05016033j,
        0.54030231 +0.7417705j ,  0.54030231 +0.47512034j,
        0.54030231 +0.23216322j])
In [10]: np.abs(shifted/base)
Out[10]:
array([  0.54030231,   0.58807001,   0.71949004,   0.91768734,
         1.18100097,   1.52791212,   2.00562555,   2.72204338,
         3.96164334,   6.77009977,  20.56100612,  20.56100612,
         6.77009977,   3.96164334,   2.72204338,   2.00562555,
         1.52791212,   1.18100097,   0.91768734,   0.71949004,   0.58807001])

我希望通过shifted/base我可以获得相位因子的相应值,但是可以看出,它不能是相位因子,因为它的np.abs是> = 1 !

2 个答案:

答案 0 :(得分:1)

我的代码中的问题是在输入第6行,由于np.fft.fftfreq()的返回值的错误(我的错误)解释,以及填充数组以获得合理结果的必要性。 / p>

以下代码效果很好,可以扩展到multidimension。

In [1]: import numpy as np
In [2]: shift = 1
In [3]: dx = 0.5
In [4]: pad = 20
In [5]: x = np.arange(-10, 11, dx)
In [6]: y = np.cos(x)
In [7]: y = np.pad(y, (0,pad), 'constant')
In [8]: y_shift = np.cos(x-shift)
In [9]: y_fft = np.fft.fft(y)
In [10]: w = np.fft.fftfreq(y.size, dx)
In [11]: phase = np.exp(-2.0*np.pi*1.0j*w*shift)
In [12]: test = phase * y_fft
In [13]: # we use np.real since the resulting inverse fft has small imaginary part values that are zero
In [14]: inv_test = np.real(np.fft.ifft(test))
In [15]: np.allclose(y[:-pad-2],inv_test[2:-pad])
Out[15]: True

答案 1 :(得分:1)

很好,非常感谢您的分享! 我前段时间已经在这方面实现了一些东西,但无法真正掌握它的数学(我盲目地移植了描述算法的白皮书)。 FWIW,就是这样:https://github.com/creaktive/flare/blob/master/nrf905_demod.c#L376