图像的轮廓检测cvFindContours

时间:2022-06-23 22:06:31
  1. 参考网络例程
  2. //图像的轮廓检测  
  3. //By MoreWindows (http://blog.csdn.net/MoreWindows)  
  4. #include <opencv2/opencv.hpp>  
  5. using namespace std;  
  6. #pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")  
  7. int main( int argc, char** argv )  
  8. {     
  9.     const char *pstrWindowsSrcTitle = "1";  
  10.     const char *pstrWindowsOutLineTitle = "2";  
  11.       
  12.     const int IMAGE_WIDTH = 400;  
  13.     const int IMAGE_HEIGHT = 200;  
  14.   
  15.     // 创建图像  
  16.     IplImage *pSrcImage = cvCreateImage(cvSize(IMAGE_WIDTH, IMAGE_HEIGHT), IPL_DEPTH_8U, 3);  
  17.     // 填充成白色  
  18.     cvRectangle(pSrcImage, cvPoint(0, 0), cvPoint(pSrcImage->width, pSrcImage->height), CV_RGB(255, 255, 255), CV_FILLED);  
  19.     // 画圆  
  20.     CvPoint ptCircleCenter = cvPoint(IMAGE_WIDTH / 4, IMAGE_HEIGHT / 2);  
  21.     int nRadius = 80;  
  22.     cvCircle(pSrcImage, ptCircleCenter, nRadius, CV_RGB(255, 255, 0), CV_FILLED);  
  23.     ptCircleCenter = cvPoint(IMAGE_WIDTH / 4, IMAGE_HEIGHT / 2);  
  24.     nRadius = 30;  
  25.     cvCircle(pSrcImage, ptCircleCenter, nRadius, CV_RGB(255, 255, 255), CV_FILLED);  
  26.     // 画矩形  
  27.     CvPoint ptLeftTop = cvPoint(IMAGE_WIDTH / 2 + 20, 20);  
  28.     CvPoint ptRightBottom = cvPoint(IMAGE_WIDTH - 20, IMAGE_HEIGHT - 20);  
  29.     cvRectangle(pSrcImage, ptLeftTop, ptRightBottom, CV_RGB(0, 255, 255), CV_FILLED);  
  30.     ptLeftTop = cvPoint(IMAGE_WIDTH / 2 + 60, 40);  
  31.     ptRightBottom = cvPoint(IMAGE_WIDTH - 60, IMAGE_HEIGHT - 40);  
  32.     cvRectangle(pSrcImage, ptLeftTop, ptRightBottom, CV_RGB(255, 255, 255), CV_FILLED);  
  33.     // 显示原图  
  34.     cvNamedWindow(pstrWindowsSrcTitle, CV_WINDOW_AUTOSIZE);  
  35.     cvShowImage(pstrWindowsSrcTitle, pSrcImage);  
  36.   
  37.   
  38.     // 转为灰度图  
  39.     IplImage *pGrayImage =  cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1);  
  40.     cvCvtColor(pSrcImage, pGrayImage, CV_BGR2GRAY);  
  41.     // 转为二值图  
  42.     IplImage *pBinaryImage = cvCreateImage(cvGetSize(pGrayImage), IPL_DEPTH_8U, 1);  
  43.     cvThreshold(pGrayImage, pBinaryImage, 250, 255, CV_THRESH_BINARY);  
  44.   
  45.   
  46.     // 检索轮廓并返回检测到的轮廓的个数  
  47.     CvMemStorage *pcvMStorage = cvCreateMemStorage();  
  48.     CvSeq *pcvSeq = NULL;  
  49.     cvFindContours(pBinaryImage, pcvMStorage, &pcvSeq, sizeof(CvContour), CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));  
  50.       
  51.     // 画轮廓图  
  52.     IplImage *pOutlineImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 3);  
  53.     int nLevels = 5;  
  54.     // 填充成白色  
  55.     cvRectangle(pOutlineImage, cvPoint(0, 0), cvPoint(pOutlineImage->width, pOutlineImage->height), CV_RGB(255, 255, 255), CV_FILLED);  
  56.     cvDrawContours(pOutlineImage, pcvSeq, CV_RGB(255,0,0), CV_RGB(0,255,0), nLevels, 2);  
  57.     // 显示轮廓图  
  58.     cvNamedWindow(pstrWindowsOutLineTitle, CV_WINDOW_AUTOSIZE);  
  59.     cvShowImage(pstrWindowsOutLineTitle, pOutlineImage);  
  60.   
  61.   
  62.     cvWaitKey(0);  
  63.   
  64.     cvReleaseMemStorage(&pcvMStorage);  
  65.   
  66.     cvDestroyWindow(pstrWindowsSrcTitle);  
  67.     cvDestroyWindow(pstrWindowsOutLineTitle);  
  68.     cvReleaseImage(&pSrcImage);  
  69.     cvReleaseImage(&pGrayImage);  
  70.     cvReleaseImage(&pBinaryImage);  
  71.     cvReleaseImage(&pOutlineImage);  
  72.     return 0;  
  73. }  


 cvFindContours

