OpenCV形態學操作

来源:互联网 发布:ecshop淘宝客采集插件 编辑:程序博客网 时间:2024/06/02 05:00

http://blog.csdn.net/byxdaz/article/details/5775717

OpenCV形態學操作

 

一、圖像腐蝕 膨脹 細化的基本原理

1.圖像細化的基本原理
⑴ 圖像形態學處理的概念
數字圖像處理中的形態學處理是指將數字形態學作為工具從圖像中提取對於表達和描繪區域形狀有用處的圖像分量,比如邊界、骨架以及凸殼,還包括用於預處理或後處理的形態學過濾、細化和修剪等。圖像形態學處理中我們感興趣的主要是二值圖像。
在二值圖像中,所有黑色像素的集合是圖像完整的形態學描述,二值圖像的各個分量是Z2的元素。假定二值圖像A和形態學處理的結構元素B是定義在笛卡兒網格上的集合,網格中值為1的點是集合的元素,當結構元素的原點移到點(x,y)時,記為Sxy,為簡單起見,結構元素為3x3,且全都為1,在這種限制下,決定輸出結果的是邏輯運算。 

⑵ 二值圖像的邏輯運算
邏輯運算盡管本質上很簡單,但對於實現以形態學為基礎額圖像處理算法是一種有力的補充手段。在圖像處理中用到的主要邏輯運算是:與、或和非(求補),它們可以互相組合形成其他邏輯運算。

⑶ 膨脹和腐蝕
膨脹和腐蝕這兩種操作是形態學處理的基礎,許多形態學算法都是以這兩種運算為基礎的。
① 膨脹
是以得到B的相對與它自身原點的映像並且由z對映像進行移位為基礎的。A被B膨脹是所有位移z的集合,這樣, 和A至少有一個元素是重疊的。我們可以把上式改寫為: 
結構元素B可以看作一個卷積模板,區別在於膨脹是以集合運算為基礎的,卷積是以算術運算為基礎的,但兩者的處理過程是相似的。
⑴ 用結構元素B,掃描圖像A的每一個像素
⑵ 用結構元素與其覆蓋的二值圖像做「與」操作
⑶ 如果都為0,結果圖像的該像素為0。否則為1

② 腐蝕
對Z中的集合A和B,B對A進行腐蝕的整個過程如下: 
⑴ 用結構元素B,掃描圖像A的每一個像素
⑵ 用結構元素與其覆蓋的二值圖像做「與」操作
⑶ 如果都為1,結果圖像的該像素為1。否則為0
腐蝕處理的結果是使原來的二值圖像減小一圈。

⑷ 擊中(匹配)或擊不中變換
假設集合A是由3個子集X,Y和Z組成的集合,擊中(匹配)的目的是要在A中找到X的位置,我們設X被包圍在一個小窗口W中,與W有關的X的局部背景定義為集合的差(W-X),則X在A內能得到精確擬合位置集合是由X對A的腐蝕後由(W-X)對A的補集Ac腐蝕的交集,這個交集就是我們要找的位置,我們用集合B來表示由X和X的背景構成的集合,我們可以令B=(B1,B2),這裡B1=X,B2=(W-X),則在A中對B進行匹配可以表示為:
A⊙B 
我們稱為形態學上的擊中或擊不中變換。

 

⑸ 開閉操作
開操作是先腐蝕、後膨脹處理。

閉操作是先膨脹、後腐蝕處理。

 

