OpenCV中findContours轮廓提取一个边缘只对应的一个轮廓

  • Post author:
  • Post category:其他

OpenCV中findContours轮廓提取一个边缘只对应的一个轮廓


众所周知,图像查找轮廓可以用findContours函数解决,但是不知道大家发现一个问题没有,有时候输入图像,得到的结果会出现图像中一条边缘有查找到两个轮廓。当然只提取最外轮廓是不会出现重复情况,但设置提取所有轮廓会出现两个轮廓,对于利用得到的轮廓进一步处理带来不必要的麻烦。现在网上很多讲解findContours()函数都是讲解参数的,当真的用到这个函数会发现跟自己的结果并不如意。下面我就以我有限的感悟谈一下如何利用findContours()得到一条边缘得到对应的一个轮廓,当然不会去修改这个函数的代码。

findContours()函数参数讲解

  • 输入image;
  • 输出contours,是二维向量的Point。如:vector< vector>contours;
  • hierarchy;每个轮廓的信息,后面要用到这些重要信息。
  • mode;轮廓检索模式,网上很多参数说明。
  • method;轮廓的近似办法。
  • offset;我没用过,直接默认参数。

提取一个边缘只对应的一个轮廓

这里说一下mode这个参数。
RETR_EXTERNAL:表示只检测最外层轮廓,意思是图像中独立的个体只检测最外层轮廓,包含在里面的轮廓不会提取出来。
RETR_LIST:提取所有轮廓,并放置在list中,不建立等级关系。意思就是提取出来的轮廓之间是没有联系的。
RETR_CCOMP:提取所有轮廓,并且将其组织为双边结构。意思就是第一层为它的外围轮廓,第二层为内围轮廓,利用这个参数可以筛选出来一个独立边缘只对应一个轮廓。
RETR_TREE:提取所有轮廓,并且重新建立网状轮廓结构。它体现出来的轮廓联系很紧密,比如说一个轮廓在另外一个轮廓的里面,轮廓里面又包含轮廓。
对了,在参数method中有个标识符–CV_CHAIN_CODE,是生成Freeman码的,但是OpenCV提供的C++接口好像不好提取,还没有深究,C接口的代码我有,网上荡的,在百度知道搜的,那不缺大神哦。

前面讲了那么多,进入正题吧。其实所有的轮廓关系在参数hierarchy中体现,大家可以调试看看那里面的值。hierarchy[i][0]–hierarchy[i][3]依次表示轮廓的后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓,如果没有对应项,设置为-1。
我们要得到一个边缘只对应的一个轮廓,需要在mode参数设置为RETR_CCOMP,表示双层结构,利用hierarchy中的信息筛选出轮廓。
如下图,其实只有四个轮廓,但查找出来了七个轮廓。
这里写图片描述

hierarchy信息中对应的 值

元素
hierarchy[ 0] 2,-1,1,-1
hierarchy[ 1] -1,-1,-1,0
hierarchy[ 2] 4,0,3,-1
hierarchy[ 3] -1,-1,-1,2
hierarchy[ 4] 6,2,5,-1
hierarchy[ 5] -1,-1,-1,4
hierarchy[ 6] -1,4,-1,-1

由上表可以发现,每个hierarchy[i][0]对应的值指示下一个轮廓,注意,这里下一个轮廓指的是另外的轮廓,不是同一个边缘的另外一个轮廓。所以我们利用这个信息可以筛选出一个边缘的一条轮廓,分别是0->2->4->6四条轮廓。
贴一下代码:

vector<int>Index;
for(int i=0;i<contours.size();)
{
    int next=hierarchy[i][0];
    Index.push_back(i);
    i=next;
    if(i==-1)
        break;
}

输出的结果Index为(0,2,4,6)。

总结

需要用得到的轮廓做下一步处理可以使用这个方法免去多余的运算。其实也不算是方法,也就是自己一点点感悟吧,毕竟我自己也是学习者,还有很多不懂得地方。希望我这点感悟对您有所帮助,写的不对的地方还望见谅,谢谢!


版权声明:本文为liumangmao1314原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。