OpenCV竟然可以这样学!成神之路终将不远(二十一)

简介: OpenCV竟然可以这样学!成神之路终将不远(二十一)

 返回目录

 

目录

21 轮廓分层

21.1 理论

21.1.1 层次结构是什么?

21.1.2 OpenCV中的分级表示

21.2 轮廓检索模式

21.2.1 RETR_LIST

21.2.2 RETR_EXTERNAL

21.2.3 RETR_CCOMP

21.2.4 RETR_TREE


21 轮廓分层

这次我们学习轮廓的层次,即轮廓中的父子关系。

21.1 理论

在前几篇关于轮廓的文章中,我们已经讨论了与OpenCV提供的轮廓相关的几个函数。但是当我们使用cv.findcontour()函数在图像中找到轮廓时,我们已经传递了一个参数,轮廓检索模式。我们通常通过了cv.RETR_LISTcv.RETR_TREE,效果很好。但这到底意味着什么呢?

另外,在输出中,我们得到了三个数组,第一个是图像,第二个是轮廓,还有一个我们命名为hierarchy的输出(请检查前面文章中的代码)。但我们从未在任何地方使用过这种层次结构。那么这个层级是什么?它是用来做什么的?它与前面提到的函数参数有什么关系?

这就是我们在本文中要讨论的内容。

21.1.1 层次结构是什么?

通常我们使用cv.findcontour()函数来检测图像中的对象,对吧?有时对象在不同的位置。但在某些情况下,某些形状在其他形状中。就像嵌套的图形一样。在这种情况下,我们把外部的称为父类,把内部的称为子类。这样,图像中的轮廓就有了一定的相互关系。我们可以指定一个轮廓是如何相互连接的,比如,它是另一个轮廓的子轮廓,还是父轮廓等等。这种关系的表示称为层次结构。

下面是一个例子:

image.gif编辑

在这张图中,有一些形状我已经从0-5开始编号。2和2a表示最外层盒子的外部和内部轮

廓。

这里,等高线0,1,2在外部或最外面。我们可以说,它们在层级0中,或者简单地说,它们

在同一个层级中。

其次是contour2a。它可以被认为是contour2的子级(或者反过来,contour-2是contour-2a

的父级)。假设它在层级1中。类似地,contour3是contour2的子级,它位于下一个层次结构

中。最后,轮廓4,5是contour3a的子级,他们在最后一个层级。从对方框的编号来看,我认为

contour4是contour3a的第一个子级(它也可以是contour5)。

我提到这些是为了理解一些术语,比如相同层级,外部轮廓,子轮廓,父轮廓,第一个子轮廓等等。现在让我们进入OpenCV。

21.1.2 OpenCV中的分级表示

所以每个轮廓都有它自己的信息关于它是什么层次,谁是它的孩子,谁是它的父母等等。OpenCV将它表示为一个包含四个值的数组: [Next,Previous,First_Child,Parent]

“Next表示同一层次的下一个轮廓。”

例如,在我们的图片中取contour0。谁是下一个同级别的等高线?这是contour1。简单地令Next=1 。类似地,Contour1也是contour2。所以Next = 2 。 contour2呢?同一水平线上没有下一条等高线。简单地,让Next = -1 。contour4呢?它与contour-5处于同一级别。它的下一条等高线是contour5,所以next = 5 。

“Previous表示同一层次上的先前轮廓。”

和上面一样。contour1之前的等值线为同级别的contour0。类似地,contour2也是contour1。

对于contour0,没有前项,所以设为-1。

“First_Child表示它的第一个子轮廓。”

没有必要作任何解释。对于contour2,child是contour2a。从而得到contour2a对应的指标值。contour3a呢?它有两个孩子。但我们只关注第一个孩子。它是contour4。那么First_Child = 4对contour3a而言。

“Parent表示其父轮廓的索引。”

它与First_Child相反。对于轮廓线4和轮廓线5,父轮廓线都是轮廓线3a。对于轮廓3a,它是

轮廓3,以此类推。

注意:如果没有子元素或父元素,则该字段被视为-1

现在我们已经了解了OpenCV中使用的层次样式,我们可以借助上面给出的相同图像来检查OpenCV中的轮廓检索模式。一些标志如 cv.RETR_LISTcv.RETR_TREEcv.RETR_CCOMPcv.RETR_EXTERNAL等等的含义。

21.2 轮廓检索模式

21.2.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]]])

image.gif

如果您没有使用任何层次结构特性,那么这是在您的代码中使用的最佳选择。

21.2.2 RETR_EXTERNAL

如果使用此标志,它只返回极端外部标志。所有孩子的轮廓都被留下了。我们可以说,根据这项规则,每个家庭只有长子得到关注。它不关心家庭的其他成员:)。

所以在我们的图像中,有多少个极端的外轮廓?在等级0级?有3个,即等值线是0 1 2,对吧?现在试着用这个标志找出等高线。这里,给每个元素的值与上面相同。并与上述结果进行了比较。以下是我得到的:

>>> hierarchy
array([[[ 1, -1, -1, -1],
[ 2, 0, -1, -1],
[-1, 1, -1, -1]]])

image.gif

