這篇介紹OPENCV提供的對影像作空間濾波的工具,透過2D Convolution(旋積或譯卷積),可以達到對影像作濾波的功能,而對影像實施低通濾波(LPF),實質上就是對影像作去除雜訊,模糊化的作用,而高通濾波(HPF)實質上對影像的作用就是銳利化,以及可以凸顯出影像的邊緣。
2D Convolution
跟信號一樣,我們也可以對 2D 圖像實施低通濾波(LPF),高通濾波(HPF)等。OpenCV 提供的函數 cv.ftlter2D() 可以讓我們對一幅圖像進行卷積操作。如下圖<一>我們對一幅圖像做Convolution (旋積),底下是使用一個 3x3 kernel (核)的運算範例圖。
操作如下:將核放在原圖像的一個像素A 上,求與核對應的圖像上 3x3個像素的和,用這個值替代像素 A 的值。重複以上操作直到
將圖像的每一個像素值都更新一遍。
圖<一>2D Convolution演算法
此圖來源:
於是我們可以改變kernel(核)的大小或是給他一個權重來達到對影像做低通濾波(LPF)或是高通濾波(HPF)的目的。如下圖<二>所示,給予一個 3x3 kernel (核)與原像素相乘加總後再取平均值,即相當於對影像做平均值濾波。再移動對每一個像素做同樣的演算,直到全部都做完。
<圖二>使用kernel 3x3做平均濾波
此圖來源:
這裡會產生一個問題,最邊邊與最角落的像素怎麼做?底下有幾種方式可以處裡。
第一種方法是邊邊會直接被捨棄,但是這樣旋積後影大小會比原本的小。
第二種方式是先在四個邊外圍都先補上一列或一行0,這樣做旋積之後影像大小可以維持不變,
但是由於補0所以會出現黑框效果,一樣的,如果補255,那麼就會出現白框。
第三種方式是將上述第二種補0方式改成補原先鄰近的值, 這樣就不會出現黑框,但是相對的,
這種處裡比較麻煩。第二第三種方式作法有一個專有名詞叫做Pading。然而
在OPENCV裡實施Convolution不用擔心這問題,因為OPENCV已經幫忙處裡好了。
OPENCV做Convolution之後的影像大小會維持不變。
下圖三為 使用cv.ftlter2D() ,執行的效果。程式碼很簡單,給定一個kernel的大小,然後直接引用 cv2.filter2D即可作用在原本影像img變數上。
EX:
kernel = np.ones((5,5),np.float32)/25
dst = cv2.filter2D(img,-1,kernel)
<圖三>
< cv.ftlter2D() 完整範例程式>
如果只是要做出上述的平均值方式濾波OPENCV,另外提供了函數
blur = cv2.blur() 及blur = cv2.boxFilter()可以使用。
那麼除了使用平均值演算方式以外,有沒有其他方式?
聰明的你可能已經想到,是的,只要在kernel核上面動一些數學變化,即可做出各式各樣的濾波演算方式。如底下函數:
cv2.medianBlur(img,5)
#取用中間值演算方式濾波,5代表使用kernel 5x5大小
#注意kernel 大小應當都使用奇數大小,這樣才會有中心點
cv2.GaussianBlur(img,(5,5),0)
#使用高斯函數做濾波
#kernel 為5x5
cv2.bilateralFilter(img,9,75,75)
#使用bilateral 做模糊濾波,它跟GaussianBlur不同的地方在於可以保留邊緣的細節。
#而GaussianBlur則會連邊緣都模糊。
看下<圖四>可以比較出各種模糊濾波的範例
<圖四>各種模糊濾波的範例
< 模糊範例程式>
為什麼要對影像模糊化?
有人這樣說,人類喜歡看清楚銳利的影像而電腦反而喜歡看模糊的影像。實際上在做影像辨識時,為了要讓電腦容易認出影像的特徵,所以通常會先去除背景的雜訊,讓特徵值在後續的處裡容易顯現出來。例如要做高通濾波去顯現邊緣或特徵最簡單的一種方式就是,直接用原圖再減去模糊化後的圖,就可以得到高通濾波的圖。
https://www.facebook.com/arbu00/
<其他有關OPENCV 文章>
OPENCV(6)--Trackbar(軌道桿)
OPENCV(5)--Drawing
OPENCV(4)--Grayscale,Binarization,Threshole(灰階化,二值化,閥值)
OPENCV(3)--Matplotlib pyplot bassic function
OPENCV(2)--Capture Video from Camera
OPENCV(1 )--How to install OPENCV in Python
<參考資料:>OPENCV官網
http://docs.opencv.org/3.1.0/index.html