轉自:OpenCV 教程
另附:計算機視覺:算法與應用(2012),Learning OpenCV(2009)
平滑圖像:濾波器
平滑 也稱 模糊, 是一項簡單且使用頻率很高的圖像處理方法。平滑處理的用途有很多, 但是在本教程中我們僅僅關注它減少噪聲的功用 (其他用途在以后的教程中會接觸到)。平滑處理時需要用到一個 濾波器 。最常用的濾波器是 線性 濾波器。不妨把 濾波器 想象成一個包含加權系數的窗口,當使用這個濾波器平滑處理圖像時,就把這個窗口滑過圖像。
歸一化濾波器 (Normalized Box Filter)
最簡單的濾波器,輸出像素值是核窗口內像素值的 均值 ( 所有像素加權系數相等)。
blur( src, dst, Size( i, i ), Point(-1,-1) );
- src: 輸入圖像
- dst: 輸出圖像
- Size( w,h ): 定義內核大小( w 像素寬度, h 像素高度)
- Point(-1, -1): 指定錨點位置(被平滑點), 如果是負值,取核的中心為錨點。
高斯濾波器 (Gaussian Filter)
最有用的濾波器 (盡管不是最快的)。 高斯濾波是將輸入數組的每一個像素點與 高斯內核 卷積將卷積和當作輸出像素值。
GaussianBlur( src, dst, Size( i, i ), 0, 0 );
- src: 輸入圖像
- dst: 輸出圖像
- Size(w, h): 定義內核的大小(需要考慮的鄰域范圍)。
和
必須是正奇數,否則將使用
和
參數來計算內核大小。
: x 方向標准方差, 如果是
則
使用內核大小計算得到。
: y 方向標准方差, 如果是
則
使用內核大小計算得到。.
中值濾波器 (Median Filter)
中值濾波將圖像的每個像素用鄰域 (以當前像素為中心的正方形區域)像素的 中值 代替 。
medianBlur ( src, dst, i );
- src: 輸入圖像
- dst: 輸出圖像, 必須與 src 相同類型
- i: 內核大小 (只需一個值,因為我們使用正方形窗口),必須為奇數。
雙邊濾波 (Bilateral Filter)
目前我們了解的濾波器都是為了 平滑 圖像, 問題是有些時候這些濾波器不僅僅削弱了噪聲, 連帶着把邊緣也給磨掉了。為避免這樣的情形 (至少在一定程度上 ), 我們可以使用雙邊濾波。類似於高斯濾波器,雙邊濾波器也給每一個鄰域像素分配一個加權系數。 這些加權系數包含兩個部分, 第一部分加權方式與高斯濾波一樣,第二部分的權重則取決於該鄰域像素與當前像素的灰度差值。
詳細的解釋可以查看 鏈接。
bilateralFilter ( src, dst, i, i*2, i/2 );
- src: 輸入圖像
- dst: 輸出圖像
- d: 像素的鄰域直徑
: 顏色空間的標准方差
: 坐標空間的標准方差(像素單位)
利用掩碼(kernel mask)簡單濾波:filter2D
矩陣的掩碼操作很簡單。其思想是:根據掩碼矩陣(也稱作核)重新計算圖像中每個像素的值。掩碼矩陣中的值表示近鄰像素值(包括該像素自身的值)對新像素值有多大影響。從數學觀點看,我們用自己設置的權值,對像素鄰域內的值做了個加權平均。
以下是利用filter2D函數實現Laplace filter來加強圖像對比度的實例(samples\cpp\tutorial_code\core\mat_mask_operations):
Mat kern = (Mat_<char>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0); filter2D(I, K, I.depth(), kern );
filter2D(src, dst, ddepth , kernel, anchor, delta, BORDER_DEFAULT );
- src: 源圖像
- dst: 目標圖像
- ddepth: dst 的深度。若為負值(如 -1),則表示其深度與源圖像相等。
- kernel: 用來遍歷圖像的核
- anchor: 核的錨點的相對位置,其中心點默認為 (-1, -1) 。
- delta: 在卷積過程中,該值會加到每個像素上。默認情況下,這個值為
。
- BORDER_DEFAULT: 這里我們保持其默認值,更多細節將在其他教程中詳解
形態學操作之:腐蝕與膨脹(Eroding and Dilating)
形態學操作就是基於形狀的一系列圖像處理操作。通過將 結構元素 作用於輸入圖像來產生輸出圖像。最基本的形態學操作有二:腐蝕與膨脹(Erosion 與 Dilation)。 他們的運用有:
- 消除噪聲
- 分割(isolate)獨立的圖像元素,以及連接(join)相鄰的元素。
- 尋找圖像中的明顯的極大值區域或極小值區域。
膨脹dilate
將圖像 與任意形狀的內核 (
),通常為正方形或圓形,進行卷積。內核
有一個可定義的 錨點, 通常定義為內核中心點。將內核
划過圖像,將內核
覆蓋區域的最大相素值提取,並代替錨點位置的相素。顯然,這一最大化操作將會導致圖像中的亮區開始”擴展” (因此有了術語膨脹 dilation )。
腐蝕erode
將內核 划過圖像,將內核
覆蓋區域的最小相素值提取,並代替錨點位置的相素。相應地,暗區會開始“腐蝕”。
Mat element = getStructuringElement( dilation_type, Size( 2*dilation_size + 1, 2*dilation_size+1 ), Point( dilation_size, dilation_size ) ); dilate( src, dilation_dst, element ); erode( src, erosion_dst, element );
dilate和erode參數相同:
- src: 原圖像
- erosion_dst: 輸出圖像
- element: 腐蝕操作的內核。如果不指定,默認為一個簡單的
矩陣。否則,我們就要明確指定它的形狀,可以使用函數getStructuringElement
- dilation_type = 矩形: MORPH_RECT 或者 交叉形: MORPH_CROSS 或者 橢圓形 MORPH_ELLIPSE
- 內核大小
- 錨點位置(若不指定,則默認為中心位置)
更多形態學變換
更直觀的圖參見此處。
開運算 (Opening)
通過先對圖像腐蝕再膨脹實現的。能夠排除小團塊物體(假設物體較背景明亮)。
閉運算(Closing)
通過先對圖像膨脹再腐蝕實現的。能夠排除小型黑洞(黑色區域)。
形態梯度(Morphological Gradient)
膨脹圖與腐蝕圖之差,能夠保留物體的邊緣輪廓。
頂帽(Top Hat)與黑帽(Black Hat)
頂帽:原圖像與開運算結果圖之差
黑帽:閉運算結果圖與原圖像之差
調用函數:morphologyEx
Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) ); /// 運行指定形態學操作 morphologyEx( src, dst, operation, element );
參數列表:
- src : 原 (輸入) 圖像
- dst: 輸出圖像
- operation: 需要運行的形態學操作。 我們有5個選項(注意:取值范圍為2~6):
- Opening: MORPH_OPEN : 2
- Closing: MORPH_CLOSE: 3
- Gradient: MORPH_GRADIENT: 4
- Top Hat: MORPH_TOPHAT: 5
- Black Hat: MORPH_BLACKHAT: 6
- element: 內核,可以使用函數:get_structuring_element:getStructuringElement <> 自定義。