数字图像处理笔记(七):频域低通滤波平滑图像

1 - 傅里叶变换

在前面我们对空间滤波做了重点的研究,现在我们来介绍一下涉及频率域中的各种滤波技术。图像从空间域转换到频率域使用的是二维傅里叶变换,一个像素为M*N的图像f(x,y)进行傅里叶变换得到F(u,v),那么一般的公式为:
F ( u , v ) = x = 0 M 1 y = 0 N 1 f ( x , y ) e j 2 π ( u x / M + v y / N ) F(u,v)=\sum_{x=0}^{M-1}\sum_{y=0}^{N-1}f(x,y)e^{-j2\pi(ux/M+vy/N)}

它的反变换就是
f ( x , y ) = 1 M N x = 0 M 1 y = 0 N 1 F ( u , v ) e j 2 π ( u x / M + v y / N ) f(x,y)=\frac{1}{MN}\sum_{x=0}^{M-1}\sum_{y=0}{N-1}F(u,v)e^{j2\pi(ux/M+vy/N)}

反变换就可以实现将频域图像恢复到时域图像。

这些公式可能有些复杂,但是使用numpy包提供的函数可以直接进行图像的傅里叶变换

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('images/12.jpg',0)
f = np.fft.fft2(img)# 快速傅里叶变换算法得到频率分布
fshift = np.fft.fftshift(f) # 默认结果中心点位置是在左上角,转移到中间位置
#取绝对值:将复数变化成实数
#取对数的目的为了将数据变化到较小的范围(比如0-255)
s1 = np.log(np.abs(f))
s2 = np.log(np.abs(fshift))
plt.subplot(121),plt.imshow(s1,'gray'),plt.title('original')
plt.subplot(122),plt.imshow(s2,'gray'),plt.title('center')
plt.show()

在这里插入图片描述

(注意的是,上图其实并没有什么含义,显示出来的可以看成是频域后图像的振幅信息)

Ok再来说说程序中为什么要有一个np.fft.fftshift(f)中心化操作,整个图像是在傅里叶变换的一个周期内完成的,将其看成横纵两个方向的一维傅里叶变换,在每个方向上都会有高频信号和低频信号,那么傅里叶变换将低频信号放在了边缘,高频信号放在了中间,然而一副图像,很明显的低频信号多而明显,所以将低频信号采用一种方法移到中间

图像变换到频域后就可以进行操作了,目前接触到的频域操作似乎也就是一些滤波操作,如同空域里面的滤波操作一样,不过原理不一样了,后面再说说一些频域滤波方法。好了一旦操作完,得到的数据还是频域数据,那么如何将其变换到时域呢?这里就是傅里叶反变换了,公式表示就如同前面那样。这个频域变换到时域的操作就是逆向傅里叶变换再走一遍(比如先反中心化,在逆变换)。一个实例如下:

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('images/12.jpg',0) #直接读为灰度图像
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
#取绝对值:将复数变化成实数
#取对数的目的为了将数据变化到0-255
s1 = np.log(np.abs(fshift))
plt.subplot(131),plt.imshow(img,'gray'),plt.title('original')
plt.subplot(132),plt.imshow(s1,'gray'),plt.title('center')
# 逆变换
f1shift = np.fft.ifftshift(fshift)
img_back = np.fft.ifft2(f1shift)
#出来的是复数,无法显示
img_back = np.abs(img_back)
plt.subplot(133),plt.imshow(img_back,'gray'),plt.title('img back')
plt.show()

在这里插入图片描述

好了,了解基本的傅里叶变换操作后,我们就可以对图像先进行傅里叶变换,然后在频率域上进行滤波操作后,再利用傅里叶逆变换得到处理之后的图像。下面就介绍频率域滤波器的作用。

2 - 使用频率域滤波器平滑图像

2.1 - 理想低通滤波器

