OPENCV形態學操作1


形態學操作是指基於形狀的一系列圖像處理操作,包括膨脹,腐蝕,二值化,開運算,閉運算,頂帽算法,黑帽算法,形態學梯度等,最基本的形態學操作就是膨脹和腐蝕.

一.膨脹

         首先需要明確一個概念,膨脹和腐蝕都是針對於圖像中較亮的區域而言的,膨脹就是亮的區域變多了,而腐蝕就是暗的區域變多了.

         膨脹的功能主要有消除噪聲,分割出獨立的圖像元素,在圖像操作的時候,有時候需要對圖像中的某些形狀進行檢測,而這些形狀相互連接在一起,不好分開檢測,膨脹就能切開這些形狀(很小的連接位置),或者圖像中有很小塊的黑斑,或許是相機上的影響,膨脹,也能消除這些小的黑斑

         膨脹的基本思路就是圖像與一個核函數進行卷積,並取出結果中的極大值作為結果,使得圖像中的高亮區域增長.這個核的形狀,錨點都可以進行設置,OPENCV提供了API供我們獲得核.

         API:Mat getStructuringElement(int 內核形狀,Size 內核尺寸,Point 錨點位置)

         注:內核形狀可以取方形MORPH_RECT,十字形MORPH_CROSS,橢圓形MORPH_ELLIPSE

                  錨點位置默認值Point(-1,-1),取形狀的中心

         通過該API就可以獲得相應的計算核,接下來計算膨脹的函數為

         API:void dilate(源圖像,目標圖像,膨脹核,錨點,int 迭代次數,int邊界模式,int 邊界為常數時邊界值)

         注:該API支持in_place(源圖像可以做目的圖像參數,算法會修改源圖像內數據),迭代次數默認為1

例子如下

Mat srcImage;
//膨脹
const int g_dilateIterMax = 100;//迭代次數
int g_nDilateIterValue;
const int g_dilateCoreMax = 100;//核大小
int g_nDilateCoreValue;
Mat dilateImage;
void OnDilateIterTrackbar(int pos,void* userData);
void onDilateCoreSizeTrackBar(int pos,void* userData);

int main(int argc,char* argv)
{
	srcImage = imread("F:\\opencv\\OpenCVImage\\erode_dilate.jpg");
	namedWindow("src image");
	namedWindow("dilate image");

	g_nDilateIterValue = 1;
	g_nDilateCoreValue = 5;
	createTrackbar("inter count", "dilate image", &g_nDilateIterValue, g_dilateIterMax,OnDilateIterTrackbar);
	createTrackbar("core size", "dilate image", &g_nDilateCoreValue, g_dilateCoreMax,onDilateCoreSizeTrackBar);
	OnDilateIterTrackbar(g_nDilateIterValue,0);

	moveWindow("src image", 0, 0);
	moveWindow("dilate image", srcImage.cols, 0);

	imshow("src image", srcImage);

	waitKey(0);
	return 0;	
}

//調整迭代次數
void OnDilateIterTrackbar(int pos,void* userData)
{
   if(pos == 0||g_nDilateCoreValue == 0)
   {
       imshow("dilate image", srcImage);
   }
   else
   {
       if(g_nDilateCoreValue%2 == 0)
       {
           g_nDilateCoreValue++;
       }
       Mat core = getStructuringElement(MORPH_RECT, Size(g_nDilateCoreValue,g_nDilateCoreValue));
       dilate(srcImage, dilateImage, core,Point(-1,-1),g_nDilateIterValue);
       imshow("dilate image", dilateImage);
   }
}

//調整核大小
void onDilateCoreSizeTrackBar(int pos,void* userData)
{
   if(pos == 0 || g_nDilateIterValue == 0)
   {
       imshow("dilate image", srcImage);
   }
   else
   {
       if(g_nDilateCoreValue%2 == 0)
       {
           g_nDilateCoreValue++;
       }
       Mat core = getStructuringElement(MORPH_RECT, Size(g_nDilateCoreValue,g_nDilateCoreValue));
       dilate(srcImage, dilateImage, core,Point(-1,-1),g_nDilateIterValue);
       imshow("dilate image", dilateImage);
   }
}

  

