1. 程式人生 > >python數字圖像處理(四) 頻率域濾波

python數字圖像處理(四) 頻率域濾波

urn nim turn 更多 都是 import ims sso frequency

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

首先讀入這次需要使用的圖像

img = cv2.imread(‘apple.jpg‘,0) #直接讀為灰度圖像
plt.imshow(img,cmap="gray")
plt.axis("off")
plt.show()

技術分享圖片

使用numpy帶的fft庫完成從頻率域到空間域的轉換。

f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)

低通濾波器

低通濾波器的公式如下
\[ H(u,v)= \begin{cases} 1, & \text{if $D(u,v)$ } \leq D_{0}\ 0, & \text{if $D(u,v)$} \geq D_{0} \end{cases} \]


其中\(D(u,v)\)為頻率域上\((u,v)\)點到中心的距離,\(D_0\)由自己設置
技術分享圖片
白點就是所允許通過的頻率範圍
3d圖像如下
技術分享圖片

我們先把蘋果轉化成頻率域看下效果

#取絕對值:將復數變化成實數
#取對數的目的為了將數據變化到0-255
s1 = np.log(np.abs(fshift))
plt.subplot(121),plt.imshow(s1,‘gray‘)
plt.title(‘Frequency Domain‘)
plt.show()

技術分享圖片

matplotlib對於不是uint8的圖像會自動把圖像的數值縮放到0-255上,更多可以查看對該問題的討論

我們在頻率域上試著取不同的\(d_0\)

再將其反變換到空間域看下效果

def make_transform_matrix(d,image):
    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)

設定距離分別為10,30,50其通過的頻率的範圍如圖

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()

技術分享圖片

講上面過程整理得到頻率域低通濾波器的代碼如下

def lowPassFilter(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))
                if dis <= d:
                    transfor_matrix[i,j]=1
                else:
                    transfor_matrix[i,j]=0
        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
plt.imshow(lowPassFilter(img,60),cmap="gray")

技術分享圖片

高通濾波器

高通濾波器同低通濾波器非常類似,只不過二者通過的波正好是相反的
\[ H(u,v)= \begin{cases} 0, & \text{if $D(u,v)$ } \leq D_{0}\ 1, & \text{if $D(u,v)$} \geq D_{0} \end{cases} \]
技術分享圖片

def highPassFilter(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))
                if dis <= d:
                    transfor_matrix[i,j]=0
                else:
                    transfor_matrix[i,j]=1
        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 = highPassFilter(img,10)
img_d2 = highPassFilter(img,30)
img_d3 = highPassFilter(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()

技術分享圖片

顯然當\(D_0=10\)時,蘋果的邊緣最清楚

不同濾波的比較

import imagefilter
thread_img = imagefilter.RobertsAlogrithm(img)
laplace_img = imagefilter.LaplaceAlogrithm(img,"fourfields")
mean_img = cv2.blur(img,(3,3))
plt.subplot(131)
plt.imshow(thread_img,cmap="gray")
plt.title("ThreadImage")
plt.axis("off")
plt.subplot(132)
plt.imshow(laplace_img,cmap="gray")
plt.axis("off")
plt.title("LaplaceImage")
plt.subplot(133)
plt.imshow(mean_img,cmap="gray")
plt.title("meanImage")
plt.axis("off")
plt.show()

技術分享圖片

空間域上的平均濾波和低通濾波一樣,只要起去掉無關信息,平滑圖像的作用。

Roberts,Laplace等濾波則起的提取邊緣的作用。

頻率域高通濾波器

高斯高通濾波器

頻率域高斯高通濾波器的公式如下
\[ H(u,v) = 1-e^{\dfrac{-D^2(u,v)}{2D_0^2}} \]
技術分享圖片

def GaussianHighFilter(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] = 1-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

使用高斯濾波器d分別為10,30,50實現的效果

img_d1 = GaussianHighFilter(img,10)
img_d2 = GaussianHighFilter(img,30)
img_d3 = GaussianHighFilter(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()

技術分享圖片

高斯低通濾波器

頻率域高斯低通濾波器的公式如下
\[ H(u,v) = e^{\dfrac{-D^2(u,v)}{2D_0^2}} \]

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()

技術分享圖片

空間域的高斯濾波

通常空間域使用高斯濾波來平滑圖像,在上一篇已經寫過,直接使用上篇文章的代碼。

def GaussianOperator(roi):
    GaussianKernel = np.array([[1,2,1],[2,4,2],[1,2,1]])
    result = np.sum(roi*GaussianKernel/16)
    return result

def GaussianSmooth(image):
    new_image = np.zeros(image.shape)
    image = cv2.copyMakeBorder(image,1,1,1,1,cv2.BORDER_DEFAULT)
    for i in range(1,image.shape[0]-1):
        for j in range(1,image.shape[1]-1):
            new_image[i-1,j-1] =GaussianOperator(image[i-1:i+2,j-1:j+2])
    return new_image.astype(np.uint8)

new_apple = GaussianSmooth(img)
plt.subplot(121)
plt.axis("off")
plt.title("origin image")
plt.imshow(img,cmap="gray")
plt.subplot(122)
plt.axis("off")
plt.title("Gaussian image")
plt.imshow(img,cmap="gray")
plt.subplot(122)
plt.axis("off")
plt.show()

技術分享圖片

巴特沃斯濾波器

無論是低通濾波器,高通濾波器都是粗暴的一刀切,正如之前那麽多空間域的濾波器一樣,我們希望它通過的頻率和與中心線性相關。
\[ h(u,v) = \frac{1} {{1+(D_0 / D(u,v))}^{2n}} \]
技術分享圖片

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+(d/dis))**n)
        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
plt.subplot(231)
butter_100_1 = butterworthPassFilter(img,100,1)
plt.imshow(butter_100_1,cmap="gray")
plt.title("d=100,n=1")
plt.axis("off")
plt.subplot(232)
butter_100_2 = butterworthPassFilter(img,100,2)
plt.imshow(butter_100_2,cmap="gray")
plt.title("d=100,n=2")
plt.axis("off")
plt.subplot(233)
butter_100_3 = butterworthPassFilter(img,100,3)
plt.imshow(butter_100_3,cmap="gray")
plt.title("d=100,n=3")
plt.axis("off")
plt.subplot(234)
butter_100_1 = butterworthPassFilter(img,30,1)
plt.imshow(butter_100_1,cmap="gray")
plt.title("d=30,n=1")
plt.axis("off")
plt.subplot(235)
butter_100_2 = butterworthPassFilter(img,30,2)
plt.imshow(butter_100_2,cmap="gray")
plt.title("d=30,n=2")
plt.axis("off")
plt.subplot(236)
butter_100_3 = butterworthPassFilter(img,30,3)
plt.imshow(butter_100_3,cmap="gray")
plt.title("d=30,n=3")
plt.axis("off")
plt.show()

技術分享圖片

可以明顯的觀察出過大的n造成的振鈴現象

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

技術分享圖片

python數字圖像處理(四) 頻率域濾波