OpenCV中一个连通域处理函数

作者:tornadomeet 出处:http://www.cnblogs.com/tornadomeet 欢迎转载或分享,但请务必声明文章出处。

连通域处理函数的原型:

    void ConnectedComponents(Mat &mask_process,  int poly1_hull0,  float perimScale,  int number = 0,  Rect &bounding_box = Rect(),  Point &contour_centers = Point(-1, -1));

参数解析:

   参数mask_process表示的是需要进行连通域处理二值图像。

  参数poly1_hull0表示轮廓边缘是否采用多边形拟合,如果该参数为1,则表示采用多边形拟合,否则采用凸包拟合。

  参数perimScale是用来将那些小的轮廓去掉,那些小的轮廓时指它的周长小于(mask长+宽)/perimScale。当然你在其内部代码也可以该为面积来判断。

  参数number 表示实际需要处理最多的轮廓的个数(如果输入的mask有多个轮廓的话),这里的处理是指计算出这些轮廓的外接矩形和中心点。默认值为0,表示函数内部不需要处理这些外接矩形和中心点。

  参数bounding_box 表示的是处理完后对应轮廓的外接矩形,默认值为Rect(),表示不需要返回这些外接矩形。

  参数contour_centers 表示处理完后对应轮廓的中心点坐标,默认值为Point(-1, -1),表示不需要返回这些中心点

实现代码:

 