二.腐蝕

         腐蝕與膨脹正好相反,是求局部最小值的操作,亮的地方會減少,黑的地方會增多,在圖像中連接接近的區域,消除高亮造成的噪聲

         API: void erode(源,目的,核,錨點,迭代次數,邊緣類型,邊緣為常數時邊界值);

         注:腐蝕和膨脹API的形式一致

使用代碼

//腐蝕
Mat srcImage;
const int g_erodeIterMax = 100;
int g_nErodeIterValue;
const int g_erodeCoreMax = 100;
int g_nErodeCoreValue;
Mat erodeImage;
void OnErodeIterTrackbar(int pos,void* userData);
void onErodeCoreSizeTrackBar(int pos,void* userData);

int main(int argc,char* argv)

{
	srcImage = imread("F:\\opencv\\OpenCVImage\\erode_dilate.jpg");
	namedWindow("src image");
    namedWindow("erode image");

   g_nErodeIterValue = 1;
   g_nErodeCoreValue = 5;
   createTrackbar("inter count", "erode image", &g_nErodeIterValue, g_erodeIterMax,OnErodeIterTrackbar);
   createTrackbar("core size", "erode image", &g_nErodeCoreValue, g_erodeCoreMax,onErodeCoreSizeTrackBar);
   OnErodeIterTrackbar(g_nErodeIterValue, 0);

	moveWindow("src image", 0, 0);
    moveWindow("erode image", srcImage.cols, 0);

	imshow("src image", srcImage);
	waitKey(0);
	return 0;	

}

//調整迭代次數
void OnErodeIterTrackbar(int pos,void* userData)
{
   if(pos == 0 || g_nErodeCoreValue == 0)
   {
       imshow("erode image", srcImage);
   }
   else
   {
       if(g_nErodeCoreValue%2 == 0)
       {
           g_nErodeCoreValue++;
       }
       Mat core = getStructuringElement(MORPH_RECT, Size(g_nErodeCoreValue,g_nErodeCoreValue),Point(-1,-1));
       erode(srcImage, erodeImage, core,Point(-1,-1),g_nErodeIterValue);
       imshow("erode image", erodeImage);
   }
}
//調整核大小
void onErodeCoreSizeTrackBar(int pos,void* userData)
{
   if(pos == 0 || g_nErodeIterValue == 0)
   {
       imshow("erode image", srcImage);
   }
   else
   {
       if(g_nErodeCoreValue%2 == 0)
       {
           g_nErodeCoreValue++;
       }
       Mat core = getStructuringElement(MORPH_RECT, Size(g_nErodeCoreValue,g_nErodeCoreValue),Point(-1,-1));
       erode(srcImage, erodeImage, core,Point(-1,-1),g_nErodeIterValue);
       imshow("erode image", erodeImage);
   }
}

  

三.形態學濾波算法

         形態學的高級操作,往往都建立在基礎的膨脹和腐蝕的操作之上

         1.開運算:開運算是一個先腐蝕,后膨脹的過程,用於在圖像中消除小的物體,在纖細點處分離物體,在平滑化較大的物體的邊界的同時不明顯改變物體的體積.

         2.閉運算:先膨脹后腐蝕的過程,能夠用於消除物體中的小型黑洞

         3.形態學梯度:膨脹圖和腐蝕圖之差,對二值圖像進行這一操作,可以將團塊的邊緣突出來,可以使用形態學梯度來保留物體的邊緣輪廓.

         4.頂帽:源圖像和開運算的結果的差值,往往用來分離比鄰近點亮一點的斑塊,在一幅圖具體大幅的背景,而微小物體有比較有規律的情況下,可以使用top_hat運算進行背景的提取

         5.黑帽:閉運算的結果與源圖像之差,突出了比源圖像輪廓周圍更暗的區域,往往用於分離比鄰近點暗一些的斑塊.

         核心API:void morpholgyEx(源,目標,int 形態學操作標志,mat 形態學操作內核,Point 錨點,int 迭代次數,int 邊界模式,int 邊界為常數時的邊界值).

         注:形態學操作標志的取值如下:MORPH_OPEN開運算  MORPH_CLOSE 閉運算 MORPH_GRENIENT 形態學梯度 MORPH_TOPHAT頂帽 MORPH_BLACKHAT黑帽 MORPH_ERODE腐蝕 MORPH_DILATE 膨脹

                  形態學操作內核就是前面膨脹腐蝕使用的內核.

