一、二维离散傅里叶变换(DFT)
-
对于二维图像处理,通常使用 x , y 表示离散的空间域坐标变量,用 u , v 表示离散的频率域变量。二维离散傅里叶变换(DFT)和反变换(IDFT)为:
-
二维离散傅里叶变换也可以用极坐标表示:
-
傅里叶频谱(Fourier spectrum)为:
-
傅里叶相位谱(Fourier phase spectrum)为:
-
傅里叶功率谱(Fourier power spectrum)为:
空间取样和频率间隔是相互对应的,频率域所对应的离散变量间的间隔为:
。即:频域中样本之间的间隔,与空间样本之间的间隔及样本数量的乘积成反比。
-
空间域滤波器和频率域滤波器也是相互对应的,二维卷积定理是在空间域和频率域滤波之间建立等价关系的纽带:
这表明 F 和 H 分别是 f 和 h 的傅里叶变换;f 和 h 的空间卷积的傅里叶变换,是它们的变换的乘积。
因此,计算两个函数的空间卷积,可以直接在空间域计算,也可以在频率域计算:先计算每个函数的傅里叶变换,再对两个变换相乘,最后进行傅里叶反变换转换回空间域。
也就是说,空间域滤波器和频率域滤波器实际上是相互对应的,有些空间域滤波器在频率域通过傅里叶变换实现会更方便、更快速。
二、Numpy 实现图像傅里叶变换
- Numpy 中的 np.fft.fft2() 函数可以实现图像的傅里叶变换 。
numpy.fft.fft2(a, s=None, axes=(- 2, - 1), norm=None) → out
- a:输入数组,一维或多维数组,可以是复数形式
- s:输出数组的形状(每个变换轴的长度),对应于 fft(x,n) 中的 n,可选项
- out:输出数组,复数形式的一维或多维数组(complex ndarray)
三、注意事项:
- 1、用于二维图像傅里叶变换时,输入数组 a 是 numpy 二维数组(灰度图像)或三维数组(彩色图像)。
- 2、输出结果是复数形式 ( R e a l + j ∗ I m a g ) (Real + j * Imag)(Real+j∗Imag) 的数组,不能直接用于显示图像。为了显示傅里叶变换结果的图像,需要将数组的值调整到 [0,255] 的灰度空间内。
经过 np.fft.fft2() 函数实现傅里叶变换得到的图片频谱信息,幅度谱的最大值(低频分量)在左上角 (0,0) 处。为了便于观察,通常用 np.fft.fftshift() 函数将低频分量移动到频域图像的中心位置。
四、函数
numpy.fft.fftshift(x, axes=None) → y
- x:输入数组,一维或多维数组
- axes:整数,或输入数组形状的元组,用于指定移动的轴,可选项
- y:输出数组
五、例程
- 8.10:二维图像的离散傅里叶变换(Numpy)
# 8.10:Numpy 实现二维离散傅里叶变换
normalize = lambda x: (x - x.min()) / (x.max() - x.min() + 1e-6)
imgGray = cv2.imread("../images/Fig0424a.tif", flags=0) # flags=0 读取为灰度图像
# imgGray = cv2.imread("../images/imgBall.png", flags=1) # flags=0 读取为灰度图像
# 傅里叶变换
# fft = np.fft.fft2(imgGray.astype(np.float32))
fft = np.fft.fft2(imgGray) # np.fft.fft2 实现傅里叶变换
# 非中心化,计算幅度谱和相位谱
ampSpectrum = np.sqrt(np.power(fft.real, 2) + np.power(fft.imag, 2)) # 幅度谱
print("ampSpectrum max={}, min={}".format(ampSpectrum.max(), ampSpectrum.min()))
# phase = np.arctan2(fft.imag, fft.real) # 计算相位角(弧度制)
# phiSpectrum = phase / np.pi*180 # 将相位角转换为 [-180, 180]
phiSpectrum = np.angle(fft)
# 中心化,将低频分量移动到频域图像的中心
fftShift = np.fft.fftshift(fft) # 将低频分量移动到频域图像的中心
# 中心化后的幅度谱
ampSpeShift = np.sqrt(np.power(fftShift.real, 2) + np.power(fftShift.imag, 2))
ampShiftNorm = np.uint8(normalize(ampSpeShift)*255) # 归一化为 [0,255]
# 幅度谱做对数变换
ampSpeLog = np.log(1 + ampSpeShift) # 幅度谱做对数变换以便于显示
ampSpeLog = np.uint8(normalize(ampSpeLog)*255) # 归一化为 [0,255]
# np.fft.ifft2 实现图像的逆傅里叶变换
invShift = np.fft.ifftshift(fftShift) # 将低频逆转换回图像四角
imgIfft = np.fft.ifft2(invShift) # 逆傅里叶变换,返回值是复数数组
imgRebuild = np.abs(imgIfft) # 将复数数组调整至灰度空间
plt.figure(figsize=(9, 6))
plt.subplot(231), plt.title("Original image"), plt.axis('off')
plt.imshow(imgGray, cmap='gray')
plt.subplot(232), plt.title("FFT phase spectrum"), plt.axis('off')
plt.imshow(phiSpectrum, cmap='gray')
plt.subplot(233), plt.title("Rebuild image with IFFT"), plt.axis('off')
plt.imshow(imgRebuild, cmap='gray')
plt.subplot(234), plt.title("FFT amplitude spectrum"), plt.axis('off')
plt.imshow(ampSpectrum, cmap='gray')
plt.subplot(235), plt.title("FFT-shift amplitude"), plt.axis('off')
plt.imshow(ampSpeShift, cmap='gray')
plt.subplot(236), plt.title("Log-trans of FFT amp"), plt.axis('off')
plt.imshow(ampSpeLog, cmap='gray')
plt.tight_layout()
plt.show()
六、资料
youcans_的博客:
https://blog.csdn.net/youcans/article/details/122614107