在使用 pyfftw 和 scipy.fft 的 ifft 操作期间发生相位不连续

Phase discontinuity happens during ifft operation using pyfftw and scipy.fft

当使用 pyfftw 对 2D 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 代码中的相位不连续,我该如何纠正它。

相位最好显示为单位圆上的角度。圆没有起点和终点。绕圈子不会产生不连续性。恰好加上 2*pi(绕圆圈一圈)不会改变相位,所以 +pi 和 -pi 是相同的相位。因此,这两个相位的绝对差不是 2*pi,而是零。如果考虑到微小的舍入误差,它几乎为零。

我的建议是使用 "cyclic" 配色方案(不知道更好的术语),其中在一端接近 +pi 而在另一端接近 -pi 为图形着色相同的颜色。

您的输入是对称的,这会导致纯实数变换(相位为 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 for double float)。根据需要进行调整。