1. 程式人生 > >數字影象處理筆記(七):頻域低通濾波平滑影象

數字影象處理筆記(七):頻域低通濾波平滑影象

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環境下對圖片處理的實驗。