以原点为圆心,以 D 0 D_0 为半径的院内,无衰减地通过所有频率,而在圆外“切断”所有频率的二维低通滤波器,称为理想低通滤波器(ILPF),其函数表达式为:
H ( u , v ) = { 1 D ( u , v ) D 0 0 D ( u , v ) > D 0 H(u,v)=\left\{\begin{matrix} 1 & D(u,v)\leq D_0\\ 0 & D(u,v) >D_0 \end{matrix}\right.
其中, D 0 D_0 是一个正常数, D ( u , v ) D(u,v) 是频率域中点 ( u , v ) (u,v) 与频率域矩形中心的距离,即
D ( u , v ) = [ ( u P / 2 ) 2 + ( v Q / 2 ) 2 ] 1 2 D(u,v)=[(u-P/2)^2+(v-Q/2)^2]^{\frac{1}{2}}

在这里插入图片描述
python构建理想低通滤波器


import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('images/12.jpg',0) #直接读为灰度图像
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
#取绝对值:将复数变化成实数
#取对数的目的为了将数据变化到0-255
s1 = np.log(np.abs(fshift))


def make_transform_matrix(d,image):
    """
    构建理想低通滤波器
    :param d: 滤波器半径
    :param image: 图像的傅里叶变换
    :return:
    """
    transfor_matrix = np.zeros(image.shape)
    center_point = tuple(map(lambda x:(x-1)/2,s1.shape))
    for i in range(transfor_matrix.shape[0]):
        for j in range(transfor_matrix.shape[1]):
            def cal_distance(pa,pb):
                from math import sqrt
                dis = sqrt((pa[0]-pb[0])**2+(pa[1]-pb[1])**2)
                return dis
            dis = cal_distance(center_point,(i,j))
            if dis <= d:
                transfor_matrix[i,j]=1
            else:
                transfor_matrix[i,j]=0
    return transfor_matrix

d_1 = make_transform_matrix(10,fshift)
d_2 = make_transform_matrix(30,fshift)
d_3 = make_transform_matrix(50,fshift)

plt.subplot(131)
plt.axis("off")
plt.imshow(d_1,cmap="gray")
plt.title('D_1 10')
plt.subplot(132)
plt.axis("off")
plt.title('D_2 30')
plt.imshow(d_2,cmap="gray")
plt.subplot(133)
plt.axis("off")
plt.title("D_3 50")
plt.imshow(d_3,cmap="gray")
plt.show()

在这里插入图片描述
之后进行滤波处理


#频率域经过理想低通滤波器变换后再进行逆变换还原到时域图像
img_d1 = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift*d_1)))
img_d2 = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift*d_2)))
img_d3 = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift*d_3)))
plt.subplot(131)
plt.axis("off")
plt.imshow(img_d1,cmap="gray")
plt.title('D_1 10')
plt.subplot(132)
plt.axis("off")
plt.title('D_2 30')
plt.imshow(img_d2,cmap="gray")
plt.subplot(133)
plt.axis("off")
plt.title("D_3 50")
plt.imshow(img_d3,cmap="gray")
plt.show()

在这里插入图片描述

2.2 - 布特沃斯低通滤波器

截止频率位于距原点 D 0 D_0 处的n阶布特沃斯低通滤波器(BLPF)的传递函数定义为
H ( u , v ) = 1 1 + [ D ( u , v ) / D 0 ] 2 n H(u,v)=\frac{1}{1+[D(u,v)/D_0]^{2n}}

在这里插入图片描述

其与ILPF的不同,BLPF传递函数在通过频率和截止频率的选择上并没有选择使用尖锐、不连续的区分,而是采用更加的平滑传递函数的滤波器。

python构建BLPF滤波器:


import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('images/12.jpg',0) #直接读为灰度图像
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
s1 = np.log(np.abs(fshift))


