【opencv】(8) 傅里叶变换,高通低通滤波器
圖像處理一般分為空間域處理和頻率域處理。
空間域處理是直接對圖像內的像素進行處理。主要劃分為灰度變換核空間濾波兩種形式,灰度變換對圖像內的單個像素進行處理,濾波處理涉及對圖像質量的改變。
頻率域處理是先將圖像變換到頻率域,然后在頻率域對圖像進行處理,最后通過反變換將圖像變為空間域。
傅里葉變換可以將圖像變換為頻率域, 傅立葉反變換將頻率域變換為空間域。
傅里葉變換的詳細可看一下知乎大佬的解釋:傅里葉分析之掐死教程(完整版)更新于2014.06.06 - 知乎
在圖像中,高頻是指變化劇烈的灰度分量,如圖像的邊緣輪廓區域。低頻是指圖像中變化緩慢的灰度分量,如圖像中輪廓內的填充,非邊緣區域。
傅里葉變換可進行高通濾波和低通濾波。低通濾波器:只保留低頻信息。如消除圖像邊界,使圖像變得模糊。高通濾波器:只保留高頻信息,消除低頻信息。如增強圖像細節,描繪圖像輪廓信息。
(1) 傅里葉變化函數:
cv2.dft(img,?flags)
img:代表輸入圖像,opencv中輸入圖像必須轉換成np.float32類型
flags:轉換標識,通常為cv2.DFT_COMPLEX_OUTPUT,其他值如下:
(2) 圖像頻譜中的零頻率分量會被移到頻域圖像的中心位置
np.fft.fftshift(x, axis)
x: 數組,代表輸入的頻譜圖數據
axis: 可選,指定需要移動的軸。默認移動所有的軸
返回位移之后的數組。
使用傅里葉變換后,在得到的頻譜圖中,頻率為0的部分會在左上角,為了計算方便,我們通常將頻率為0的部分轉換到頻譜圖中心位置。
(3) 計算二維矢量的幅值
cv2.magnitude(x, y)
x:數組類型,表示浮點型的x軸坐標,也就是實部
y:數組類型,表示浮點型的y軸坐標,也就是虛部
返回值為:x和y的平方和開根,
由于cv2.dft()返回的結果是雙通道的(實部和虛部),通常需要轉換成圖像格式[0,255],才能正常顯示頻譜圖。公式為:
20*np.log(cv2.magnitude(x, y))
(4) 構造濾波器
傅里葉變換之后,構造一個和原圖像相同size的掩模。注意:構造的掩模是三維度的,因為傅里葉變換后的結果第三維度是實部和虛部,有2個通道。掩模的shape應該和它一致。
低通濾波器:構造一個像素值全為0的掩模底板,獲取頻率為0的部分的中心坐標,以它為中點,設置掩模大小,掩模內的像素值都為255。把掩模覆蓋到頻譜圖上,只保留掩模值為255的部分,其他全部刪除。即在頻譜圖像上,只保留頻率為0附近的點,其他高頻點全部刪除。因為掩模白色部分框住的就是所有的低頻點。
高通濾波器:構造一個像素值全為255的掩模底板,獲取頻率為0的部分的中心坐標,以它為中點,設置掩模大小,都掩模內的像素值為0。把掩模覆蓋到頻譜圖上,只保留掩模值為255的部分,其他全部刪除。即在頻譜圖像上,只刪除頻率為0附近的點,其他高頻點全部保留。因為掩模黑色部分覆蓋住的就是所有的低頻點。
我們在下面代碼段的圖中進一步理解
(5) 傅里葉逆變換函數
cv2.idft(img)
img:代表輸入處理后的頻譜圖像
在使用cv2.dft()獲得頻譜圖時,將低頻點從邊緣移動到圖像中間,現在要逆變換,得把低頻點還原到原始位置,使用函數:?np.fft.ifftshift(處理后的頻譜圖)?,之后才能將頻譜圖轉變回空間圖像。
注意,逆變換后的結果是包含實部和虛部的,仍需要使用cv2.magnitude函數進行處理
1. 正向變換
import cv2
import numpy as np
import matplotlib.pyplot as plt
filepath = 'C:\\...\\opencv\\img' # 獲取圖片所在文件夾
#(1)正向變換
# 導入圖像,變成灰度圖
img = cv2.imread(filepath+'\\mh1.jpg',0)
# 轉變成np.float32類型
img_float = np.float32(img)
# 傅里葉變換
dft = cv2.dft(img_float,flags=cv2.DFT_COMPLEX_OUTPUT)
# 獲得頻譜圖,將低頻值轉換到中間
dft_shift = np.fft.fftshift(dft)
# 得到灰度圖能表示的形式,將對實部虛部計算后的結果,映射到0-255之間
magnitude = 20*np.log(cv2.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))
# 繪圖
plt.subplot(121), plt.imshow(img,cmap='gray')
plt.title('input image'), plt.xticks([]), plt.yticks([]) #不顯示坐標軸
plt.subplot(122), plt.imshow(magnitude,cmap='gray')
plt.title('magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()
下圖左側是原圖,右側是FFT變換后的頻譜圖。右側圖中間的亮點代表的頻率為0的部分,離中心點越近,頻率越低,越往外發散,頻率越高。
因此我們只需要把中間一小塊的點抹除掉就能消除所有頻率在0附近的部分,消除低頻信息,實現高通濾波。或者只保留中心點附近的部分,就能消除所有的高頻信息,實現高通濾波。至于怎么消除呢,我們之前提講解過的掩模就可以用在這里。
2. 低通濾波
#(1)傅里葉正向變換
img = cv2.imread(filepath+'\\mh1.jpg',0) 導入圖像,變成灰度圖
# 轉變成np.float32類型
img_float = np.float32(img)
# 傅里葉變換
dft = cv2.dft(img_float,flags=cv2.DFT_COMPLEX_OUTPUT)
# 獲得頻譜圖,將低頻值轉換到中間
dft_shift = np.fft.fftshift(dft)
#(2)構造濾波器
# 獲取頻率為0部分中心點位置
rows,cols = img.shape # (471,498),分別保存圖像的高和寬
crow,col = int(rows/2), int(cols/2) # 計算中心點坐標
# 構造低通濾波器,相當于構造一個掩模
mask = np.zeros((rows,cols,2),np.uint8) # 構造的size和原圖相同,2通道,傅里葉變換后有實部和虛部
mask[crow-30:crow+30, col-30:col+30] = 255 # 構造一個以頻率為0點中心對稱,長30+30,寬30+30的一個區域,只保留區域內部的頻率
#(3)濾波
# 頻譜圖上,低頻的信息都在中間,濾波器和頻譜圖相乘,遮擋四周,保留中間,中間是低頻
fshift = dft_shift*mask
# 在獲得頻譜圖時,將低頻點從邊緣點移動到圖像中間,現在要逆變換,得還回去
f_ishift = np.fft.ifftshift(fshift)
#(4)傅里葉逆變換idft
img_back = cv2.idft(f_ishift)
# 還原后的還是有實部和虛部,需要進一步處理
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])
#(5)繪圖
# 結果展示,低通使圖像模糊
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('input img'), plt.xticks([]), plt.yticks([]) #不顯示坐標軸
plt.subplot(122), plt.imshow(img_back, cmap='gray')
plt.title('fft img'), plt.xticks([]), plt.yticks([])
plt.show()
構造的濾波器是以頻率等于0為中心的矩形,寬30+30,高30+30,如圖1。只保留白色部分,消除黑色部分。白色部分框住的是低頻信息,濾波器設置的越大,保留的低頻信息也就越多,過大會保留高頻信息。
圖2原圖,圖3是低通濾波后的圖,明顯變模糊了,消除了圖像的邊界。
3. 高通濾波?
#(1)正向傅里葉變換
img = cv2.imread(filepath+'\\mh1.jpg',0) # 導入圖像,變成灰度圖
# 轉變成np.float32類型
img_float = np.float32(img)
# 傅里葉變換
dft = cv2.dft(img_float,flags=cv2.DFT_COMPLEX_OUTPUT)
# 獲得頻譜圖,將低頻值轉換到中間
dft_shift = np.fft.fftshift(dft)
#(2)構造濾波器,獲取頻率為0的坐標
rows,cols = img.shape #(471,498),分別保存圖像的高和寬
crow,col = int(rows/2), int(cols/2) # 計算中心點坐標
# 構造高通濾波器,相當于構造一個掩模,設置的越大,低頻信息刪除的越多
mask = np.ones((rows,cols,2),np.uint8) # 構造的size和原圖相同,2通道,傅里葉變換后有實部和虛部
mask[crow-10:crow+10, col-10:col+10] = 0 # 以頻率為0處坐標為中心,寬10+10,高10+10的部分抹除
#(3)傅里葉逆變換
# 刪除中間的信息,保留其他部分的信息,低頻都集中在中央位置,統一刪除
fshift = dft_shift*mask
# 在獲得頻譜圖時,將低頻點從邊緣點移動到圖像中間,現在要逆變換,得還回去
f_ishift = np.fft.ifftshift(fshift)
# 傅里葉逆變換idft
img_back = cv2.idft(f_ishift)
# 還原后的還是有實部和虛部,需要進一步處理
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])
#(4)繪圖
# 結果展示,只有邊界信息
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('input img'), plt.xticks([]), plt.yticks([]) #不顯示坐標軸
plt.subplot(122), plt.imshow(img_back, cmap='gray')
plt.title('fft img'), plt.xticks([]), plt.yticks([])
plt.show()
高通濾波器,構造一個以頻率等于0為中心的矩形,寬10+10,高10+10,如圖1。只保留白色部分,消除黑色部分。白色部分(像素255)框住的是高頻信息,黑色部分(像素為0)設置的越大,消除的低頻信息也就越多,過大會一定程度抹除一些高頻信息。
圖2原圖,圖3是高通濾波后的圖,只保留了圖像的邊界,抹除了圖像的內在信息。
總結
以上是生活随笔為你收集整理的【opencv】(8) 傅里叶变换,高通低通滤波器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【opencv】(7) 图像匹配、直方图
- 下一篇: 【深度学习】(1) 前向传播,附pyth