使用范例如下:

1.開運算 閉運算 形態學梯度三者聯合

//源¡ä圖ª?像?
Mat srcImage;

//開a運?算?
const int g_openIterMax = 100;
int g_nopenIterValue;
const int g_openCoreMax = 100;
int g_nopenCoreValue;
Mat openImage;
void OnopenIterTrackbar(int pos,void* userData);
void onopenCoreSizeTrackBar(int pos,void* userData);

//閉À?運?算?
const int g_closeIterMax = 100;
int g_ncloseIterValue;
const int g_closeCoreMax = 100;
int g_ncloseCoreValue;
Mat closeImage;
void OncloseIterTrackbar(int pos,void* userData);
void oncloseCoreSizeTrackBar(int pos,void* userData);

//形?態¬?學¡ì梯¬Y度¨¨
const int g_gredientIterMax = 100;
int g_ngredientIterValue;
const int g_gredientCoreMax = 100;
int g_ngredientCoreValue;
Mat gredientImage;
void OngredientIterTrackbar(int pos,void* userData);
void ongredientCoreSizeTrackBar(int pos,void* userData);


int main(int argc,char* argv[])
{
   srcImage = imread("F:\\opencv\\OpenCVImage\\morpholgy.jpg");
   
   g_nopenIterValue = 1;
   g_nopenCoreValue = 5;
   namedWindow("open image");
   createTrackbar("iter count", "open image", &g_nopenIterValue, g_openIterMax,OnopenIterTrackbar,0);
   createTrackbar("core size", "open image", &g_nopenCoreValue, g_openCoreMax,onopenCoreSizeTrackBar,0);
   onopenCoreSizeTrackBar(g_nopenCoreValue, 0);
   
   g_ncloseCoreValue = 5;
   g_ncloseIterValue = 1;
   namedWindow("close image");
   createTrackbar("iter count", "close image", &g_ncloseIterValue, g_closeIterMax,OncloseIterTrackbar,0);
   createTrackbar("core size", "close image", &g_ncloseCoreValue, g_closeCoreMax,oncloseCoreSizeTrackBar,0);
   oncloseCoreSizeTrackBar(g_ncloseCoreValue, 0);
   
   g_ngredientCoreValue = 5;
   g_ngredientIterValue = 1;
   namedWindow("gredient image");
   createTrackbar("iter count", "gredient image", &g_ngredientIterValue, g_gredientIterMax,OngredientIterTrackbar,0);
   createTrackbar("core size", "gredient image", &g_ngredientCoreValue, g_gredientCoreMax,OngredientIterTrackbar,0);
   OngredientIterTrackbar(g_ngredientIterValue, 0);
   
   imshow("src image", srcImage);
  
   moveWindow("src image", 0, 0);
   moveWindow("open image", srcImage.cols, 0);
   moveWindow("close image", srcImage.cols*2, 0);
   moveWindow("gredient image", srcImage.cols*3, 0);
   
   waitKey(0);
   return 0;
}

