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

也就是說如果將空域上的模板進行離散傅里葉變化得到頻域上的模板,那么用空域模板進行空域濾波和用得到的頻域模板進行頻域濾波最后結果是一樣的,兩種方法有時可以互換。
但需要注意的一點是,將原始圖像與空域模板進行卷積運算,得到卷積結果的長度要比原來的圖像長,就算對圖像和模板進行填充,得到的卷積結果的第一位也不是模板在原始圖像第一個像素處的卷積。
比如假設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()
比較結果為

