OpenCV中文网站

 找回密码
 立即注册
搜索
热搜: 安装 配置
查看: 10692|回复: 8

求助,如何求轮廓内最大的内接圆

[复制链接]
发表于 2017-5-8 20:09:29 | 显示全部楼层 |阅读模式
图片经过简单的预处理能够得到较完整的轮廓,现想求出该轮廓中最大的内接圆,请问应该如何实现。

外轮廓

外轮廓
回复

使用道具 举报

 楼主| 发表于 2017-5-8 21:17:03 | 显示全部楼层
请各位指导指导
回复 支持 反对

使用道具 举报

发表于 2017-5-8 23:09:36 | 显示全部楼层
群里面讨论了一下
参考
http://answers.opencv.org/question/1494/pointpolygontest-is-not-working-properly/

首先,了解一个函数
PointPolygonTest
测试点是否在多边形中
double cvPointPolygonTest( const CvArr* contour, CvPoint2D32f pt, int measure_dist );
contour 输入轮廓.
pt 针对轮廓需要测试的点。
measure_dist 如果非0,函数将估算点到轮廓最近边的距离。
函数cvPointPolygonTest 决定测试点是否在轮廓内,轮廓外,还是轮廓的边上(或者共边的交点上),它的返回值是正负零,相对应的,当measure_dist=0时,返回值是1, -1,0, 同样当 measure_dist≠0 ,它是返回一个从点到最近的边的带符号距离。

然后,转变一个思路。所谓最大内切圆,就是在轮廓中找一中心点,是的轮廓上所有的点到这个中心的距离 在所有可能中最大。
那么,然后就是一个简单遍历的问题。当然,如果如贾所说,首先控制搜索空间,会提高速度。


  1. cv::MatcontourImg=imread("contour.png");
  2. std::vector<cv::Mat>channels;
  3. cv::split(contourImg,channels);// On these lines, the input image is paddedcv::Matgray(contourImg.rows+20,contourImg.cols+20,CV_8UC1);
  4. gray=255;
  5. channels[0].copyTo(gray(cv::Rect(10,10,contourImg.cols,contourImg.rows)));
  6. cv::imshow("Original",gray);
  7. std::vector<std::vector<cv::Point>>contours;
  8. cv::findContours(gray,contours,CV_RETR_LIST,CV_CHAIN_APPROX_NONE);
  9. cv::Matdrawing(gray.size(),CV_8UC3);
  10. cv::Matdraw2=drawing.clone();
  11. cv::drawContours(drawing,contours,0,cv::Scalar(20,175,20),1,CV_AA);
  12. doubledist,maxdist=-1;
  13. cv::Pointcenter;
  14. for(inti=0;i<contourImg.cols;i++)
  15. {for(intj=0;j<contourImg.rows;j++){dist=pointPolygonTest(contours[0],cv::Point(i,j),true);
  16. if(dist>maxdist)
  17. {maxdist=dist;center=cv::Point(i,j);}}}cv::circle(drawing,center,maxdist,cv::Scalar(220,75,20),1,CV_AA);cv::imshow("Contours",drawing);cv::waitKey();return0;
复制代码

回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-5-9 09:01:43 | 显示全部楼层
jsxyheu2014 发表于 2017-5-8 23:09
群里面讨论了一下
参考
http://answers.opencv.org/question/1494/pointpolygontest-is-not-working-proper ...

非常感谢您能一直这么关注我的问题,给予我知道之指导。我先学习一下,后面有不明白的还望多指教!
回复 支持 反对

使用道具 举报

发表于 2017-5-9 13:08:01 | 显示全部楼层
重新这里并且贴出完整代码:
《如何寻找已知轮廓的最大内接圆》
http://www.cnblogs.com/jsxyhelu/p/6830093.html
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-5-9 15:08:06 | 显示全部楼层
jsxyheu2014 发表于 2017-5-9 13:08
重新这里并且贴出完整代码:
《如何寻找已知轮廓的最大内接圆》
http://www.cnblogs.com/jsxyhelu/p/683009 ...

这个方法到时不错,但是处理的时间会很久啊
回复 支持 反对

使用道具 举报

发表于 2017-6-19 15:57:18 | 显示全部楼层
不过用楼上所说的函数要先把轮廓连续起来吧,我刚想了下可以用边缘法线的形式去连续边缘线,但只是想想,如果楼主有时间可以试着编下程序实现,可能比较花时间,楼上的程序没有加typedef vector<oint> VP;可能是版本不同吧,我的是VS2010,opencv2.4.9,,如果楼主弄好了边缘连续记得给我发一份哈937784613@qq.com,不甚感激
  1. #include <opencv2/core/core.hpp>
  2. #include <opencv2/highgui/highgui.hpp>
  3. #include <opencv2/imgproc/imgproc.hpp>
  4. #include <iostream>
  5. using namespace cv;
  6. using namespace std;

  7. typedef vector<Point> VP;
  8. VP FindBigestContour(Mat src){   
  9.     int imax = 0; //代表最大轮廓的序号
  10.     int imaxcontour = -1; //代表最大轮廓的大小
  11.     std::vector<std::vector<cv::Point>>contours;   
  12.     findContours(src,contours,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE);
  13.     for (int i=0;i<contours.size();i++){
  14.         int itmp =  contourArea(contours[i]);//这里采用的是轮廓大小
  15.         if (imaxcontour < itmp ){
  16.             imax = i;
  17.             imaxcontour = itmp;
  18.         }
  19.     }
  20.     return contours[imax];
  21. }
  22. int main(int argc, char* argv[])
  23. {
  24.     Mat src = imread("0619.png");
  25.     Mat temp;
  26.     cvtColor(src,temp,COLOR_BGR2GRAY);
  27.     threshold(temp,temp,100,255,THRESH_OTSU);
  28.     imshow("src",temp);
  29.     //寻找最大轮廓
  30.     VP VPResult = FindBigestContour(temp);
  31.     //寻找最大内切圆
  32.     int dist = 0;
  33.     int maxdist = 0;
  34.     Point center;
  35.     for(int i=0;i<src.cols;i++)
  36.     {
  37.         for(int j=0;j<src.rows;j++)
  38.         {
  39.             dist = pointPolygonTest(VPResult,cv::Point(i,j),true);
  40.             if(dist>maxdist)
  41.             {
  42.                 maxdist=dist;
  43.                 center=cv::Point(i,j);
  44.             }
  45.         }
  46.     }
  47.     //绘制结果
  48.     circle(src,center,maxdist,Scalar(0,0,255));
  49.     imshow("dst",src);
  50.     waitKey();
  51. }
复制代码

回复 支持 反对

使用道具 举报

发表于 2017-8-30 16:01:36 | 显示全部楼层
tao_hau 发表于 2017-5-9 15:08
这个方法到时不错,但是处理的时间会很久啊

可以考虑在轮廓的最大外接矩形区域内遍历 。
回复 支持 反对

使用道具 举报

发表于 2019-6-25 10:48:38 | 显示全部楼层
可以根据具体的应用场景缩小圆心的遍历范围
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|OpenCV中文网站

GMT+8, 2024-4-20 06:49 , Processed in 0.011707 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表