1. 程式人生 > 實用技巧 >空域濾波器與頻域濾波器的關係

空域濾波器與頻域濾波器的關係

頻域濾波和空域濾波有著密不可分的關係。頻域濾波器是通過對影象變化頻率的控制來達到影象處理的目的,而空域濾波器是通過影象矩陣對模板進行卷積運算達到處理影象的效果。由卷積定理可知,空域上的卷積數值上等於影象和模板傅立葉變換乘積的反變換。

也就是說如果將空域上的模板進行離散傅立葉變化得到頻域上的模板,那麼用空域模板進行空域濾波和用得到的頻域模板進行頻域濾波最後結果是一樣的,兩種方法有時可以互換。

但需要注意的一點是,將原始影象與空域模板進行卷積運算,得到卷積結果的長度要比原來的影象長,就算對影象和模板進行填充,得到的卷積結果的第一位也不是模板在原始影象第一個畫素處的卷積。

比如假設p位原始影象長度為P,q為卷積模板長度為Q,則由卷積的運算公式易得不產生混淆下影象的最小填充後尺寸為P+Q-1,填充後p,q為

執行如下程式

import numpy as np
# 保留效數點後三位
np.set_printoptions(precision=3)
# 不使用科學計數法
np.set_printoptions(suppress=True)

p = np.array([[1,2,3,0,0],[4,5,6,0,0],[7,8,9,0,0],[0,0,0,0,0],[0,0,0,0,0]])
q = np.array([[1,1,1,0,0],[1,-8,1,0,0],[1,1,1,0,0],[0,0,0,0,0],[0,0,0,0,0]])
pp = np.fft.fft2(p)
qq = np.fft.fft2(q)
tt = pp*qq
t = np.fft.ifft2(tt)
print('p\n', p) print('q\n', q) print('t\n', t.real)

利用卷積定理可以得到卷積後的結果t為

從上述執行結果可知,雖然進行零填充可以有效避免混淆,但無法改變的一點是,卷積後圖像的尺寸會變大。可以看出卷積後的結果填滿了整個5×5的矩陣。理論上用模板在影象第一個畫素處的卷積值(也就是3)來替代影象原來的第一個畫素更加恰當——我們之前編寫的空域濾波器的程式也是這麼做的——而現在這個結果在卷積運算的(1,1)處。實際上真正在影象上的卷積結果位於t的中心處,即下面截圖才是與原始影象相等大小的濾波結果。

因此要想得到和空域濾波器相同的結果,在填充和頻域濾波之後提取影象時,就要將得到的處理結果的邊緣去掉。假設模板大小位P×Q,則濾波後得到的邊緣寬度為(floor(P/2), floor(Q/2))。

下面進行空域濾波和頻域濾波的比較。比較步驟如下

(1)定義一個小尺寸的空域模板,用該模板進行空域濾波,獲得濾波影象。

(2)根據空域濾波模板和原影象的大小計算頻域模板的填充大小。

(3)將空域模板進行填充並乘以$(-1)^{x+y}$,然後進行傅立葉變換得到頻域模板。

(4)用得到的頻域模板進行頻域濾波,並對濾波結果進行擷取。

(5)空域濾波和頻域濾波的結果顯示比較。

其中對sobel運算元的比較程式碼如下

import frequency_function as fre
import airspace_filter as air
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

original_image_test4 = cv.imread('test4.tif',0)


'''比較對應的頻域濾波器和空域濾波器是否等效'''
#
# 比較sobel運算元
#
# 得到空域sobel濾波函式
airspace_result_test1 = air.laplace_sharpen(original_image_test4, my_type='big')
# 定義空域濾波模板
air_model = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]])
# 計算模板填充後的尺寸
shape = (2*original_image_test4.shape[0], 2*original_image_test4.shape[1])
# 將空域模板填充到相應尺寸,變換為頻域模板並將低頻移至中心
fre_model = np.fft.fft2(fre.my_get_fp(fre.my_fill(air_model, shape)))
# 用頻域模板進行頻域濾波
frequency_result_test1 = fre.myfunc_seldifine(original_image_test4, fre_model, output_offset=(1, 1))
# 將濾波結果的畫素值轉換到0~255
airspace_result_test1=air.show_edge(airspace_result_test1)
frequency_result_test1=air.show_edge(frequency_result_test1)

# 結果顯示
plt.subplot(131)
plt.imshow(original_image_test4)
plt.title('original')
plt.subplot(132)
plt.imshow(airspace_result_test1)
plt.title('spatial filter')
plt.subplot(133)
plt.imshow(frequency_result_test1)
plt.title('frequency filter')
plt.show()

比較結果為

可以看出兩種方式效果是相同的。

對高斯低通濾波的比較程式碼

import frequency_function as fre
import airspace_filter as air
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

original_image_test1 = cv.imread('test1.pgm',0)
original_image_test2 = cv.imread('test2.tif',0)
original_image_test3 = cv.imread('test3_corrupt.pgm',0)
original_image_test4 = cv.imread('test4.tif',0)

#
# 比較高斯濾波器
#
# 得到空域高斯濾波函式
airspace_result_test1 = air.gaussion_blur_gray(original_image_test1, 7, 1.5)
# 獲得空域高斯濾波模板
air_model = air.get_gaussion_blur_retric(7, 1.5)
# 計算模板填充後的尺寸
shape = (original_image_test1.shape[0] + 7, original_image_test1.shape[1] + 7)
# 將空域模板填充到相應尺寸,變換為頻域模板並將低頻移至中心
fre_model = np.fft.fft2(fre.my_get_fp(fre.my_fill(air_model, shape)))
# 用頻域模板進行頻域濾波
frequency_result_test1 = fre.myfunc_seldifine(original_image_test1, fre_model, output_offset=(3, 3))

# 濾波結果顯示
plt.subplot(131)
plt.imshow(original_image_test1)
plt.title('original')
plt.subplot(132)
plt.imshow(airspace_result_test1)
plt.title('spatial filter')
plt.subplot(133)
plt.imshow(frequency_result_test1)
plt.title('frequency filter')
plt.show()

比較結果為