《【OpenCV入門指南】第三篇Canny邊緣檢測》中介紹了邊緣檢測,本篇介紹輪廓檢測,輪廓檢測的原理通俗的說就是掏空內(nèi)部點,比如原圖中有3*3的矩形點。那么就可以將中間的那一點去掉。
???????在OpenCV中使用輪廓檢測是非常方便。直接使用cvFindContours函數(shù)就能完成對圖像輪廓的檢測。下面就來看看這個函數(shù)的用法。
《OpenCV入門指南》系列文章地址:http://blog.csdn.net/morewindows/article/category/863841
?
一.關(guān)鍵函數(shù)
1.1? cvFindContours
函數(shù)功能:對圖像進行輪廓檢測,這個函數(shù)將生成一條鏈表以保存檢測出的各個輪廓信息,并傳出指向這條鏈表表頭的指針。
函數(shù)原型:
int?cvFindContours(
? CvArr*?image,
? CvMemStorage*?storage,
? CvSeq**?first_contour,?
? int?header_size=sizeof(CvContour),
? int?mode=CV_RETR_LIST,?
? int?method=CV_CHAIN_APPROX_SIMPLE,
? CvPoint?offset=cvPoint(0,0)
);
函數(shù)說明:
第一個參數(shù)表示輸入圖像,必須為一個8位的二值圖像。圖像的二值化請參見《【OpenCV入門指南】第四篇圖像的二值化》。
?
第二參數(shù)表示存儲輪廓的容器。為CvMemStorage類型,定義在OpenCV的\core\types_c.h中。
?
第三個參數(shù)為輸出參數(shù),這個參數(shù)將指向用來存儲輪廓信息的鏈表表頭。
?
第四個參數(shù)表示存儲輪廓鏈表的表頭大小,當?shù)诹鶄€參數(shù)傳入CV_CHAIN_CODE時,要設(shè)置成sizeof(CvChain),其它情況統(tǒng)一設(shè)置成sizeof(CvContour)。
?
第五個參數(shù)為輪廓檢測的模式,有如下取值:
CV_RETR_EXTERNAL:只檢索最外面的輪廓;
CV_RETR_LIST:檢索所有的輪廓,并將其保存到一條鏈表當中;
CV_RETR_CCOMP:檢索所有的輪廓,并將他們組織為兩層:頂層是各部分的外部邊界,第二層是空洞的邊界;
CV_RETR_TREE:檢索所有的輪廓,并重構(gòu)嵌套輪廓的整個層次,可以參見下圖。
第六個參數(shù)用來表示輪廓邊緣的近似方法的,常用值如下所示:
CV_CHAIN_CODE:以Freeman鏈碼的方式輸出輪廓,所有其他方法輸出多邊形(頂點的序列)。
CV_CHAIN_APPROX_SIMPLE:壓縮水平的、垂直的和斜的部分,也就是,函數(shù)只保留他們的終點部分。
?
第七個參數(shù)表示偏移量,比如你要從圖像的(100, 0)開始進行輪廓檢測,那么就傳入(100, 0)。
?
使用cvFindContours函數(shù)能檢測出圖像的輪廓,將輪廓繪制出來則需要另一函數(shù)——cvDrawContours來配合了。下面介紹cvDrawContours函數(shù)。
?
1.2? cvDrawContours
函數(shù)功能:在圖像上繪制外部和內(nèi)部輪廓
函數(shù)原型:
void?cvDrawContours(
? CvArr?*img,
? CvSeq*?contour,
? CvScalar?external_color,
? CvScalar?hole_color,
? int?max_level,
? int?thickness=1,
? int?line_type=8,
? CvPoint?offset=cvPoint(0,0)
);
第一個參數(shù)表示輸入圖像,函數(shù)將在這張圖像上繪制輪廓。
第二個參數(shù)表示指向輪廓鏈表的指針。
第三個參數(shù)和第四個參數(shù)表示顏色,繪制時會根據(jù)輪廓的層次來交替使用這二種顏色。
第五個參數(shù)表示繪制輪廓的最大層數(shù),如果是0,只繪制contour;如果是1,追加繪制和contour同層的所有輪廓;如果是2,追加繪制比contour低一層的輪廓,以此類推;如果值是負值,則函數(shù)并不繪制contour后的輪廓,但是將畫出其子輪廓,一直到abs(max_level) - 1層。
第六個參數(shù)表示輪廓線的寬度,如果為CV_FILLED則會填充輪廓內(nèi)部。
第七個參數(shù)表示輪廓線的類型。
第八個參數(shù)表示偏移量,如果傳入(10,20),那繪制將從圖像的(10,20)處開始。
?
二.示例程序代碼
下面用一個非常簡單的例子展示如何使用輪廓檢測。
[cpp]?view plaincopy
?? ?? #include?<opencv2/opencv.hpp>?? using?namespace?std;?? #pragma?comment(linker,?"/subsystem:\"windows\"?/entry:\"mainCRTStartup\"")?? int?main(?int?argc,?char**?argv?)?? {????? ????const?char?*pstrWindowsSrcTitle?=?"原圖(http://blog.csdn.net/MoreWindows)";?? ????const?char?*pstrWindowsOutLineTitle?=?"輪廓圖(http://blog.csdn.net/MoreWindows)";?? ?????? ????const?int?IMAGE_WIDTH?=?400;?? ????const?int?IMAGE_HEIGHT?=?200;?? ?? ?????? ????IplImage?*pSrcImage?=?cvCreateImage(cvSize(IMAGE_WIDTH,?IMAGE_HEIGHT),?IPL_DEPTH_8U,?3);?? ?????? ????cvRectangle(pSrcImage,?cvPoint(0,?0),?cvPoint(pSrcImage->width,?pSrcImage->height),?CV_RGB(255,?255,?255),?CV_FILLED);?? ?????? ????CvPoint?ptCircleCenter?=?cvPoint(IMAGE_WIDTH?/?4,?IMAGE_HEIGHT?/?2);?? ????int?nRadius?=?80;?? ????cvCircle(pSrcImage,?ptCircleCenter,?nRadius,?CV_RGB(255,?255,?0),?CV_FILLED);?? ????ptCircleCenter?=?cvPoint(IMAGE_WIDTH?/?4,?IMAGE_HEIGHT?/?2);?? ????nRadius?=?30;?? ????cvCircle(pSrcImage,?ptCircleCenter,?nRadius,?CV_RGB(255,?255,?255),?CV_FILLED);?? ?????? ????CvPoint?ptLeftTop?=?cvPoint(IMAGE_WIDTH?/?2?+?20,?20);?? ????CvPoint?ptRightBottom?=?cvPoint(IMAGE_WIDTH?-?20,?IMAGE_HEIGHT?-?20);?? ????cvRectangle(pSrcImage,?ptLeftTop,?ptRightBottom,?CV_RGB(0,?255,?255),?CV_FILLED);?? ????ptLeftTop?=?cvPoint(IMAGE_WIDTH?/?2?+?60,?40);?? ????ptRightBottom?=?cvPoint(IMAGE_WIDTH?-?60,?IMAGE_HEIGHT?-?40);?? ????cvRectangle(pSrcImage,?ptLeftTop,?ptRightBottom,?CV_RGB(255,?255,?255),?CV_FILLED);?? ?????? ????cvNamedWindow(pstrWindowsSrcTitle,?CV_WINDOW_AUTOSIZE);?? ????cvShowImage(pstrWindowsSrcTitle,?pSrcImage);?? ?? ?? ?????? ????IplImage?*pGrayImage?=??cvCreateImage(cvGetSize(pSrcImage),?IPL_DEPTH_8U,?1);?? ????cvCvtColor(pSrcImage,?pGrayImage,?CV_BGR2GRAY);?? ?????? ????IplImage?*pBinaryImage?=?cvCreateImage(cvGetSize(pGrayImage),?IPL_DEPTH_8U,?1);?? ????cvThreshold(pGrayImage,?pBinaryImage,?250,?255,?CV_THRESH_BINARY);?? ?? ?? ?????? ????CvMemStorage?*pcvMStorage?=?cvCreateMemStorage();?? ????CvSeq?*pcvSeq?=?NULL;?? ????cvFindContours(pBinaryImage,?pcvMStorage,?&pcvSeq,?sizeof(CvContour),?CV_RETR_TREE,?CV_CHAIN_APPROX_SIMPLE,?cvPoint(0,?0));?? ?????? ?????? ????IplImage?*pOutlineImage?=?cvCreateImage(cvGetSize(pSrcImage),?IPL_DEPTH_8U,?3);?? ????int?nLevels?=?5;?? ?????? ????cvRectangle(pOutlineImage,?cvPoint(0,?0),?cvPoint(pOutlineImage->width,?pOutlineImage->height),?CV_RGB(255,?255,?255),?CV_FILLED);?? ????cvDrawContours(pOutlineImage,?pcvSeq,?CV_RGB(255,0,0),?CV_RGB(0,255,0),?nLevels,?2);?? ?????? ????cvNamedWindow(pstrWindowsOutLineTitle,?CV_WINDOW_AUTOSIZE);?? ????cvShowImage(pstrWindowsOutLineTitle,?pOutlineImage);?? ?? ?? ????cvWaitKey(0);?? ?? ????cvReleaseMemStorage(&pcvMStorage);?? ?? ????cvDestroyWindow(pstrWindowsSrcTitle);?? ????cvDestroyWindow(pstrWindowsOutLineTitle);?? ????cvReleaseImage(&pSrcImage);?? ????cvReleaseImage(&pGrayImage);?? ????cvReleaseImage(&pBinaryImage);?? ????cvReleaseImage(&pOutlineImage);?? ????return?0;?? }??
運行結(jié)果如下圖所示:
由圖可以看出,輪廓線已經(jīng)按層次交替的繪制成功了,讀者可以修改程序中的cvDrawContours中的nLevels參數(shù),看看圖形會有什么變化。
?
下一篇《【OpenCV入門指南】第六篇輪廓檢測下》將對一個復雜的圖像進行輪廓檢測,以便大家更好的觀察出輪廓檢測的特點。
?
《OpenCV入門指南》系列文章地址:http://blog.csdn.net/morewindows/article/category/863841
轉(zhuǎn)載請標明出處,原文地址:http://blog.csdn.net/morewindows/article/details/8253137
歡迎關(guān)注微博:http://weibo.com/MoreWindows
《新程序員》:云原生和全面數(shù)字化實踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀
總結(jié)
以上是生活随笔為你收集整理的【OpenCV入门指南】第五篇 轮廓检测 上的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。