(6) 細化
圖像細化一般作為一種圖像預處理技術出現,目的是提取源圖像的骨架,即是將原圖像中線條寬度大於1個像素的線條細化成只有一個像素寬,形成「骨架」,形成骨架後能比較容易的分析圖像,如提取圖像的特征。
細化基本思想是「層層剝奪」,即從線條邊緣開始一層一層向裡剝奪,直到線條剩下一個像素的為止。圖像細化大大地壓縮了原始圖像地數據量,並保持其形狀的基本拓撲結構不變,從而為文字識別中的特征抽取等應用奠定了基礎。細化算法應滿足以下條件:
① 將條形區域變成一條薄線;
② 薄線應位與原條形區域的中心;
③ 薄線應保持原圖像的拓撲特性。
細化分成串行細化和並行細化,串行細化即是一邊檢測滿足細化條件的點,一邊刪除細化點;並行細化即是檢測細化點的時候不進行點的刪除只進行標記,而在檢測完整幅圖像後一次性去除要細化的點。
常用的圖像細化算法有hilditch算法,pavlidis算法和rosenfeld算法等。
注:進行細化算法前要先對圖像進行二值化,即圖像中只包含「黑」和「白」兩種顏色。

具體詳細的圖像形態學資料參考:http://wenku.baidu.com/view/1923d18fcc22bcd126ff0ccc.html

 

二、OpenCv形態學操作相關函數

1、MorphologyEx         高級形態學變換

void cvMorphologyEx( const CvArr* src, CvArr* dst, CvArr* temp,
IplConvKernel* element, int operation, int iterations=1 );
src 
輸入圖像. 
dst 
輸出圖像. 
temp 
臨時圖像,某些情況下需要 
element 
結構元素 
operation 
形態操作的類型: 
CV_MOP_OPEN - 開運算 
CV_MOP_CLOSE - 閉運算 
CV_MOP_GRADIENT - 形態梯度 
CV_MOP_TOPHAT - "頂帽" 
CV_MOP_BLACKHAT - "黑帽" 
iterations 
膨脹和腐蝕次數. 
函數 cvMorphologyEx 在膨脹和腐蝕基本操作的基礎上,完成一些高級的形態變換: 

開運算
dst=open(src,element)=dilate(erode(src,element),element) 
閉運算
dst=close(src,element)=erode(dilate(src,element),element) 
形態梯度 
dst=morph_grad(src,element)=dilate(src,element)-erode(src,element) 
"頂帽"
dst=tophat(src,element)=src-open(src,element) 
"黑帽"
dst=blackhat(src,element)=close(src,element)-src 
臨時圖像 temp 在形態梯度以及對「頂帽」和「黑帽」操作時的 in-place 模式下需要。

2、Dilate    使用任意結構元素膨脹圖像

void cvDilate( const CvArr* src, CvArr* dst, IplConvKernel* element=NULL, int iterations=1 );
src 
輸入圖像. 
dst 
輸出圖像. 
element 
用於膨脹的結構元素。若為 NULL, 則使用 3×3 長方形的結構元素 
iterations 
膨脹的次數 
函數 cvDilate 對輸入圖像使用指定的結構元進行膨脹,該結構決定每個具有最小值象素點的鄰域形狀: 
dst=dilate(src,element): dst(x,y)=max((x',y') in element))src(x+x',y+y')
函數支持(in-place)模式。膨脹可以重復進行 (iterations) 次. 對彩色圖像,每個彩色通道單獨處理。

3、Erode    使用任意結構元素腐蝕圖像

void cvErode( const CvArr* src, CvArr* dst, IplConvKernel* element=NULL, int iterations=1 );
src 
輸入圖像. 
dst 
輸出圖像. 
element 
用於腐蝕的結構元素。若為 NULL, 則使用 3×3 長方形的結構元素 
iterations 
腐蝕的次數 
函數 cvErode 對輸入圖像使用指定的結構元素進行腐蝕,該結構元素決定每個具有最小值象素點的鄰域形狀: 
dst=erode(src,element): dst(x,y)=min((x',y') in element))src(x+x',y+y')
函數可能是本地操作,不需另外開辟存儲空間的意思。腐蝕可以重復進行 (iterations) 次. 對彩色圖像,每個彩色通道單獨處理。

注:CreateStructuringElementEx  創建結構元素;ReleaseStructuringElement 刪除結構元素。

 

三、OpenCv形態學實例代碼:

1、腐蝕、膨脹、開運算、閉運算

內容參考:http://blog.csdn.net/gnuhpc/archive/2009/06/21/4286177.aspx

