在用pyfftw对一个二维ndarray进行ifft时,我发现结果相位在很多位置是不连续的。我的代码如下。
import numpy as np
import pyfftw
from scipy.fft import ifftshift,fftshift
import matplotlib.pyplot as plt
N = 256
kx = np.linspace(-np.floor(N/2),np.ceil(N/2)-1,N)
kX,kY = np.meshgrid(kx,kx)
kR = np.sqrt(kX**2 + kY**2)
mask = np.where((kR<=15),1,0)
ifft_obj = pyfftw.builders.ifft2(ifftshift(mask))
wave = fftshift(ifft_obj())
plt.imshow(np.angle(wave),cmap='jet')
plt.colorbar()
相位图如下最小相位值为 -3.141592653589793
而最大值为 3.141592653589793
而且它们的差异大于2pi。使用scipy.fft只是得到同样的结果。然而,当我转向Matlab时,结果看起来更合理。我的代码是。
N = 256;
kx = linspace(-floor(N/2),ceil(N/2)-1,N);
[kX,kY] = meshgrid(kx,kx);
kR = sqrt(kX.^2 + kY.^2);
mask = single(kR<=15);
wave = fftshift(ifft2(ifftshift(mask)));
imshow(angle(wave));
caxis([min(angle(wave),[],'all') max(angle(wave),[],'all')]);
axis image; colormap jet;colorbar;
不知道是什么原因导致python代码中的相位不连续,如何纠正。
您的输入是对称的,这导致了一个纯实数变换(正值时相位为0,负值时相位为π)。但是由于FFT算法的数值不准确,结果的虚值非常小。因此,相位与0和π有一点偏差。在您的彩色映射图像中,0的小偏差是看不到的,但π的小偏差会导致接近于-π的值(因为 乙方副总裁已经讨论过).
MATLAB没有显示这个问题,因为MATLAB的 ifft
识别输入是(共轭)对称的,并输出一个纯实像。它只是忽略了那些小的虚值。
您可以在 Python 中用
wave = np.real_if_close(wave, tol=1000)
这里的容忍度是 np.finfo(wave.dtype).eps * tol
(2.22 10-13 对于双浮球)。) 根据需要进行调整。
一个相位最好显示为单位圆上的一个角。而圆没有起点和终点。绕圆不会产生不连续。正好加上2*pi(绕圆一圈)不会改变相位,所以+pi和-pi是同一个相位。因此,这两个相位的绝对差不是2*pi,而是零。如果你考虑到微小的四舍五入误差,它几乎为零。
我的建议是使用一个 "循环 "的颜色方案(不知道更好的术语),其中一端接近+pi,另一端接近-pi,用相同的颜色给图形着色。