OpenCV-Python 轮廓分层 | 二十五
目标
这次我们学习轮廓的层次,即轮廓中的父子关系。
理论
在前几篇关于轮廓的文章中,我们已经讨论了与OpenCV提供的轮廓相关的几个函数。但是当我们使用cv.findcontour()函数在图像中找到轮廓时,我们已经传递了一个参数,轮廓检索模式。我们通常通过了cv.RETR_LIST或cv.RETR_TREE,效果很好。但这到底意味着什么呢?
另外,在输出中,我们得到了三个数组,第一个是图像,第二个是轮廓,还有一个我们命名为hierarchy的输出(请检查前面文章中的代码)。但我们从未在任何地方使用过这种层次结构。那么这个层级是什么?它是用来做什么的?它与前面提到的函数参数有什么关系?
这就是我们在本文中要讨论的内容。
层次结构是什么?
通常我们使用cv.findcontour()函数来检测图像中的对象,对吧?有时对象在不同的位置。但在某些情况下,某些形状在其他形状中。就像嵌套的图形一样。在这种情况下,我们把外部的称为父类,把内部的称为子类。这样,图像中的轮廓就有了一定的相互关系。我们可以指定一个轮廓是如何相互连接的,比如,它是另一个轮廓的子轮廓,还是父轮廓等等。这种关系的表示称为层次结构。
下面是一个例子:
在这张图中,有一些形状我已经从0-5开始编号。2和2a表示最外层盒子的外部和内部轮廓。
这里,等高线0,1,2在外部或最外面。我们可以说,它们在层级-0中,或者简单地说,它们在同一个层级中。
其次是contour-2a。它可以被认为是contour-2的子级(或者反过来,contour-2是contour-2a的父级)。假设它在层级-1中。类似地,contour-3是contour-2的子级,它位于下一个层次结构中。最后,轮廓4,5是contour-3a的子级,他们在最后一个层级。从对方框的编号来看,我认为contour-4是contour-3a的第一个子级(它也可以是contour-5)。
我提到这些是为了理解一些术语,比如相同层级,外部轮廓,子轮廓,父轮廓,第一个子轮廓等等。现在让我们进入OpenCV。
OpenCV中的分级表示
所以每个轮廓都有它自己的信息关于它是什么层次,谁是它的孩子,谁是它的父母等等。OpenCV将它表示为一个包含四个值的数组:[Next, Previous, First_Child, Parent]
“Next表示同一层次的下一个轮廓。”
例如,在我们的图片中取contour-0。谁是下一个同级别的等高线?这是contour-1。简单地令Next = 1
。类似地,Contour-1也是contour-2。所以Next = 2
。
contour-2呢?同一水平线上没有下一条等高线。简单地,让Next = -1
。contour-4呢?它与contour-5处于同一级别。它的下一条等高线是contour-5,所以next = 5
。
“Previous表示同一层次上的先前轮廓。”
和上面一样。contour-1之前的等值线为同级别的contour-0。类似地,contour-2也是contour-1。对于contour-0,没有前项,所以设为-1。
“First_Child表示它的第一个子轮廓。”
没有必要作任何解释。对于contour-2, child是contour-2a。从而得到contour-2a对应的指标值。contour-3a呢?它有两个孩子。但我们只关注第一个孩子。它是contour-4。那么First_Child = 4
对contour-3a而言。
“Parent表示其父轮廓的索引。”
它与First_Child相反。对于轮廓线-4和轮廓线-5,父轮廓线都是轮廓线-3a。对于轮廓3a,它是轮廓-3,以此类推。
注意
如果没有子元素或父元素,则该字段被视为-1
现在我们已经了解了OpenCV中使用的层次样式,我们可以借助上面给出的相同图像来检查OpenCV中的轮廓检索模式。一些标志如 cv.RETR_LIST, cv.RETR_TREE,cv.RETR_CCOMP, cv.RETR_EXTERNAL等等的含义。
轮廓检索模式
1. RETR_LIST
这是四个标志中最简单的一个(从解释的角度来看)。它只是检索所有的轮廓,但不创建任何亲子关系。在这个规则下,父轮廓和子轮廓是平等的,他们只是轮廓。他们都属于同一层级。
这里,第3和第4项总是-1。但是很明显,下一项和上一项都有对应的值。你自己检查一下就可以了。
下面是我得到的结果,每一行是对应轮廓的层次细节。例如,第一行对应于轮廓0。下一条轮廓是轮廓1。所以Next = 1
。没有先前的轮廓,所以Previous=-1
。剩下的两个,如前所述,是-1
。
>>> hierarchy
array([[[ 1, -1, -1, -1],
[ 2, 0, -1, -1],
[ 3, 1, -1, -1],
[ 4, 2, -1, -1],
[ 5, 3, -1, -1],
[ 6, 4, -1, -1],
[ 7, 5, -1, -1],
[-1, 6, -1, -1]]])
如果您没有使用任何层次结构特性,那么这是在您的代码中使用的最佳选择。
2. RETR_EXTERNAL
如果使用此标志,它只返回极端外部标志。所有孩子的轮廓都被留下了。我们可以说,根据这项规则,每个家庭只有长子得到关注。它不关心家庭的其他成员:)。
所以在我们的图像中,有多少个极端的外轮廓?在等级0级?有3个,即等值线是0 1 2,对吧?现在试着用这个标志找出等高线。这里,给每个元素的值与上面相同。并与上述结果进行了比较。以下是我得到的:
>>> hierarchy
array([[[ 1, -1, -1, -1],
[ 2, 0, -1, -1],
[-1, 1, -1, -1]]])
如果只想提取外部轮廓,可以使用此标志。它在某些情况下可能有用。
3. RETR_CCOMP
此标志检索所有轮廓并将其排列为2级层次结构。物体的外部轮廓(即物体的边界)放在层次结构-1中。对象内部孔洞的轮廓(如果有)放在层次结构-2中。如果其中有任何对象,则其轮廓仅在层次结构1中重新放置。以及它在层级2中的漏洞等等。
只需考虑在黑色背景上的“白色的零”图像。零的外圆属于第一级,零的内圆属于第二级。
我们可以用一个简单的图像来解释它。这里我用红色标注了等高线的顺序和它们所属的层次,用绿色标注(1或2),顺序与OpenCV检测等高线的顺序相同。
考虑第一个轮廓,即contour-0。这是hierarchy-1。它有两个孔,分别是等高线1和2,属于第二级。因此,对于轮廓-0,在同一层次的下一个轮廓是轮廓-3。previous也没有。在hierarchy-2中,它的第一个子结点是contour-1。它没有父类,因为它在hierarchy-1中。所以它的层次数组是[3,-1,1,-1]
现在contour-1。它在层级-2中。相同层次结构中的下一个(在contour-1的父母关系下)是contour-2。没有previous。没有child
,但是parent
是contour-0。所以数组是[2,-1,-1,0]
类似的contour-2:它在hierarchy-2中。在contour-0下,同一层次结构中没有下一个轮廓。所以没有Next
。previous
是contour-1。没有child
,parent
是contour0。所以数组是[-1,1,-1,0]
contour-3:层次-1的下一个是轮廓-5。以前是contour-0。child
是contour4,没有parent
。所以数组是[5,0,4,-1]
contour-4:它在contour-3下的层次结构2中,它没有兄弟姐妹。没有next
,没有previous
,没有child
,parent
是contour-3。所以数组是[-1,-1,-1,3]
剩下的你可以补充。这是我得到的最终答案:
>>> hierarchy
array([[[ 3, -1, 1, -1],
[ 2, -1, -1, 0],
[-1, 1, -1, 0],
[ 5, 0, 4, -1],
[-1, -1, -1, 3],
[ 7, 3, 6, -1],
[-1, -1, -1, 5],
[ 8, 5, -1, -1],
[-1, 7, -1, -1]]])
4. RETR_TREE
这是最后一个家伙,完美先生。它检索所有的轮廓并创建一个完整的家族层次结构列表。它甚至告诉,谁是爷爷,父亲,儿子,孙子,甚至更多…
操作系统是用户和硬件沟通的桥梁 操作系统,位于底层硬件与应用软件之间的一层 工作方式:向下管理硬件,向上提供接口 操作系统进行切换操作: 把CPU的使用权切换给不同的进程. 1.出现IO操作 2.固定 ... 简介 在前边的第二十二篇文章里,已经分享了通过获取控件的坐标点来获取点击事件的所需要的点击位置,那么还有没有其他方法来获取控件点击事件所需要的点击位置呢?答案是:Yes!因为在不同的大小屏幕的手机上获 ... 转载自http://www.cnblogs.com/liwenzhou/p/8032238.html 一.Python3连接MySQL PyMySQL 是在 Python3.x 版本中用于连接 MyS ... 参考:匿名函数 NOTE 1.Python对匿名函数提供了有限的支持. eg. #!/usr/bin/env python3 def main(): lis = list(map(lambda x: ... 一.介绍 本例子用Selenium +phantomjs爬取今日头条(http://www.toutiao.com/search/?keyword=电视)的资讯信息,输入给定关键字抓取资讯信息. 给定 ... 接口类 继承有两种用途:继承基类的方法,并且做出自己的改变或扩展(代码重用)和声明某个子类兼容于某基类,定义一个接口类interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子 ... import requestsimport unittest class TestQQ(unittest.TestCase): '''测试QQ号接口''' # 此注释将展示到测 ... # 链表 cars = ['a', "b"] print(cars) # 链表长度 print(len(cars)) # 结尾添加元素 cars.append("c&qu ... 二十五. Python基础(25)--模块和包 ● 知识框架 ● 模块的属性__name__ # my_module.py def fun1(): print("Hello& ... 王尔德曾说过,"一个人应该永远保持一点神秘感".让·保·里克特也表示,:"一个人泄露了秘密,哪怕一丝一毫,就再也得不到安宁了".可见,对于自然人来说,保有自 ... 视频描述 顾名思义视频描述是计算机对视频生成一段描述,如图所示,这张图片选取了一段视频的两帧,针对它的描述是"A man is doing stunts on his bike", ... 疫情禁足在家,用原生的JS实现了一个HTML可视化编辑工具,页面布局基于Bootstrap.大约一个月时间,打通主要技术关卡,实现了第一版: 可以拖放编辑,实现了几乎所有的bootstrap预定义 ... 纠结两天(浏览器中唤起本地APP),一直找不到解决方案,今天总算基本搞定. ps:吐槽一下 魔窗那篇文章,为什么就不直接把js代码开源开源,混淆后的代码看得我好恼火 参考文章:魔窗解决方案.京东解决方 ... 一 go module 常用命令 模块维护:go mod command arguments创建模块:go mod init example.com/hello清除无用依赖: go mod tidy ... 注:如需转载,请附上原文链接,如有建议或意见,欢迎批评指正! 需求说明: // index.jsp页面 1 <% 2 String basePath = request.getScheme() ... 1.---- cd /usr/local/src/php-5.5.34/ext/mysql/2.---- /usr/local/php5/bin/phpize3.---- ./configure ... 1.作用 在图片较多的页面中,页面加载性能较差.使用图片懒加载可以让图片出现在可视区域时再进行加载,从而提高用户体验. 2.原理 设置img标签的src属性为空或统一的图片路径(如加载中样式),监听页 ... <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ... 一.了解 CentOS中如果安装有yum,一般会有python2的某个版本.命令行键入python,出现的python2的环境: [root@instance-hrnebyqu src]# pytho ...OpenCV-Python 轮廓分层 | 二十五的更多相关文章
随机推荐