转自:opencv findcontour查找最大的内轮廓
问题是怎么来的呢
比如输入一幅图像,往往需要我们找最大的轮廓,如果是仅仅是查找最大的轮廓,那么问题也比较简单了,直接找出所有的轮廓,然后根据轮廓的面积,遍历查找出最大的轮廓即可。如果是找最大的外轮廓,那么问题也比较简单,因为findContours(image_contour_outside, contours_out, hierarchy_out, RETR_EXTERNAL, CHAIN_APPROX_NONE);有参数,CV_RETR_EXTERNAL:只检索最外面的轮廓。fingcontours函数详解,可参考百度百科。
现在的问题是:我们要查找最大的内轮廓。如果有一个参数,限定只找内轮廓就好了,可惜opencv并没有提供这样的接口。那么问题就需要我们自己动手解决了。
话不多说,直接上代码吧。开发环境vs2013+opencv2.4.13
-
int chao_get_pointlist_inner_contour2(Mat src, vector<Point> &contourlist)
-
{
-
Mat image_contour_all = src.clone();
-
Mat image_contour_outside = src.clone();
-
-
vector<vector<Point> > contours_out;
-
vector<Vec4i> hierarchy_out;
-
findContours(image_contour_outside, contours_out, hierarchy_out, RETR_EXTERNAL, CHAIN_APPROX_NONE);
-
-
vector<vector<Point> > contours_all;
-
vector<Vec4i> hierarchy_all;
-
findContours(image_contour_all, contours_all, hierarchy_all, RETR_TREE, CHAIN_APPROX_NONE);
-
-
if (contours_all.size() == contours_out.size()) return -1;//没有内轮廓,则提前返回
-
-
for (int i = 0; i < contours_out.size(); i++)
-
{
-
int conloursize = contours_out[i].size();
-
for (int j = 0; j < contours_all.size(); j++)
-
{
-
int tem_size = contours_all[j].size();
-
if (conloursize == tem_size)
-
{
-
swap(contours_all[j], contours_all[contours_all.size() - 1]);
-
contours_all.pop_back();
-
break;
-
}
-
}
-
}
-
-
//contours_all中只剩下内轮廓
-
//查找最大轮廓
-
double maxarea = 0;
-
int maxAreaIdx = 0;
-
for (int index = contours_all.size() - 1; index >= 0; index--)
-
{
-
double tmparea = fabs(contourArea(contours_all[index]));
-
if (tmparea>maxarea)
-
{
-
maxarea = tmparea;
-
maxAreaIdx = index;//记录最大轮廓的索引号
-
}
-
}
-
-
contourlist = contours_all[maxAreaIdx];
-
-
return 0;
-
}
效果如图所示:

这个函数的原理就是:
1、找出所有的轮廓,包含内轮廓和外轮廓;
2、仅找出外轮廓;
3、删除所有轮廓中的外轮廓,即得到内轮廓
4、找出内轮廓中的最大轮廓
这是我目前想到的方法,如果读到这篇博文的读者,有更好的方法和建议,欢迎提出。