[html]  view plain copy
  1. #include <iostream>  
  2. #include <opencv.hpp>  
  3.   
  4.   
  5. using namespace cv;  
  6. using namespace std;  
  7.   
  8. //Just some convienience macros  
  9. #define CV_CVX_WHITE    CV_RGB(0xff,0xff,0xff)  
  10. #define CV_CVX_BLACK    CV_RGB(0x00,0x00,0x00)  
  11.   
  12.   
  13. void ConnectedComponents(Mat &mask_process, int poly1_hull0, float perimScale, int number = 0,  
  14.                          Rect &bounding_box = Rect(), Point &contour_centers = Point(-1, -1))  
  15. {  
  16.     /*下面4句代码是为了兼容原函数接口,即内部使用的是c风格,但是其接口是c++风格的*/  
  17.     IplImage *mask = &mask_process.operator IplImage();  
  18.     int *num = &number;  
  19.     CvRect *bbs = &bounding_box.operator CvRect();  
  20.     CvPoint *centers = &contour_centers.operator CvPoint();  
  21.     static CvMemStorage*    mem_storage    = NULL;  
  22.     static CvSeq*            contours    = NULL;  
  23.     //CLEAN UP RAW MASK  
  24.         //开运算作用:平滑轮廓,去掉细节,断开缺口  
  25.         cvMorphologyEx( mask, mask, NULL, NULL, CV_MOP_OPEN, 1 );//对输入mask进行开操作,CVCLOSE_ITR为开操作的次数,输出为mask图像  
  26.         //闭运算作用:平滑轮廓,连接缺口  
  27.         cvMorphologyEx( mask, mask, NULL, NULL, CV_MOP_CLOSE, 1 );//对输入mask进行闭操作,CVCLOSE_ITR为闭操作的次数,输出为mask图像  
  28.     //FIND CONTOURS AROUND ONLY BIGGER REGIONS  
  29.         if( mem_storage==NULL ) mem_storage = cvCreateMemStorage(0);  
  30.             else cvClearMemStorage(mem_storage);  
  31.         //CV_RETR_EXTERNAL=0是在types_c.h中定义的,CV_CHAIN_APPROX_SIMPLE=2也是在该文件中定义的  
  32.         CvContourScanner scanner = cvStartFindContours(mask,mem_storage,sizeof(CvContour),CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE);  
  33.         CvSeq* c;  
  34.         int numCont = 0;  
  35.         //该while内部只针对比较大的轮廓曲线进行替换处理  
  36.         while( (c = cvFindNextContour( scanner )) != NULL )  
  37.         {  
  38.             double len = cvContourPerimeter( c );  
  39.             double q = (mask->height + mask->width) /perimScale;   //calculate perimeter len threshold  
  40.             if( len < q ) //Get rid of blob if it's perimeter is too small  
  41.             {  
  42.                 cvSubstituteContour( scanner, NULL );    //用NULL代替原来的那个轮廓  
  43.             }  
  44.             else //Smooth it's edges if it's large enough  
  45.             {  
  46.                 CvSeq* c_new;  
  47.                 if(poly1_hull0) //Polygonal approximation of the segmentation  
  48.                     c_new = cvApproxPoly(c,sizeof(CvContour),mem_storage,CV_POLY_APPROX_DP, 2,0);  
  49.                 else //Convex Hull of the segmentation  
  50.                     c_new = cvConvexHull2(c,mem_storage,CV_CLOCKWISE,1);  
  51.                 cvSubstituteContour( scanner, c_new ); //最开始的轮廓用凸包或者多项式拟合曲线替换  
  52.                 numCont++;  
  53.             }  
  54.         }  
  55.         contours = cvEndFindContours( &scanner );    //结束轮廓查找操作  
  56.     // PAINT THE FOUND REGIONS BACK INTO THE IMAGE  
  57.         cvZero( mask );  
  58.         IplImage *maskTemp;  
  59.         //CALC CENTER OF MASS AND OR BOUNDING RECTANGLES  
  60.         if(*num != 0)  
  61.         {  
  62.             int N = *num, numFilled = 0i=0;  
  63.             CvMoments moments;  
  64.             double M00, M01, M10;  
  65.             maskTemp = cvCloneImage(mask);  
  66.             for(i=0c=contours; c != NULL; c = c->h_next,i++ )        //h_next为轮廓序列中的下一个轮廓  
  67.             {  
  68.                 if(i < N) //Only process up to *num of them  
  69.                 {  
  70.                     //CV_CVX_WHITE在本程序中是白色的意思  
  71.                     cvDrawContours(maskTemp,c,CV_CVX_WHITE, CV_CVX_WHITE,-1,CV_FILLED,8);  
  72.                     //Find the center of each contour  
  73.                     if(centers != &cvPoint(-1, -1))  
  74.                     {  
  75.                         cvMoments(maskTemp,&moments,1);    //计算mask图像的最高达3阶的矩  
  76.                         M00 = cvGetSpatialMoment(&moments,0,0); //提取x的0次和y的0次矩  
  77.                         M10 = cvGetSpatialMoment(&moments,1,0); //提取x的1次和y的0次矩  
  78.                         M01 = cvGetSpatialMoment(&moments,0,1); //提取x的0次和y的1次矩  
  79.                         centers[i].x = (int)(M10/M00);    //利用矩的结果求出轮廓的中心点坐标  
  80.                         centers[i].y = (int)(M01/M00);  
  81.                     }  
  82.                     //Bounding rectangles around blobs  
  83.                     if(bbs != &CvRect())  
  84.                     {  
  85.                         bbs[i] = cvBoundingRect(c); //算出轮廓c的外接矩形  
  86.                     }  
  87.                     cvZero(maskTemp);  
  88.                     numFilled++;  
  89.                 }  
  90.                 //Draw filled contours into mask  
  91.                 cvDrawContours(mask,c,CV_CVX_WHITE,CV_CVX_WHITE,-1,CV_FILLED,8); //draw to central mask  
  92.             } //end looping over contours  
  93.             *num = numFilled;  
  94.             cvReleaseImage( &maskTemp);  
  95.         }  
  96.         //ELSE JUST DRAW PROCESSED CONTOURS INTO THE MASK  
  97.         else  
  98.         {  
  99.             for( c=contours; c != NULL; c = c->h_next )  
  100.             {  
  101.                 cvDrawContours(mask,c,CV_CVX_WHITE, CV_CVX_BLACK,-1,CV_FILLED,8);  
  102.             }  
  103.         }  
  104. }  
  105.   
  106. int main()  
  107. {  
  108.     Mat src, mask;  
  109.     src = imread("test.png", 0);    //以灰度图像读入  
  110.     imshow("src", src);  
  111.   
  112.     mask = src > 0;     //转换为二值图像  
  113.     imshow("mask", mask);  
  114.   
  115.     ConnectedComponents(mask, 1, 8.0, 1, Rect(), Point(-1, -1));    //采用多边形拟合处理  
  116.     imshow("out1", mask);  
  117.   
  118.     ConnectedComponents(mask, 0, 8.0, 1, Rect(), Point(-1, -1));    //c采用凸包进行处理  
  119.     imshow("out2", mask);  
  120.     waitKey(0);  
  121.   
  122.     return 0;  
  123. }  


实验结果

  所需处理原始图像的灰度图:

  

 

  其对应的mask图像:

  

 

  使用多项式拟合的连通域处理后图像:

  

 

  使用凸包集拟合的连通域处理后的图像:

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值