首页 > 代码库 > 如何寻找已知轮廓的最大内接圆
如何寻找已知轮廓的最大内接圆
问题的提出:
所谓内切圆,是指“与多边形各边都相切的圆“。我们这里需要找的是所谓”内接圆“,可以简单认为是”圆点在轮廓中,到轮廓中所有点的距离一样的图像“。在这所有的”内接圆“中,寻找半径最大的哪一个。
这个问题已经广泛讨论了,比如
这样的图像,寻找轮廓的最大内接圆。
解决方法:
利用计算机图像学技术中轮廓的相关思路,可以直接从圆的定义解决此问题。基于OpenCV的代码和注释如下:
#include "stdafx.h"
#include <iostream>
using namespace std;
using namespace cv;
VP FindBigestContour(Mat src){
int imax = 0; //代表最大轮廓的序号
int imaxcontour = -1; //代表最大轮廓的大小
std::vector<std::vector<cv::Point>>contours;
findContours(src,contours,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE);
for (int i=0;i<contours.size();i++){
int itmp = contourArea(contours[i]);//这里采用的是轮廓大小
if (imaxcontour < itmp ){
imax = i;
imaxcontour = itmp;
}
}
return contours[imax];
}
int main(int argc, char* argv[])
{
Mat src = imread("e:/template/cloud.png");
Mat temp;
cvtColor(src,temp,COLOR_BGR2GRAY);
threshold(temp,temp,100,255,THRESH_OTSU);
imshow("src",temp);
//寻找最大轮廓
VP VPResult = FindBigestContour(temp);
//寻找最大内切圆
int dist = 0;
int maxdist = 0;
Point center;
for(int i=0;i<src.cols;i++)
{
for(int j=0;j<src.rows;j++)
{
dist = pointPolygonTest(VPResult,cv::Point(i,j),true);
if(dist>maxdist)
{
maxdist=dist;
center=cv::Point(i,j);
}
}
}
//绘制结果
circle(src,center,maxdist,Scalar(0,0,255));
imshow("dst",src);
waitKey();
}
#include <iostream>
using namespace std;
using namespace cv;
VP FindBigestContour(Mat src){
int imax = 0; //代表最大轮廓的序号
int imaxcontour = -1; //代表最大轮廓的大小
std::vector<std::vector<cv::Point>>contours;
findContours(src,contours,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE);
for (int i=0;i<contours.size();i++){
int itmp = contourArea(contours[i]);//这里采用的是轮廓大小
if (imaxcontour < itmp ){
imax = i;
imaxcontour = itmp;
}
}
return contours[imax];
}
int main(int argc, char* argv[])
{
Mat src = imread("e:/template/cloud.png");
Mat temp;
cvtColor(src,temp,COLOR_BGR2GRAY);
threshold(temp,temp,100,255,THRESH_OTSU);
imshow("src",temp);
//寻找最大轮廓
VP VPResult = FindBigestContour(temp);
//寻找最大内切圆
int dist = 0;
int maxdist = 0;
Point center;
for(int i=0;i<src.cols;i++)
{
for(int j=0;j<src.rows;j++)
{
dist = pointPolygonTest(VPResult,cv::Point(i,j),true);
if(dist>maxdist)
{
maxdist=dist;
center=cv::Point(i,j);
}
}
}
//绘制结果
circle(src,center,maxdist,Scalar(0,0,255));
imshow("dst",src);
waitKey();
}
其中
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 ,它是返回一个从点到最近的边的带符号距离。
测试点是否在多边形中
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 ,它是返回一个从点到最近的边的带符号距离。
结果:
优化的思路:
这里对圆心的遍历,是遍历了所有的图像上面的点。然而根据”内接圆心一定在轮廓内部“这个先验知识,可以缩小循环范围,提高算法效率。
如何寻找已知轮廓的最大内接圆
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。