一、形態學概述
我們圖像處理中指的形態學,往往表示的是數學形態學。下面一起來了解數學形態學的概念。
下面是來自百度百科對數學形態學的解釋:
數學形態學是由一組形態學的代數運算子組成的,它的基本運算有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);
這周的內容就是這些,下周見