OpenCV學習筆記(五)形態學操作:腐蝕、膨脹

一、形態學概述

我們圖像處理中指的形態學,往往表示的是數學形態學。下面一起來了解數學形態學的概念。
下面是來自百度百科對數學形態學的解釋:

數學形態學是由一組形態學的代數運算子組成的,它的基本運算有4個: 膨脹(或擴張)、腐蝕(或侵蝕)、開啟和閉合,它們在二值圖像灰度圖像中各有特點。基于這些基本運算還可推導和組合成各種數學形態學實用算法,用它們可以進行圖像形狀和結構的分析及處理,包括圖像分割特征抽取邊緣檢測圖像濾波圖像增強和恢復等。數學形態學方法利用一個稱作結構元素的“探針”收集圖像的信息,當探針在圖像中不斷移動時, 便可考察圖像各個部分之間的相互關系,從而了解圖像的結構特征。數學形態學基于探測的思想,與人的FOA(Focus Of Attention)的視覺特點有類似之處。作為探針的結構元素,可直接攜帶知識(形態、大小、甚至加入灰度和色度信息)來探測、研究圖像的結構特點。

本篇文章主要描述的是形態學操作中的膨脹、腐蝕。

膨脹與腐蝕能實現多種多樣的功能,主要如下:

  • 消除噪聲

  • 分割(isolate)出獨立的圖像元素,在圖像中連接(join)相鄰的元素。

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

  • 求出圖像的梯度

二、膨脹

其實,膨脹就是求局部最大值的操作。

按數學方面來說,膨脹或者腐蝕操作就是將圖像(或圖像的一部分區域,我們稱之為A)與核(我們稱之為B)進行卷積。

核可以是任何的形狀和大小,它擁有一個單獨定義出來的參考點,我們稱其為錨點(anchorpoint)。多數情況下,核是一個小的中間帶有參考點和實心正方形或者圓盤,其實,我們可以把核視為模板或者掩碼。

而膨脹就是求局部最大值的操作,核B與圖形卷積,即計算核B覆蓋的區域的像素點的最大值,并把這個最大值賦值給參考點指定的像素。這樣就會使圖像中的高亮區域逐漸增長。如下圖所示,這就是膨脹操作的初衷。


下面上一張膨脹運算的效果圖:

三、腐蝕

再來看一下腐蝕,大家應該知道,膨脹和腐蝕是一對好基友,是相反的一對操作,所以腐蝕就是求局部最小值的操作。

我們一般都會把腐蝕和膨脹對應起來理解和學習。下文就可以看到,兩者的函數原型也是基本上一樣的。

原理圖:

下面上一張腐蝕的效果圖:

四、API函數

接下來我們來看看OpenCV是用哪些函數實現這些運算的:

1.膨脹--dilate

使用像素鄰域內的局部極大運算符來膨脹一張圖片,從src輸入,由dst輸出。支持就地(in-place)操作。
函數原型:

void dilate(  
    InputArray src,  
    OutputArray dst,  
    InputArray kernel,  
    Point anchor=Point(-1,-1),  
    int iterations=1,  
    int borderType=BORDER_CONSTANT,  
    const Scalar& borderValue=morphologyDefaultBorderValue()   
);  

參數詳解:

  • 第一個參數,InputArray類型的src,輸入圖像,即源圖像,填Mat類的對象即可。圖像通道的數量可以是任意的,但圖像深度應為CV_8U,CV_16U,CV_16S,CV_32F或 CV_64F其中之一。
  • 第二個參數,OutputArray類型的dst,即目標圖像,需要和源圖片有一樣的尺寸和類型。
  • 第三個參數,InputArray類型的kernel,膨脹操作的核。若為NULL時,表示的是使用參考點位于中心3x3的核。
  • 第四個參數,Point類型的anchor,錨的位置,其有默認值(-1,-1),表示錨位于中心。
  • 第五個參數,int類型的iterations,迭代使用erode()函數的次數,默認值為1。
  • 第六個參數,int類型的borderType,用于推斷圖像外部像素的某種邊界模式。注意它有默認值BORDER_DEFAULT。
  • 第七個參數,const Scalar&類型的borderValue,當邊界為常數時的邊界值,有默認值morphologyDefaultBorderValue(),一般我們不用去管他。

我們一般使用函數 getStructuringElement配合這個參數的使用。getStructuringElement函數會返回指定形狀和尺寸的結構元素。

其中,getStructuringElement函數的第一個參數表示內核的形狀,我們可以選擇如下三種形狀之一:

  • 矩形: MORPH_RECT
  • 交叉形: MORPH_CROSS
  • 橢圓形: MORPH_ELLIPSE

而getStructuringElement函數的第二和第三個參數分別是內核的尺寸以及錨點的位置。

使用dilate函數,一般我們只需要填前面的三個參數,后面的四個參數都有默認值。
調用范例:

Mat img = imread("dog.jpg");
Mat out;
dilate(img, out, getStructuringElement(MORPH_RECT, Size(50, 50)));
2.膨脹--erode