/******************************* 

數學形態運算,最常見的基本運算有七種, 

分別為:腐蝕、膨脹、開運算、閉運算、擊中、細化和粗化, 

它們是全部形態學的基礎。 

********************************/ 

#include "cv.h"  

#include "highgui.h"  

#include <stdlib.h>  

#include <stdio.h>  

IplImage *src=0;  

IplImage *dst=0;  

IplConvKernel *element=0;//聲明一個結構元素  

int element_shape=CV_SHAPE_RECT;//長方形形狀的元素  

int max_iters=10;  

int open_close_pos=0;  

int erode_dilate_pos=0;  

void OpenClose(int pos)  

{  

    int n=open_close_pos-max_iters;  

    int an=n>0?n:-n;  

    element = cvCreateStructuringElementEx(an*2+1,   an*2+1,an,an,element_shape,0);//創建結構元素  

     

    if (n<0)  

    {  

        cvErode(src,dst,element,1);//腐蝕圖像  

        cvDilate(dst,dst,element,1);//膨脹圖像  

    }  

    else 

    {         

        cvDilate(dst,dst,element,1);//膨脹圖像  

        cvErode(src,dst,element,1);//腐蝕圖像  

    }  

    cvReleaseStructuringElement(&element);  

    cvShowImage("Open/Close",dst);  

}  

void ErodeDilate(int pos)  

{  

    int n=erode_dilate_pos-max_iters;  

    int an=n>0?n:-n;  

    element = cvCreateStructuringElementEx(an*2+1,an*2+1,an,an,element_shape,0);  

    if (n<0)  

    {  

        cvErode(src,dst,element,1);  

    }  

    else 

    {  

        cvDilate(src,dst,element,1);  

    }  

    cvReleaseStructuringElement(&element);  

    cvShowImage("Erode/Dilate",dst);  

}  

int main(int argc,char **argv)  

{  

    char *filename =argc ==2?argv[1]:(char *)"lena.jpg";      

    if( (src = cvLoadImage(filename,1)) == 0 )  

        return -1;  

    dst=cvCloneImage(src);  

    cvNamedWindow("Open/Close",1);  

    cvNamedWindow("Erode/Dilate",1);  

    open_close_pos = erode_dilate_pos = max_iters;  

    cvCreateTrackbar("iterations","Open/Close",&open_close_pos,max_iters*2+1,OpenClose);  

    cvCreateTrackbar("iterations","Erode/Dilate",&erode_dilate_pos,max_iters*2+1,ErodeDilate);  

    for (;;)  

    {  

        int c;  

        OpenClose(open_close_pos);  

        ErodeDilate(erode_dilate_pos);  

        c= cvWaitKey(0);  

        if (c==27)  

        {  

            break;  

        }  

        switch(c) {  

        case 'e':  

            element_shape=CV_SHAPE_ELLIPSE;  

            break;  

        case 'r':  

            element_shape=CV_SHAPE_RECT;  

            break;  

        case '/r':  

            element_shape=(element_shape+1)%3;  

            break;  

        default:  

            break;   

        }  

    }  

    cvReleaseImage(&src);  

    cvReleaseImage(&dst);  

     

    cvDestroyWindow("Open/Close");  

    cvDestroyWindow("Erode/Dilate");  

    return 0;  

}  

/***************************** 

腐蝕和膨脹,看上去好像是一對互逆的操作,實際上,這兩種操作不具有互逆的關系。 

開運算和閉運算正是依據腐蝕和膨脹的不可逆性,演變而來的。 

先腐蝕後膨脹的過程就稱為開運算。 

閉運算是通過對腐蝕和膨脹的另一種不同次序的執行而得到的, 

閉運算是先膨脹後腐蝕的過程,其功能是用來填充物體內細小空洞、連接鄰近物體、平滑其邊界, 

同時不明顯改變不明顯改變其面積。 

******************************/ 

2、opencv實現二值圖像細化

內容參考:http://blog.csdn.net/byxdaz/archive/2010/06/02/5642669.aspx


原创粉丝点击