前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >opencv 9 -- 轮廓 层次结构

opencv 9 -- 轮廓 层次结构

作者头像
wust小吴
发布2019-07-08 18:27:40
7850
发布2019-07-08 18:27:40
举报
文章被收录于专栏:风吹杨柳风吹杨柳

轮廓之间的父子关系

使用函数 cv2.findContours 来查找轮廓, 我们需要传入一个参数:轮廓提取模式(Contour_Retrieval_Mode)。 我们总是 把它设置为 cv2.RETR_LIST 或者是 cv2.RETR_TREE,效果还可以。 但是它们到底代表什么呢? 同时,我们得到的结果包含 3 个数组, 第一个图像,第二个是轮廓,第三个是层次结构。 但是我们从来没有用过层次结构

层次结构是用来干嘛的呢? 层次结构与轮廓提取模式有什么关系呢?

1 什么是层次结构

通常我们使用函数 cv2.findContours 在图片中查找一个对象。 有时对象可能位于不同的位置。 还有些情况,一个形状在另外一个形状的内部。 这种情况下我们称外部的形状为父,内部的形状为子。

按照这种方式分类,一幅图像中的所有轮廓之间就建立父子关系。 这样我们就可以确定一个轮廓与其他轮廓是怎样连接的, 比如它是不是某个轮廓的子轮廓,或者是父轮廓。

这种关系 就成为组织结构

这里写图片描述
这里写图片描述

在这幅图像中,给这几个形状编号为 0-5。 2 和 2a 分别代表最外边矩形的外轮廓和内轮廓。

在这里边轮廓 0,1,2 在外部或最外边。 我们可以称他们为(组织结构) 0 级,简单来说就是他们属于同一级

接下来轮廓 2a。 我们把它当成轮廓 2 的子轮廓。它就成为(组织结构)第 1 级。

同样轮廓 3 是轮廓 2 的子轮廓,成为(组织结构)第 3 级。

最后轮廓 4,5 是轮廓 3a 的子轮廓,成为(组织结构)4 级(最后一级)。

按照这种方式 给这些形状编号, 我们可以说轮廓 4 是轮廓 3a 的子轮廓(当然轮廓 5 也是)。

2 OpenCV 中层次结构

不管层次结构是什么样的,每一个轮廓都包含自己的信息: 谁是父,谁 是子等。

OpenCV 使用一个含有四个元素的数组表示:

[Next,Previous, First_Child,Parent]

Next

表示同一级组织结构中的下一个轮廓。

以上图中的轮廓 0 为例,轮廓 1 就是他的 Next

同样,轮廓 1 的 Next 是 2,Next=2

那轮廓 2 呢?在同一级没有 Next。这时 Next=-1

而轮廓 4 的 Next 为 5,所以它的 Next=5

Previous

表示同一级结构中的前一个轮廓

与前面一样,轮廓 1 的 Previous 为轮廓 0,轮廓 2 的 Previous 为轮 廓 1

轮廓 0 没有 Previous,所以 Previous=-1

First_Child

表示它的第一个子轮廓。 没有必要再解释了,轮廓 2 的子轮廓为 2a。 所以它的 First_Child 为 2a。 那轮廓 3a 呢?它有两个子轮廓。 但是我们只要第一个子轮廓,所以是轮 廓 4(按照从上往下,从左往右的顺序排序)

Parent

表示它的父轮廓。 与 First_Child 刚好相反。 轮廓 4 和 5 的父轮廓是轮廓 3a。 而轮廓 3a 的父轮廓是 3

注意:如果没有父或子,就为 -1

cv2.RETR_LIST,cv2.RETR_TREE,cv2.RETR_CCOMP,cv2.RETR_EXTERNAL 到底代表什么意思?

1 、轮廓检索模式 cv2.RETR_LIST

RETR_LIST 从解释的角度来看,这种应是最简单的。 它只是提取所有的轮 廓,而不去创建任何父子关系。 换句话说就是“人人平等”,它们属于同一级组 织轮廓

所以在这种情况下,组织结构数组的第三和第四个数都是 -1。 但是,很明 显,Next 和 Previous 要有对应的值

代码语言:javascript
复制
>>> 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 级):轮廓 0,1,2

代码语言:javascript
复制
>>> hierarchy
array([[
[1,-1,-1,-1],
[2, 0,-1,-1],
[-1, 1, -1, -1]]])

当你只想得到最外边的轮廓时,你可以选择这种模式。这在有些情况下很 有用

3、RETR_CCOMP

在这种模式下会返回所有的轮廓并将轮廓分为两级组织结构。 例如,一个对象的外轮廓为第 1 级组织结构。 而对象内部中空洞的轮廓为 第 2 级组织结构, 空洞中的任何对象的轮廓又是第 1 级组织结构。 空洞的组织 结构为第 2 级。 想象一下一副黑底白字的图像,图像中是数字 0。 0 的外边界属于第一级 组织结构,0 的内部属于第 2 级组织结构。 我们可以以下图为例简单介绍一下。我们已经用红色数字为这些轮廓编号, 并用绿色数字代表它们的组织结构。顺序与 OpenCV 检测轮廓的顺序一致

这里写图片描述
这里写图片描述

现在我们考虑轮廓 0,它的组织结构为第 1 级。 其中有两个空洞 1 和 2, 它们属于第 2 级组织结构。 所以对于轮廓 0 来说跟他属于同一级组织结构的 下一个(Next)是轮廓 3, 并且没有Previous。

它的 Fist_Child 为轮廓 1, 组织结构为 2。 由于它是第 1 级,所以没有父轮廓。 因此它的组织结构数组为 [3,-1,1,-1]。

现在是轮廓 1,它是第 2 级。 处于同一级的下一个轮廓为 2。 没有 Previous,也没有 Child, (因为是第 2 级所以有父轮廓)父轮廓是 0。 所以数组是 [2,-1,-1,0]。

轮廓 2:它是第 2 级。 在同一级的组织结构中没有 Next。 Previous 为轮 廓 1。 没有子,父轮廓为 0, 所以数组是 [-1,1,-1,0]

轮廓 3:它是第 1 级。 在同一级的组织结构中 Next 为 5。 Previous 为 轮廓 0。 子为 4,没有父轮廓, 所以数组是 [5,0,4,-1]

轮廓 4:它是第 2 级。 在同一级的组织结构中没有 Next。 没有 Previous, 没有子,父轮廓为 3, 所以数组是 [-1,-1,-1,3]

代码语言:javascript
复制
>>> 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

这种模式下会返回 所有轮廓,并且创建一个完整的组织结构列表。 它甚至会告诉你谁是爷爷,爸 爸,儿子,孙子等

还是以上图为例,使用这种模式,对 OpenCV 返回的结果重新排序并分 析它, 红色数字是边界的序号,绿色是组织结构

轮廓 0 的组织结构为 0, 同一级中 Next 为 7,没有 Previous。 子轮廓 是 1, 没有父轮廓。 所以数组是 [7,-1,1,-1]。

轮廓 1 的组织结构为 1, 同一级中没有其他,没有 Previous。 子轮廓是 2,父轮廓为 0。 所以数组是 [-1,-1,2,0]

代码语言:javascript
复制
>>> 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]]])
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年05月22日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 什么是层次结构
  • 2 OpenCV 中层次结构
  • Next
  • Previous
  • First_Child
  • Parent
  • 1 、轮廓检索模式 cv2.RETR_LIST
  • 2、RETR_EXTERNAL
  • 3、RETR_CCOMP
  • 4、RETR_TREE
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档