离散傅立叶变换中的移位定理
Shift theorem in Discrete Fourier Transform
我正在尝试用 python+numpy 解决一个问题,其中我有一些 that I need to convolve with another function 类型的函数。为了优化代码,我对f和g进行了fft运算,将它们相乘,然后进行逆变换得到结果。
作为进一步的优化,我意识到,由于移位定理,我可以简单地计算一次 f(x,y,z) 的 fft,然后将其乘以一个取决于 [=14= 的相位因子], 其中 N 是 x 和 y 的长度。
我试图用 python+numpy 实现这个简单的公式,但由于某些目前我还不清楚的原因它失败了,所以我请求 SO 社区的帮助来计算找出我所缺少的。
我也提供了一个简单的例子。
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!
由于对 np.fft.fftfreq()
的 return 值的不正确(我的错)解释以及按顺序填充数组的必要性,我的代码中的问题都在输入行 6以获得良好的结果。
以下代码效果很好,可以扩展到多维。
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
不错,非常感谢分享!
前段时间我在这行中实现了一些东西,但无法真正掌握它的数学原理(我盲目地移植了描述该算法的白皮书)。 FWIW,这是它:https://github.com/creaktive/flare/blob/master/nrf905_demod.c#L376
我正在尝试用 python+numpy 解决一个问题,其中我有一些
作为进一步的优化,我意识到,由于移位定理,我可以简单地计算一次 f(x,y,z) 的 fft,然后将其乘以一个取决于 [=14= 的相位因子], 其中 N 是 x 和 y 的长度。
我试图用 python+numpy 实现这个简单的公式,但由于某些目前我还不清楚的原因它失败了,所以我请求 SO 社区的帮助来计算找出我所缺少的。
我也提供了一个简单的例子。
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!
由于对 np.fft.fftfreq()
的 return 值的不正确(我的错)解释以及按顺序填充数组的必要性,我的代码中的问题都在输入行 6以获得良好的结果。
以下代码效果很好,可以扩展到多维。
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
不错,非常感谢分享! 前段时间我在这行中实现了一些东西,但无法真正掌握它的数学原理(我盲目地移植了描述该算法的白皮书)。 FWIW,这是它:https://github.com/creaktive/flare/blob/master/nrf905_demod.c#L376