天天看點

OpenCV學習筆記(六) 濾波器 形态學操作(腐蝕、膨脹等)

OpenCV學習筆記(六) 濾波器 形态學操作(腐蝕、膨脹等)

轉自:OpenCV 教程

另附:計算機視覺:算法與應用(2012),Learning OpenCV(2009)

平滑圖像:濾波器

平滑 也稱 模糊, 是一項簡單且使用頻率很高的圖像處理方法。平滑處理的用途有很多, 但是在本教程中我們僅僅關注它減少噪聲的功用 (其他用途在以後的教程中會接觸到)。平滑處理時需要用到一個 濾波器 。最常用的濾波器是 線性 濾波器。不妨把 濾波器 想象成一個包含權重系數的視窗,當使用這個濾波器平滑處理圖像時,就把這個視窗滑過圖像。

歸一化濾波器 (Normalized Box Filter)

最簡單的濾波器,輸出像素值是核視窗内像素值的 均值 ( 所有像素權重系數相等)。

1

blur( src, dst, Size( i, i ), Point(-1,-1) );

src: 輸入圖像

dst: 輸出圖像

Size( w,h ): 定義核心大小( w 像素寬度, h 像素高度)

Point(-1, -1): 指定錨點位置(被平滑點), 如果是負值,取核的中心為錨點。

高斯濾波器 (Gaussian Filter)

最有用的濾波器 (盡管不是最快的)。 高斯濾波是将輸入數組的每一個像素點與 高斯核心 卷積将卷積和當作輸出像素值。

1

GaussianBlur( src, dst, Size( i, i ), 0, 0 );

src: 輸入圖像

dst: 輸出圖像

Size(w, h): 定義核心的大小(需要考慮的鄰域範圍)。 w 和 h 必須是正奇數,否則将使用 \sigma_{x} 和 \sigma_{y} 參數來計算核心大小。

\sigma_{x}: x 方向标準方差, 如果是 0 則 \sigma_{x} 使用核心大小計算得到。

\sigma_{y}: y 方向标準方差, 如果是 0 則 \sigma_{y} 使用核心大小計算得到。.

中值濾波器 (Median Filter)

中值濾波将圖像的每個像素用鄰域 (以目前像素為中心的正方形區域)像素的 中值 代替 。

1

medianBlur ( src, dst, i );

src: 輸入圖像

dst: 輸出圖像, 必須與 src 相同類型

i: 核心大小 (隻需一個值,因為我們使用正方形視窗),必須為奇數。

雙邊濾波 (Bilateral Filter)

目前我們了解的濾波器都是為了 平滑 圖像, 問題是有些時候這些濾波器不僅僅削弱了噪聲, 連帶着把邊緣也給磨掉了。為避免這樣的情形 (至少在一定程度上 ), 我們可以使用雙邊濾波。類似于高斯濾波器,雙邊濾波器也給每一個鄰域像素配置設定一個權重系數。 這些權重系數包含兩個部分, 第一部分權重方式與高斯濾波一樣,第二部分的權重則取決于該鄰域像素與目前像素的灰階內插補點。

詳細的解釋可以檢視 連結。

1

bilateralFilter ( src, dst, i, i*2, i/2 );

src: 輸入圖像

dst: 輸出圖像

d: 像素的鄰域直徑

\sigma_{Color}: 顔色空間的标準方差

\sigma_{Space}: 坐标空間的标準方差(像素機關)

利用掩碼(kernel mask)簡單濾波:filter2D

矩陣的掩碼操作很簡單。其思想是:根據掩碼矩陣(也稱作核)重新計算圖像中每個像素的值。掩碼矩陣中的值表示近鄰像素值(包括該像素自身的值)對新像素值有多大影響。從數學觀點看,我們用自己設定的權值,對像素鄰域内的值做了個權重平均。

以下是利用filter2D函數實作Laplace filter來加強圖像對比度的執行個體(samples\cpp\tutorial_code\core\mat_mask_operations):

1

2

3

4

Mat kern = (Mat_(3,3) << 0, -1, 0,

-1, 5, -1,

0, -1, 0);

filter2D(I, K, I.depth(), kern );

1

filter2D(src, dst, ddepth , kernel, anchor, delta, BORDER_DEFAULT );

src: 源圖像

dst: 目标圖像

ddepth: dst 的深度。若為負值(如 -1),則表示其深度與源圖像相等。

kernel: 用來周遊圖像的核

anchor: 核的錨點的相對位置,其中心點預設為 (-1, -1) 。

delta: 在卷積過程中,該值會加到每個像素上。預設情況下,這個值為 0 。

BORDER_DEFAULT: 這裡我們保持其預設值,更多細節将在其他教程中詳解

形态學操作之:腐蝕與膨脹(Eroding and Dilating)

形态學操作就是基于形狀的一系列圖像處理操作。通過将 結構元素 作用于輸入圖像來産生輸出圖像。最基本的形态學操作有二:腐蝕與膨脹(Erosion 與 Dilation)。 他們的運用有:

消除噪聲

分割(isolate)獨立的圖像元素,以及連接配接(join)相鄰的元素。

尋找圖像中的明顯的極大值區域或極小值區域。

膨脹dilate

将圖像 A 與任意形狀的核心 (B),通常為正方形或圓形,進行卷積。核心 B 有一個可定義的 錨點, 通常定義為核心中心點。将核心 B 劃過圖像,将核心 B 覆寫區域的最大相素值提取,并代替錨點位置的相素。顯然,這一最大化操作将會導緻圖像中的亮區開始”擴充” (是以有了術語膨脹 dilation )。

腐蝕erode

将核心 B 劃過圖像,将核心 B 覆寫區域的最小相素值提取,并代替錨點位置的相素。相應地,暗區會開始“腐蝕”。

1

2

3

4

5

6

Mat element = getStructuringElement( dilation_type,

Size( 2dilation_size + 1, 2dilation_size+1 ),

Point( dilation_size, dilation_size ) );

dilate( src, dilation_dst, element );

erode( src, erosion_dst, element );

dilate和erode參數相同:

src: 原圖像

erosion_dst: 輸出圖像

element: 腐蝕操作的核心。如果不指定,預設為一個簡單的 3x3 矩陣。否則,我們就要明确指定它的形狀,可以使用函數getStructuringElement

getStructuringElement的參數:

dilation_type = 矩形: MORPH_RECT 或者 交叉形: MORPH_CROSS 或者 橢圓形 MORPH_ELLIPSE

核心大小

錨點位置(若不指定,則預設為中心位置)

更多形态學變換

更直覺的圖參見此處。

開運算 (Opening)

通過先對圖像腐蝕再膨脹實作的。能夠排除小團塊物體(假設物體較背景明亮)。

dst = open( src, element) = dilate( erode( src, element ) )

閉運算(Closing)

通過先對圖像膨脹再腐蝕實作的。能夠排除小型黑洞(黑色區域)。

dst = close( src, element ) = erode( dilate( src, element ) )

形态梯度(Morphological Gradient)

膨脹圖與腐蝕圖之差,能夠保留物體的邊緣輪廓。

頂帽(Top Hat)與黑帽(Black Hat)

頂帽:原圖像與開運算結果圖之差

dst = tophat( src, element ) = src - open( src, element )

黑帽:閉運算結果圖與原圖像之差

dst = blackhat( src, element ) = close( src, element ) - src

調用函數:morphologyEx

1

2

3

4

Mat element = getStructuringElement( morph_elem, Size( 2morph_size + 1, 2morph_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 <> 自定義。

繼續閱讀