如果只想提取外部轮廓,可以使用此标志。它在某些情况下可能有用。

21.2.3 RETR_CCOMP

此标志检索所有轮廓并将其排列为2级层次结构。物体的外部轮廓(即物体的边界)放在层次结构-1中。对象内部孔洞的轮廓(如果有)放在层次结构-2中。如果其中有任何对象,则其轮廓仅在层次结构1中重新放置。以及它在层级2中的漏洞等等。

只需考虑在黑色背景上的“白色的零”图像。零的外圆属于第一级,零的内圆属于第二级。

我们可以用一个简单的图像来解释它。这里我用红色标注了等高线的顺序和它们所属的层次,用绿色标注(1或2),顺序与OpenCV检测等高线的顺序相同。

image.gif编辑

考虑第一个轮廓,即contour0。这是hierarchy1。它有两个孔,分别是等高线1和2,属于第二级。因此,对于轮廓0,在同一层次的下一个轮廓是轮廓3。previous也没有。在hierarchy2中,它的第一个子结点是contour1。它没有父类,因为它在hierarchy1中。所以它的层次数组是[3, -1, 1, -1]。

现在contour1。它在层级2中。相同层次结构中的下一个(在contour1的父母关系下)是

contour2。没有previous。没有child ,但是parent是contour0。所以数组是[2,-1,-1,0]

类似的contour2:它在hierarchy2中。在contour0下,同一层次结构中没有下一个轮廓。所以没有Next 。previous 是contour1。没有child , parent 是contour0。所以数组是[-1, 1, -1, 0]

contour3:层次1的下一个是轮廓5。以前是contour0。child 是contour4,没有parent 。所以数组是[5, 0, 4, -1]

contour4:它在contour3下的层次结构2中,它没有兄弟姐妹。没有next ,没有previous ,没有

child,parent是contour3。所以数组是[-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]]])

image.gif

21.2.4 RETR_TREE

这是最后一个家伙,完美先生。它检索所有的轮廓并创建一个完整的家族层次结构列表。它甚至告诉,谁是爷爷,父亲,儿子,孙子,甚至更多…:)。

例如,我拿上面的图片,重写了cv的代码。RETR_TREE,根据OpenCV给出的结果重新排序等高线并进行分析。同样,红色的字母表示轮廓数,绿色的字母表示层次顺序。

image.gif编辑

取contour0:它在hierarchy0 中。同一层次结构的next轮廓是轮廓7。没有previous的轮

廓。child是contour1,没有parent。所以数组是[7, -1, 1, -1]

以contour2 为例:它在hierarchy1中。没有轮廓在同一水平。没有previous 。child 是

contour3 。父母是contour1 。所以数组是[-1, -1, 3, 1]

剩下的,你自己试试。以下是完整答案:

>>> hierarchy
array([[[ 7, -1, 1, -1],
[-1, -1, 2, 0],
[-1, -1, 3, 1],
[-1, -1, 4, 2],
[-1, -1, 5, 3],
[ 6, -1, -1, 4],
[-1, 5, -1, 4],
[ 8, 0, -1, -1],
[-1, 7, -1, -1]]])

image.gif


欢迎评论区留言,一起探讨OpenCV成神之路的奥秘。

顺便给我加个关注,点个赞,加个收藏,让我们一起登上神坛。

image.gif编辑

相关文章
|
9月前
|
机器学习/深度学习 编解码 计算机视觉
OpenCV竟然可以这样学!成神之路终将不远(十六)
OpenCV竟然可以这样学!成神之路终将不远(十六)
|
9月前
|
计算机视觉 Python
OpenCV竟然可以这样学!成神之路终将不远(十)
OpenCV竟然可以这样学!成神之路终将不远(十)
|
9月前
|
算法 计算机视觉 Python
OpenCV竟然可以这样学!成神之路终将不远(二十六)
OpenCV竟然可以这样学!成神之路终将不远(二十六)
|
9月前
|
算法 计算机视觉 索引
OpenCV竟然可以这样学!成神之路终将不远(二十五)
OpenCV竟然可以这样学!成神之路终将不远(二十五)
|
9月前
|
计算机视觉 Python
OpenCV竟然可以这样学!成神之路终将不远(二十四)
OpenCV竟然可以这样学!成神之路终将不远(二十四)
|
9月前
|
计算机视觉 Python
OpenCV竟然可以这样学!成神之路终将不远(二十三)
OpenCV竟然可以这样学!成神之路终将不远(二十三)
|
9月前
|
计算机视觉 索引 Python
OpenCV竟然可以这样学!成神之路终将不远(二十二)
OpenCV竟然可以这样学!成神之路终将不远(二十二)
|
9月前
|
文字识别 计算机视觉 索引
OpenCV竟然可以这样学!成神之路终将不远(二十)
OpenCV竟然可以这样学!成神之路终将不远(二十)
|
9月前
|
定位技术 计算机视觉 Python
OpenCV竟然可以这样学!成神之路终将不远(十九)
OpenCV竟然可以这样学!成神之路终将不远(十九)
|
9月前
|
算法 计算机视觉 索引
OpenCV竟然可以这样学!成神之路终将不远(十八)
OpenCV竟然可以这样学!成神之路终将不远(十八)