void OnopenIterTrackbar(int pos,void* userData)
{
   if(g_nopenCoreValue == 0||g_nopenIterValue == 0)
   {
       imshow("open image", srcImage);
   }
   else
   {
       if(g_nopenCoreValue%2 == 0)
           g_nopenCoreValue++;
       Mat core = getStructuringElement(MORPH_RECT, Size(g_nopenCoreValue,g_nopenCoreValue));
       morphologyEx(srcImage, openImage, MORPH_OPEN, core,Point(-1,-1),g_nopenIterValue);
       imshow("open image", openImage);
   }
}
void onopenCoreSizeTrackBar(int pos,void* userData)
{
   if(g_nopenCoreValue == 0||g_nopenIterValue == 0)
   {
       imshow("open image", srcImage);
   }
   else
   {
       if(g_nopenCoreValue%2 == 0)
           g_nopenCoreValue++;
       Mat core = getStructuringElement(MORPH_RECT, Size(g_nopenCoreValue,g_nopenCoreValue));
       morphologyEx(srcImage, openImage, MORPH_OPEN, core,Point(-1,-1),g_nopenIterValue);
       imshow("open image", openImage);
   }
}
void OncloseIterTrackbar(int pos,void* userData)
{
   if(g_ncloseCoreValue == 0||g_ncloseIterValue == 0)
   {
       imshow("close image", srcImage);
   }
   else
   {
       if(g_ncloseCoreValue%2 == 0)
           g_ncloseCoreValue++;
       Mat core = getStructuringElement(MORPH_RECT, Size(g_ncloseCoreValue,g_ncloseCoreValue));
       morphologyEx(srcImage, closeImage, MORPH_CLOSE, core,Point(-1,-1),g_ncloseIterValue);
       imshow("close image", closeImage);
   }
}
void oncloseCoreSizeTrackBar(int pos,void* userData)
{
   if(g_ncloseCoreValue == 0||g_ncloseIterValue == 0)
   {
       imshow("close image", srcImage);
   }
   else
   {
       if(g_ncloseCoreValue%2 == 0)
           g_ncloseCoreValue++;
       Mat core = getStructuringElement(MORPH_RECT, Size(g_ncloseCoreValue,g_ncloseCoreValue));
       morphologyEx(srcImage, closeImage, MORPH_CLOSE, core,Point(-1,-1),g_ncloseIterValue);
       imshow("close image", closeImage);
   }
}
void OngredientIterTrackbar(int pos,void* userData)
{
   if(g_ngredientCoreValue == 0||g_ngredientIterValue == 0)
   {
       imshow("gredient image", srcImage);
   }
   else
   {
       if(g_ngredientCoreValue%2 == 0)
           g_ngredientCoreValue++;
       Mat core = getStructuringElement(MORPH_RECT, Size(g_ngredientCoreValue,g_ngredientCoreValue));
       morphologyEx(srcImage, gredientImage, MORPH_GRADIENT, core,Point(-1,-1),g_ngredientIterValue);
       imshow("gredient image", gredientImage);
   }
}
void ongredientCoreSizeTrackBar(int pos,void* userData)
{
   if(g_ngredientCoreValue == 0||g_ngredientIterValue == 0)
   {
       imshow("gredient image", srcImage);
   }
   else
   {
       if(g_ngredientCoreValue%2 == 0)
           g_ngredientCoreValue++;
       Mat core = getStructuringElement(MORPH_RECT, Size(g_ngredientCoreValue,g_ngredientCoreValue));
       morphologyEx(srcImage, gredientImage, MORPH_GRADIENT, core,Point(-1,-1),g_ngredientIterValue);
       imshow("gredient image", gredientImage);
   }
}

  

2. 頂帽 黑帽結合

Mat srcImage;

//頂£¤帽¡À tophat
const int g_tophatIterMax = 100;
int g_ntophatIterValue;
const int g_tophatCoreMax = 100;
int g_ntophatCoreValue;
Mat tophatImage;
void OntophatIterTrackbar(int pos,void* userData);
void ontophatCoreSizeTrackBar(int pos,void* userData);

//黑¨²帽¡À
const int g_blackhatIterMax = 100;
int g_nblackhatIterValue;
const int g_blackhatCoreMax = 100;
int g_nblackhatCoreValue;
Mat blackhatImage;
void OnblackhatIterTrackbar(int pos,void* userData);
void onblackhatCoreSizeTrackBar(int pos,void* userData);