使用像素鄰域內的局部極小運算符來腐蝕一張圖片,從src輸入,由dst輸出。支持就地(in-place)操作。
函數原型:

void erode(  
    InputArray src,  
    OutputArray dst,  
    InputArray kernel,  
    Point anchor=Point(-1,-1),  
    int iterations=1,  
    int borderType=BORDER_CONSTANT,  
    const Scalar& borderValue=morphologyDefaultBorderValue()  
 );  

參數詳解:

  • 第一個參數,InputArray類型的src,輸入圖像,即源圖像,填Mat類的對象即可。圖像通道的數量可以是任意的,但圖像深度應為CV_8U,CV_16U,CV_16S,CV_32F或 CV_64F其中之一。
  • 第二個參數,OutputArray類型的dst,即目標圖像,需要和源圖片有一樣的尺寸和類型。
  • 第三個參數,InputArray類型的kernel,腐蝕操作的內核。若為NULL時,表示的是使用參考點位于中心3x3的核。我們一般使用函數 getStructuringElement配合這個參數的使用。getStructuringElement函數會返回指定形狀和尺寸的結構元素(內核矩陣)。
  • 第四個參數,Point類型的anchor,錨的位置,其有默認值(-1,-1),表示錨位于單位(element)的中心,我們一般不用管它。
  • 第五個參數,int類型的iterations,迭代使用erode()函數的次數,默認值為1。
  • 第六個參數,int類型的borderType,用于推斷圖像外部像素的某種邊界模式。注意它有默認值BORDER_DEFAULT。
  • 第七個參數,const Scalar&類型的borderValue,當邊界為常數時的邊界值,有默認值morphologyDefaultBorderValue(),一般我們不用去管他。需要用到它時,可以看官方文檔中的createMorphologyFilter()函數得到更詳細的解釋。

同樣的,使用erode函數,一般我們只需要填前面的三個參數,后面的四個參數都有默認值。而且往往結合getStructuringElement一起使用。

調用范例:

Mat img = imread("dog.jpg");
Mat out;
erode(img, out, getStructuringElement(MORPH_RECT, Size(50, 50)));

五、開運算、閉運算

開運算,其實就是先腐蝕后膨脹的過程。反之閉運算就是先膨脹后腐蝕的過程。

開運算、閉運算的函數--morphologyEx

morphologyEx函數利用基本的膨脹和腐蝕技術(也能實現膨脹和腐蝕),來執行更加高級形態學變換,如開閉運算等操作。這一節我們來了解它的參數意義和使用方法。

void morphologyEx(  
InputArray src,  
OutputArray dst,  
int op,  
InputArraykernel,  
Pointanchor=Point(-1,-1),  
intiterations=1,  
intborderType=BORDER_CONSTANT,  
constScalar& borderValue=morphologyDefaultBorderValue() );  

參數詳解:

  • 第一個參數,InputArray類型的src,輸入圖像,即源圖像,填Mat類的對象即可。圖像位深應該為以下五種之一:CV_8U, CV_16U,CV_16S, CV_32F 或CV_64F。
  • 第二個參數,OutputArray類型的dst,即目標圖像,函數的輸出參數,需要和源圖片有一樣的尺寸和類型。
  • 第三個參數,int類型的op,表示形態學運算的類型,可以是如下之一的標識符:
  • MORPH_DILATE – 膨脹
  • MORPH_ERODE – 腐蝕
  • MORPH_OPEN – 開運算(Opening operation)
  • MORPH_CLOSE – 閉運算(Closing operation)
  • MORPH_GRADIENT -形態學梯度(Morphological gradient)
  • MORPH_TOPHAT - “頂帽”(“Top hat”)
  • MORPH_BLACKHAT - “黑帽”(“Black hat“)
  • 第四個參數,InputArray類型的kernel,形態學運算的內核。若為NULL時,表示的是使用參考點位于中心3x3的核。我們一般使用函數 getStructuringElement配合這個參數的使用。
  • 第五個參數,Point類型的anchor,錨的位置,其有默認值(-1,-1),表示錨位于中心。
  • 第六個參數,int類型的iterations,迭代使用函數的次數,默認值為1。
  • 第七個參數,int類型的borderType,用于推斷圖像外部像素的某種邊界模式。注意它有默認值BORDER_ CONSTANT。
  • 第八個參數,const Scalar&類型的borderValue,當邊界為常數時的邊界值,有默認值morphologyDefaultBorderValue(),一般我們不用去管他。需要用到它時,可以看官方文檔中的createMorphologyFilter()函數得到更詳細的解釋。

調用范例:


    Mat img = imread("dog.jpg");

    Mat out1,out2;

    Mat element = getStructuringElement(MORPH_RECT, Size(50, 50));

    morphologyEx(img, out1, MORPH_OPEN, element);
    morphologyEx(img, out2, MORPH_CLOSE, element);

    namedWindow("dog1", 2);
    imshow("dog1", out1);

    namedWindow("dog2", 2);
    imshow("dog2", out2);

    waitKey(0); 

這周的內容就是這些,下周見

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容