问题是怎么来的呢
比如输入一幅图像,往往需要我们找最大的轮廓,如果是仅仅是查找最大的轮廓,那么问题也比较简单了,直接找出所有的轮廓,然后根据轮廓的面积,遍历查找出最大的轮廓即可。如果是找最大的外轮廓,那么问题也比较简单,因为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、找出内轮廓中的最大轮廓
这是我目前想到的方法,如果读到这篇博文的读者,有更好的方法和建议,欢迎提出。