opencv:基于凹点匹配的重叠分割 opencv:基于凹点匹配的重叠分割

opencv:基于凹点匹配的重叠分割

     有重叠部分的两个同类型物体由于灰度近似,所以一般较难分类(如下图)。实际操作中是使用一种凹点匹配的方法来寻找分割点进行分割。


两个重叠物体 其中黄色十字地方就是凹点


    寻找到凹点是解决该分割问题的关键。这里采用如下方法:

       1、寻找该图像的最小凸闭包,

       2、图闭包和凹图形相减得到凹区域

       3、提取凹区域的轮廓

       4、按照区域面积大小最为权重,选取最大的两个区域作为凹点所在区域

       5、遍历这两个区域,寻找距离最短的两个点作为凹点

       6、基于该两个凹点分割


关键实现:

[cpp]  view plain  copy
  1. /** 
  2.  * @brief searchConcaveRegion 寻找凹区域 
  3.  * @param hull  凸包点集 
  4.  * @param src  原图像(二值图) 
  5.  * @return 返回 图像凹区域 
  6.  */  
  7. Mat searchConcaveRegion(std::vector<std::vector<Point> >hull, Mat &src)  
  8. {  
  9.     if(src.empty())  
  10.         return Mat();  
  11.   
  12.     Mat concaveRegion=Mat::zeros(src.rows,src.cols,CV_8UC1);  
  13.     //填充凸包点集  
  14.     for(int i=0;i<hull.size();++i)  
  15.         drawContours(concaveRegion,hull,i,Scalar(255),CV_FILLED);  
  16.   
  17.     concaveRegion=concaveRegion-src*255;  
  18.   
  19.     medianBlur(concaveRegion,concaveRegion,3);  
  20.   
  21.     return concaveRegion;  
  22. }  
  23.   
  24. /** 
  25.  * @brief searchConcavePoint 
  26.  * @param src 凹区域图像 
  27.  * @return 返回匹配好的凹点对(2个) 
  28.  */  
  29. std::vector<Point2f> searchConcavePoint(Mat &src)  
  30. {  
  31.     std::vector<Point2f> ConcavePoint;  
  32.     //轮廓寻找  
  33.     std::vector<std::vector<Point> > contour;//用来存储轮廓  
  34.     std::vector<Vec4i> hierarchys;  
  35.     findContours(src, contour, hierarchys,  
  36.                  CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));  //寻找轮廓  
  37.   
  38.     //凹区域少于2要退出  
  39.     if(contour.size()<2)  
  40.         return ConcavePoint;  
  41.   
  42.     //按照轮廓面积大小排序  
  43.     std::sort(contour.begin(),contour.end(),[](const std::vector<Point> &s1,  
  44.               const std::vector<Point> &s2){  
  45.         double a1=contourArea(s1);  
  46.         double a2=contourArea(s2);  
  47.         return a1>a2;  
  48.     });  
  49.   
  50.     int minDistance=100000000;//最短距离  
  51.     for(int i=0;i<contour[0].size();++i)  
  52.         for(int j=0;j<contour[1].size();++j)  
  53.         {  
  54.             //欧氏距离  
  55.             int d= std::sqrt(std::pow((contour[0][i].x-contour[1][j].x),2)+  
  56.                     std::pow((contour[0][i].y-contour[1][j].y),2));  
  57.             if(minDistance>d)  
  58.             {  
  59.                 minDistance=d;  
  60.                 ConcavePoint.push_back(contour[0][i]);  
  61.                 ConcavePoint.push_back(contour[1][j]);  
  62.             }  
  63.         }  
  64.     qDebug()<<"ConcavePoint0:"<<ConcavePoint[0].x<<","<<ConcavePoint[0].y;  
  65.     qDebug()<<"ConcavePoint1:"<<ConcavePoint[1].x<<","<<ConcavePoint[1].y;  
  66.   
  67.     return ConcavePoint;  
  68. }  

注意:本文讨论的就是只有单一重叠区域的简单情况,对于一些多重叠区域,其凹点能否正确匹配是实现分割的关键。

效果:本人用这种方法来提取图像区域较为准确质心,防止质心偏移:

                                                                                         

                                 原始图                                                                                                                                               凹区域

                                                                                           

                               分割结果                                                                                                                                                          提取质心结果

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cfqcfqcfqcfqcfq/article/details/53133357
个人分类:  opencv

猜你喜欢

转载自blog.csdn.net/qq_40909394/article/details/80596845