理解python中fft2的一个简单案例

信息处理 fft Python 麻木的
2022-01-27 09:42:18

我有代表表面的二维数组。我通过扫描一些理论上平坦的物体来创建它们,我最终得到了可以称为“缺陷”的东西,或者偏离了完美平坦的表面。

我希望获得关于缺陷的主要波长及其幅度的信息,所以我使用了 numpy 的 fft2。由于我是第一个计时器,我做了一些挖掘并尝试使用一些基本示例来掌握。

这是一个:

import numpy as np
import matplotlib.pyplot as plt

"""
fft2 playground.
"""

# Initialise an empty array
field = np.empty([29, 481])

# Set the wave amplitude
amp = 2.5

# Create the synthetic sinusoidal field
for n, i in enumerate(np.linspace(0, 2 * np.pi, field.shape[0])):
    for m, j in enumerate(np.linspace(0, 2 * np.pi, field.shape[1])):
        field[n, m] = amp * np.sin(j)

# Perform 2D fourier and shift the result to centre
f = np.fft.fft2(field)
fshift = np.fft.fftshift(f)

# Calculate the magnitude and phase spectra
magnitude_spectrum = 20*np.log(np.abs(fshift))
phase_spectrum = np.angle(fshift)

# Reconstruct the initial field
f_ishift = np.fft.ifftshift(fshift)
re_field = np.abs(np.fft.ifft2(f_ishift))

# Plot
fig = plt.figure()

fig.add_subplot(411)
plt.imshow(field, cmap='gray')
plt.title('Field'), plt.xticks([]), plt.yticks([])
plt.colorbar()

fig.add_subplot(412)
plt.imshow(magnitude_spectrum, cmap='gray')
plt.title('Magnitude spectrum'), plt.xticks([]), plt.yticks([])

fig.add_subplot(413)
plt.imshow(phase_spectrum, cmap='gray')
plt.title('Phase spectrum'), plt.xticks([]), plt.yticks([])

fig.add_subplot(414)
plt.imshow(re_field, cmap='gray')
plt.title('Reconstructed field'), plt.xticks([]), plt.yticks([])
plt.colorbar()

plt.show()

这使:

尝试简单正弦波的 fft2 和 ifft2。

显然返回的字段与输入的字段不一样。幅度是正确的,但它是镜像的并且有 90 度的相位差。我觉得我错过了一些东西,但我无法确定它。

另外,我希望幅度谱会像 2 个点,一个在中心像素的两侧,没有别的。我的理解是中心像素是零频率,移动到边缘是更高的频率,直到奈奎斯特。

值得注意的是,如果我改变输入场的尺寸,我会在幅度和相位谱上得到不同的结果。

有人可以指出我错过了什么吗?我如何从 fft 取回初始场以及为什么幅度谱是这样的?

谢谢!

2个回答

构建时re_field,放弃np.abs. 它将正弦波的所有负值变为正值。取而代之的是,np.real对 的结果做一个ifft2以摆脱由舍入误差引起的虚部。然后你会得到一个与原件完全匹配的结果。

在幅度谱中你看不到你插入的正弦波,因为它的频率太低了。垂直的黑线是x方向的DC部分,为零,水平的白线是y方向的DC部分,因为只有y方向的DC,所以具有全幅值。

尝试一些更高的频率,然后你会得到一个更好的主意。

幅度是正确的,但它是镜像的并且有 90 度的相位差。我觉得我错过了一些东西,但我无法确定它。

re_field里面有np.abs,所以不是一回事。你已经纠正了信号。要删除可忽略的虚部,请np.fft.ifft2(f_ishift).real改用。

另外,我希望幅度谱会像 2 个点,一个在中心像素的两侧,没有别的。

是的,如果您不先对它进行对数缩放。但是,您的频率是每帧 1 个周期,这非常低,并且正好适合 DC 线路。如果您使用更高的频率,您可以看到与该频率相对应的间距更宽的点。