函数功能:对图像进行轮廓检测,这个函数将生成一条链表以保存检测出的各个轮廓信息,并传出指向这条链表表头的指针。

函数原型:

int cvFindContours(

  CvArrimage,

  CvMemStoragestorage,

  CvSeq** first_contour  

  int header_size=sizeof(CvContour),

  int mode=CV_RETR_LIST  

  int method=CV_CHAIN_APPROX_SIMPLE,

  CvPoint offset=cvPoint(0,0)

);

函数说明:

第一个参数表示输入图像,必须为一个8位的二值图像。图像的二值化请参见《OpenCV入门指南】第四篇图像的二值化》。

 

第二参数表示存储轮廓的容器。为CvMemStorage类型,定义在OpenCV\core\types_c.h中。

 

第三个参数为输出参数,这个参数将指向用来存储轮廓信息的链表表头。

 

第四个参数表示存储轮廓链表的表头大小,当第六个参数传入CV_CHAIN_CODE时,要设置成sizeof(CvChain),其它情况统一设置成sizeof(CvContour)。

 

第五个参数为轮廓检测的模式,有如下取值:

CV_RETR_EXTERNAL:只检索最外面的轮廓;

  CV_RETR_LIST:检索所有的轮廓,并将其保存到一条链表当中;

  CV_RETR_CCOMP:检索所有的轮廓,并将他们组织为两层:顶层是各部分的外部边界,第二层是空洞的边界;

CV_RETR_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次,可以参见下图。

图像的轮廓检测cvFindContours

第六个参数用来表示轮廓边缘的近似方法的,常用值如下所示:

CV_CHAIN_CODE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)。

  CV_CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部分,也就是,函数只保留他们的终点部分。

 

第七个参数表示偏移量,比如你要从图像的(100, 0)开始进行轮廓检测,那么就传入(100, 0)。

 

使用cvFindContours函数能检测出图像的轮廓,将轮廓绘制出来则需要另一函数——cvDrawContours来配合了。下面介绍cvDrawContours函数。

 


cvDrawContours

函数功能:在图像上绘制外部和内部轮廓

函数原型:

void cvDrawContours(

  CvArr *img,

  CvSeqcontour,

  CvScalar external_color,

  CvScalar hole_color,

  int max_level,

  int thickness=1,

  int line_type=8,

  CvPoint offset=cvPoint(0,0)

);

第一个参数表示输入图像,函数将在这张图像上绘制轮廓。

第二个参数表示指向轮廓链表的指针。

第三个参数和第四个参数表示颜色,绘制时会根据轮廓的层次来交替使用这二种颜色。

第五个参数表示绘制轮廓的最大层数,如果是0,只绘制contour;如果是1,追加绘制和contour同层的所有轮廓;如果是2,追加绘制比contour低一层的轮廓,以此类推;如果值是负值,则函数并不绘制contour后的轮廓,但是将画出其子轮廓,一直到abs(max_level) - 1层。

第六个参数表示轮廓线的宽度,如果为CV_FILLED则会填充轮廓内部。

第七个参数表示轮廓线的类型。

第八个参数表示偏移量,如果传入(1020),那绘制将从图像的(1020)处开始