def butterworthPassFilter(image, d, n):
    f = np.fft.fft2(image)
    fshift = np.fft.fftshift(f)

    def make_transform_matrix(d):
        transfor_matrix = np.zeros(image.shape)
        center_point = tuple(map(lambda x: (x - 1) / 2, s1.shape))
        for i in range(transfor_matrix.shape[0]):
            for j in range(transfor_matrix.shape[1]):
                def cal_distance(pa, pb):
                    from math import sqrt
                    dis = sqrt((pa[0] - pb[0]) ** 2 + (pa[1] - pb[1]) ** 2)
                    return dis

                dis = cal_distance(center_point, (i, j))
                transfor_matrix[i, j] = 1 / ((1 + (dis / d)) ** n)
        return transfor_matrix

    d_matrix = make_transform_matrix(d)
    plt.imshow(d_matrix, cmap="gray")
    new_img = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift * d_matrix)))
    return new_img

butter_5_1 = butterworthPassFilter(img,5,1)
plt.subplot(121)
plt.imshow(img,cmap="gray")
plt.title("img")
plt.axis("off")
plt.subplot(122)
plt.imshow(butter_5_1,cmap="gray")
plt.title("d=5,n=3")
plt.axis("off")
plt.show()

在这里插入图片描述

2.3 - 高斯低通滤波器

高斯低通滤波(GLPF)函数表达式:
H ( u , v ) = e D 2 ( u , v ) / 2 σ 2 H(u,v)=e^{-D^2(u,v)/2\sigma^2}

其中,D(u,v)是距频率矩形中心的距离, σ \sigma 是关于中心的扩展度的度量。通过令 σ = D 0 \sigma=D_0 我们可以在本节中使用其他滤波器的表示法来表示该滤波器
H ( u , v ) = e D 2 ( u , v ) / 2 D 0 2 H(u,v)=e^{-D^2(u,v)/2D_0^2}
其中, D 0 D_0 是截止频率,当 D ( u , v ) = D 0 D(u,v)=D_0 时,GLPF下降到其最大值的0.607处
在这里插入图片描述

python实现高斯低通滤波器平滑图像


import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('images/12.jpg',0) #直接读为灰度图像
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
s1 = np.log(np.abs(fshift))


def GaussianLowFilter(image,d):
    f = np.fft.fft2(image)
    fshift = np.fft.fftshift(f)
    def make_transform_matrix(d):
        transfor_matrix = np.zeros(image.shape)
        center_point = tuple(map(lambda x:(x-1)/2,s1.shape))
        for i in range(transfor_matrix.shape[0]):
            for j in range(transfor_matrix.shape[1]):
                def cal_distance(pa,pb):
                    from math import sqrt
                    dis = sqrt((pa[0]-pb[0])**2+(pa[1]-pb[1])**2)
                    return dis
                dis = cal_distance(center_point,(i,j))
                transfor_matrix[i,j] = np.exp(-(dis**2)/(2*(d**2)))
        return transfor_matrix
    d_matrix = make_transform_matrix(d)
    new_img = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift*d_matrix)))
    return new_img

img_d1 = GaussianLowFilter(img,10)
img_d2 = GaussianLowFilter(img,30)
img_d3 = GaussianLowFilter(img,50)
plt.subplot(131)
plt.axis("off")
plt.imshow(img_d1,cmap="gray")
plt.title('D_1 10')
plt.subplot(132)
plt.axis("off")
plt.title('D_2 30')
plt.imshow(img_d2,cmap="gray")
plt.subplot(133)
plt.axis("off")
plt.title("D_3 50")
plt.imshow(img_d3,cmap="gray")
plt.show()

在这里插入图片描述

3 - 总结

总结一下,我们学习了如何将图片进行傅里叶变换到频率域,通过在频域率的低通滤波来进行图像的平滑处理,然后我们主要介绍了理想低通滤波器(ILPF)、布特沃斯低通滤波器(BLPF)和高斯低通滤波器(GLPF)的原理和具体的在python环境下对图片处理的实验。

猜你喜欢

转载自blog.csdn.net/HHH_ANS/article/details/85030759