75. Numpy 实现图像傅里叶变换

6. 频率域图像滤波索引

一、二维离散傅里叶变换(DFT)

  • 对于二维图像处理,通常使用 x , y 表示离散的空间域坐标变量,用 u , v 表示离散的频率域变量。二维离散傅里叶变换(DFT)和反变换(IDFT)为:


  • 二维离散傅里叶变换也可以用极坐标表示:


  • 傅里叶频谱(Fourier spectrum)为:


  • 傅里叶相位谱(Fourier phase spectrum)为:


  • 傅里叶功率谱(Fourier power spectrum)为:


  • 空间取样和频率间隔是相互对应的,频率域所对应的离散变量间的间隔为:\Delta u = 1/M \Delta T,\Delta v = 1/N \Delta Z。即:频域中样本之间的间隔,与空间样本之间的间隔及样本数量的乘积成反比。

  • 空间域滤波器和频率域滤波器也是相互对应的,二维卷积定理是在空间域和频率域滤波之间建立等价关系的纽带:


  • 这表明 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
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容