实现 fftshift 和 ifftshift 的正确顺序(在 python 中)

Posted

技术标签:

【中文标题】实现 fftshift 和 ifftshift 的正确顺序(在 python 中)【英文标题】:Correct order of implementing fftshift and ifftshift (in python) 【发布时间】:2017-06-28 08:41:21 【问题描述】:

我想对函数 psi(x) 进行傅里叶变换,将其乘以 k 空间函数 exp(-kx^2-ky^2),然后将乘积逆傅里叶变换回 x 空间。

但是我的 x 空间和 k 空间网格是居中的,我知道我需要 fftshiftifftshift 来正确实现我的 k 空间乘法。但是我不明白它们是如何工作的,所以我不知道以什么顺序来实现它们。有人可以告诉我我在这里做得是否正确吗?

import scipy.fftpack as spfft
import numpy as np

#Create a centred k-space grid]

kxmax, kymax = 10,10
kxgrid = np.linspace(-kxmax/2, kxmax/2, NX)
kygrid = np.linspace(-kymax/2, kymax/2, NY)
KX, KY = np.meshgrid(kxgrid, kygrid, indexing='xy')

psi = spfft.ifft2(spfft.fftshift(np.exp(-(KX**2 + KY**2)) * spfft.fftshift(spfft.fft2(psi))))

【问题讨论】:

【参考方案1】:

不,你没有,但没关系,这可能会很混乱。

第一件事:fftifft 要求原点位于向量的开头(或者在您的二维情况下,位于数组的左上角)。输入 psi 的原点是否像 KX 一样居中?如果是这样,它的原点必须以ifftshift 开头。 (如果没有,那就别管它了。)

第二:因为KXKY 起源于它们的中心,你必须解除它们的偏移:你需要spfft.ifftshift(np.exp(-(KX**2 + KY**2))(注意i)。

最后:您的输出 psi 因此将在开始时有其来源。如果您希望它的原点像KXfftshift 一样居中。

总结:

inputOriginStart = # ...
inputOriginStartFFT = spfft.fft2(psiOriginStart)
filterOriginStartFFT = spfft.ifftshift(np.exp(-(KX**2 + KY**2)))
outputOriginStart = spfft.ifft2(filterOriginStartFFT * inputOriginStartFFT)

其中inputOriginStart 是输入psi,假设它的起源在开头,而outputOriginStart 是输出psi——为了清楚起见重命名。 (我总是很清楚。如果它不起作用,你可以更容易地弄清楚。)

编辑修复了提问者指出的错误——是的,我有一个错误,在开头留下psiOriginStart的来源;然后ifftshiftKXKY 的居中原点函数。 (如果你想将outputOriginStart的原点移到中心,那么使用fftshift。)

编辑 2 将过滤器(KXKY 的功能)与数据分开,以使正确的括号明显。


如何保持这些直线?需要记住的一些技巧:

fftifft 总是需要输入并给出起源在开头的输出。这应该很容易从经验中记住。 fftshift 采用 fft 需要/制作的起点原点并将原点转移到中心。再说一次,我很容易记住这一点,因为我在输入 fftshift(fft(...)) 一千次后会产生肌肉记忆。 最后,唯一剩下的就是推断ifftshiftfftshift 的倒数:它采用居中的原点向量/数组并将原点移到开头。

【讨论】:

我有一个困惑,为什么spfft.fftshift(spfft.fft2(psiOriginStart))) ?一旦我对左上角的psiOriginstart 进行了傅立叶变换,我需要留在那里与spfft.ifftshift(np.exp(-(KX**2 + KY**2)) 相乘,对吗?最后,我ifftshift回到中心。所以,应该是spfft.ifft2(spfft.ifftshift(np.exp(-(KX**2 + KY**2)) * spfft.fft2(psiOriginStart)))吧? @ap21 你完全正确——你现在明白了!!!对困惑感到抱歉!我编辑了答案。请注意:在你的评论中你说,“最后,我 ifftshift back to the center”——不完全是,你会 fftshift 从开始到中心的原点(见第二个项目符号)。编辑包含此注释。 我认为您的括号中可能仍然存在错误。我们只想像spfft.ifftshift(np.exp(-(KX**2 + KY**2))) 那样移动exp(-kx^2+ky^2) 的原点,而不是像你写的那样做spfft.ifftshift(np.exp(-(KX**2 + KY**2)) * spfft.fft2(psiOriginStart))。对吗? 哦不,你又完全正确了,我很惭愧!我编辑了答案以明确去哪里。感谢您的耐心等待!

以上是关于实现 fftshift 和 ifftshift 的正确顺序(在 python 中)的主要内容,如果未能解决你的问题,请参考以下文章

C++-实现matlab的fftshift(OpenCV)

fftshift函数详解

FFT和IFFT的Matlab实现(幅频响应和相频响应)

FFT和IFFT的Matlab实现(幅频响应和相频响应)

p68 对数变换 关于fft2 fftshift 频谱

OFDM留空中央直流子载波的原理及实现