int main(int argc,char* argv[])
{
   srcImage = imread("F:\\opencv\\OpenCVImage\\morpholgy.jpg");
   
   g_ntophatIterValue = 1;
   g_ntophatCoreValue = 5;
   namedWindow("tophat image");
   createTrackbar("iter count", "tophat image", &g_ntophatIterValue, g_tophatIterMax,OntophatIterTrackbar,0);
   createTrackbar("core size", "tophat image", &g_ntophatCoreValue, g_tophatCoreMax,ontophatCoreSizeTrackBar,0);
   ontophatCoreSizeTrackBar(g_ntophatCoreValue, 0);
   
   g_nblackhatCoreValue = 5;
   g_nblackhatIterValue = 1;
   namedWindow("blackhat image");
   createTrackbar("iter count", "blackhat image", &g_nblackhatIterValue, g_blackhatIterMax,OnblackhatIterTrackbar,0);
   createTrackbar("core size", "blackhat image", &g_nblackhatCoreValue, g_blackhatCoreMax,onblackhatCoreSizeTrackBar,0);
   onblackhatCoreSizeTrackBar(g_nblackhatCoreValue, 0);
   
   imshow("src image", srcImage);
   
   moveWindow("src image", 0, 0);
   moveWindow("tophat image", srcImage.cols, 0);
   moveWindow("blackhat image", srcImage.cols*2, 0);
   
   waitKey(0);
   return 0;
}

void OntophatIterTrackbar(int pos,void* userData)
{
   if(g_ntophatCoreValue == 0||g_ntophatIterValue == 0)
   {
       imshow("tophat image", srcImage);
   }
   else
   {
       if(g_ntophatCoreValue%2 == 0)
           g_ntophatCoreValue++;
       Mat core = getStructuringElement(MORPH_RECT, Size(g_ntophatCoreValue,g_ntophatCoreValue));
       morphologyEx(srcImage, tophatImage, MORPH_TOPHAT, core,Point(-1,-1),g_ntophatIterValue);
       imshow("tophat image", tophatImage);
   }
}
void ontophatCoreSizeTrackBar(int pos,void* userData)
{
   if(g_ntophatCoreValue == 0||g_ntophatIterValue == 0)
   {
       imshow("tophat image", srcImage);
   }
   else
   {
       if(g_ntophatCoreValue%2 == 0)
           g_ntophatCoreValue++;
       Mat core = getStructuringElement(MORPH_RECT, Size(g_ntophatCoreValue,g_ntophatCoreValue));
       morphologyEx(srcImage, tophatImage, MORPH_TOPHAT, core,Point(-1,-1),g_ntophatIterValue);
       imshow("tophat image", tophatImage);
   }
}


void OnblackhatIterTrackbar(int pos,void* userData)
{
   if(g_nblackhatCoreValue == 0||g_nblackhatIterValue == 0)
   {
       imshow("blackhat image", srcImage);
   }
   else
   {
       if(g_nblackhatCoreValue%2 == 0)
           g_nblackhatCoreValue++;
       Mat core = getStructuringElement(MORPH_RECT, Size(g_nblackhatCoreValue,g_nblackhatCoreValue));
       morphologyEx(srcImage, blackhatImage, MORPH_BLACKHAT, core,Point(-1,-1),g_nblackhatIterValue);
       imshow("blackhat image", blackhatImage);
   }
}
void onblackhatCoreSizeTrackBar(int pos,void* userData)
{
   if(g_nblackhatCoreValue == 0||g_nblackhatIterValue == 0)
   {
       imshow("blackhat image", srcImage);
   }
   else
   {
       if(g_nblackhatCoreValue%2 == 0)
           g_nblackhatCoreValue++;
       Mat core = getStructuringElement(MORPH_RECT, Size(g_nblackhatCoreValue,g_nblackhatCoreValue));
       morphologyEx(srcImage, blackhatImage, MORPH_BLACKHAT, core,Point(-1,-1),g_nblackhatIterValue);
       imshow("blackhat image", blackhatImage);
   }
}

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM