0
点赞
收藏
分享

微信扫一扫

【OpenCV 完整例程】81. 频率域高斯低通滤波器

【OpenCV 完整例程】81. 频率域高斯低通滤波器

3.3 频率域高斯低通滤波器(GLPF)

例程 8.16 以理想低通滤波器为例,给出了频率域图像滤波的一般步骤。

高斯滤波器的滤波效果随着样值点到傅里叶变换中心的距离的变化而变化,当距离增大时滤波效果变好。

频率域高斯低通滤波器也是一个掩模蒙板:

H ( u , v ) = e − ( u 2 + v 2 ) / 2 σ 2 D ( u , v ) = ( u − P / 2 ) 2 + ( v − Q / 2 ) 2 H(u,v) = e^{-(u^2+v^2)/2 \sigma^2}\\ D(u,v) = \sqrt {(u-P/2)^2+(v-Q/2)^2} H(u,v)=e(u2+v2)/2σ2D(u,v)=(uP/2)2+(vQ/2)2
式中 D 0 = σ D_0=\sigma D0=σ 是截止频率,当 D ( u , v ) = D 0 D(u,v) = D_0 D(u,v)=D0 时 GLPF 下降到最大值的 0.607处。

利用二维高斯蒙板,可以滤去高频、保留低频。频域高斯函数的方差 σ 2 \sigma^2 σ2 越小,高斯函数越狭窄,滤除的高频成分(图像细节)越多,图像越模糊。

空间域高斯滤波器的计算量随着模板的增大而增大,而频率域高斯滤波的计算量独立于滤波函数。


例程 8.18:频率域高斯低通滤波器 (GLPF)

# OpenCVdemo08.py
# Demo08 of OpenCV
# 8. 图像的频率域滤波
# Copyright 2021 Youcans, XUPT
# Crated:2021-12-15

    # 8.18:频率域高斯低通滤波器 (GLPF)
    imgGray = cv2.imread("../images/imgLena.tif", flags=0)  # flags=0 读取为灰度图像

    # (1)首先对图像进行傅里叶变换
    imgFloat32 = np.float32(imgGray)  # 将图像转换成 float32
    dft = cv2.dft(imgFloat32, flags=cv2.DFT_COMPLEX_OUTPUT)  # 傅里叶变换
    dftShift = np.fft.fftshift(dft)  # 将低频分量移动到频域图像的中心

    # # 幅度谱
    # imgDFT = 10 * np.log(cv2.magnitude(dftShift[:,:,0], dftShift[:,:,1]))
    # plt.figure(figsize=(9, 6))
    # plt.subplot(121), plt.axis('off'), plt.title("Original"), plt.imshow(imgGray, 'gray')
    # plt.subplot(122), plt.axis('off'), plt.title("FFt"), plt.imshow(imgDFT, cmap='gray')
    # plt.show()

    plt.figure(figsize=(9, 6))
    rows, cols = imgGray.shape[:2]  # 图片的高度和宽度
    sigma2 = [0.5, 0.09, 0.01]  # square of sigma
    for i in range(3):
        # 构造高斯滤波器遮罩:# Gauss = 1/(2*pi*s2) * exp(-(x**2+y**2)/(2*s2))
        x, y = np.mgrid[-1:1:2.0 / rows, -1:1:2.0 / cols]
        z = 1 / (2 * np.pi * sigma2[i]) * np.exp(-(x ** 2 + y ** 2) / (2 * sigma2[i]))
        # maskGauss = np.uint8(cv2.normalize(z, None, 0, 255, cv2.NORM_MINMAX))  # 归一化为 [0,255]
        zNorm = np.uint8(cv2.normalize(z, None, 0, 255, cv2.NORM_MINMAX))  # 归一化为 [0,255]
        maskGauss = np.zeros((rows, cols, 2), np.uint8)
        maskGauss[:,:,0] = zNorm
        maskGauss[:,:,1] = zNorm
        print(maskGauss.shape, maskGauss.max(), maskGauss.min())

        # (2)然后在频率域修改傅里叶变换
        dftTrans = dftShift * maskGauss  # 修改傅里叶变换实现滤波

        # (3)最后通过傅里叶逆变换返回空间域
        ishift = np.fft.ifftshift(dftTrans)  # 将低频逆转换回图像四角
        idft = cv2.idft(ishift)  # 逆傅里叶变换
        imgRebuild = cv2.magnitude(idft[:,:,0], idft[:,:,1])  # 重建图像

        plt.subplot(2,3,i+1), plt.title("Mask (s^2={})".format(sigma2[i])), plt.axis('off')
        plt.imshow(maskGauss[:,:,0], cmap='gray')
        plt.subplot(2,3,i+4), plt.title("DFT GLPF (s^2={})".format(sigma2[i])), plt.axis('off')
        plt.imshow(imgRebuild, cmap='gray')

    plt.tight_layout()
    plt.show()

在这里插入图片描述


程序说明:

(1)使用 cv2.getOptimalDFTSize() 获得快速傅里叶变换的优化尺寸,对原始图像进行了边缘扩充和补 0 填充,因此与原始图像尺寸不一定相同。频域滤波后截取左上角,得到与原始图像大小一致的滤波图像。
(2)注意滤波器的尺寸要与(快速)傅里叶变换的尺寸相同,与原始图像的大小不一定相同。

(本节完)


版权声明:

youcans@xupt 原创作品,转载必须标注原文链接

Copyright 2021 youcans, XUPT

Crated:2022-1-25


举报

相关推荐

0 条评论