Matlab:对于偶实函数,FFT的结果为复数,IFFT的结果为实数。

3

我正在测试Matlab中FFT和IFFT函数的有效性。

我可以将这些函数的输出与一个众所周知的数学事实进行比较:偶数实函数(如以0为中心的高斯函数)的傅里叶变换是另一个偶数实函数(FFT[real, 0-centered Gaussian] = real, 0-centered Gaussian)。这个事实应该对FFT和IFFT都成立。

首先,我创建我的网格:

nx = 256; % grid total pixel count
X = 500; % grid size (um)
dx = X/nx; %  grid spacing (um)
x = linspace(-nx/2,nx/2-1,nx)*dx; % x grid (um)

df = 1/(nx*dx); % spectral grid spacing (1/um)
f = linspace(-nx/2,nx/2-1,nx)*df; % f grid (1/um)

我制作高斯函数:

A = 1; % magnitude (arbitrary units) 
x_fwhm = 7; % Full width at half maximum diameter (um)

x0 = x_fwhm/sqrt(2*log(2)); % 1/e^2 radius (um)
y = A*exp(-2*x.^2./(x0)^2); % Gaussian (arbitrary units) 

应用快速傅里叶变换(FFT):

yFFT = fftshift(fft(fftshift(y))); 

或者,使用 IFFT:

yIFFT = fftshift(ifft(fftshift(y))); 

绘制结果:图中显示了:(a)在空间中定义的高斯函数y,(b)FFT(y)的实部,(c)IFFT(y)的实部,(d)FFT(y)的虚部和(e)IFFT(y)的虚部。 IFFT完美地完成了它的工作:yIFFT是一个纯实数高斯函数。然而,FFT得到一个复数:存在一个非常小的虚部。这很正常,因为傅里叶变换算法会有误差,并且这个误差可以忽略不计。令我困惑的是,为什么IFFT中根本没有任何误差?FFT和IFFT算法有这么大的不同吗?
***注意:由于我的数组具有偶数个元素,fftshift和ifftshift在此处是等效的。
2个回答

5
处理实值时间域信号是相当普遍的。事实上,ifft函数内置了对应频域中出现的对称性的处理,如文档中的“算法”部分所述:
ifft函数会测试Y向量是否为共轭对称。当第i个元素满足v(i) = conj(v([1,end:-1:2]))时,向量v就是共轭对称的。如果Y向量是共轭对称的,则反变换计算速度更快,输出为实数。”
换句话说,ifft通过检测输入是否具有共轭对称性来构造yIFFT的虚部恰好为0。
另一方面,即使是时间域信号也相对较少见,Mathworks也没有认为在fft函数中执行类似的测试是必要的。尽管如此,您仍然可以通过使用ifft函数计算FFT来利用共轭对称性测试。
% compute fft(x,[],dim) using ifft:
size(x,dim) * conj(ifft(conj(x),[],dim))

非常好!这让我想知道其他语言,比如Python或C++的FFTW库是否也是如此。 - Liz Salander

1
您的代码中有错误:

yFFT = fftshift(fft(fftshift(y)));

应该阅读。
yFFT = fftshift(fft(ifftshift(y)));
ifftshift函数将原点从中间移到最左边的箱子。 fftshift将原点从最左边的箱子移动到中间。这两个操作对于奇数大小的数组相似但不完全相同。请注意,您的反向变换存在相同的问题,但是像SleuthEye所解释的那样没有错误。 [不用担心那一点,我有点困惑,你的情况没有区别。]

另外,

linspace(-nx/2,nx/2-1,nx)

would be better written as

-nx/2 : nx/2-1

假设nx是偶数。这样更短,但由于计算方式的不同,它可能会有更小的数值误差(也许没有区别,但当步长为1时,我尽量避免使用linspace)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接