A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

内容来自OpenCV-Python Tutorials 自己翻译整理

目标:
轮廓的层次结构、父子关系

原理:
使用cv2.findContours函数查找轮廓时需要传入一个轮廓提取模式的参数(Contour_Retrieval_Mode),通常设置为cv2.RETR_LIST 和 cv2.RETR_TREE。代表什么意思?
结果会得到三个数组,第一个是图像,第二个是轮廓,第三个是层次结构,下面要讨论关于层次结构。

啥是层次结果?
使用函数 cv2.findContours查找轮廓时,图片中的对象可能位于不同位置。如果有一个形状在另外一个形状的内部,这时称在外部的形状为父,内部形状为子孙。如此下来,图像中的轮廓建立了父子关系。如下面例子。

图中有一堆编号,0-5。其中2和2a代表最外层矩形的外轮廓和内轮廓。
轮廓0,1,2在外部或者最外部。可以称之为0级,也就是这些轮廓属于同一级。(没出现被别的轮廓套圈的现象)
下面的轮廓2a,被当成2号轮廓的子轮廓。该轮廓为1级轮廓。同理,轮廓3是轮廓2的自轮廓,为第三级,轮廓4,5位3a的自轮廓,为第四级。
综上,轮廓的层次结构大概分为外轮廓、子轮廓、父轮廓。

opencv中的层次结构
无论任何层次结构,每个轮廓都有自己的父子关系。opencv中使用含有四个元素的数组表示[Next ,Previous ,First_Child ,Parent]

  • Next表示同一级组织结构中的下一个轮廓,上图中轮廓0为例子,轮廓1就是轮廓0的Next。轮廓2在同一级没有Next,此时Next为-1
  • Previous表示同一级的前一个轮廓,轮廓1的Previous为轮廓0,轮廓0的Previous不存在,为-1。
  • First_Child表示第一个子轮廓,轮廓2的子轮廓为2a,轮廓3a的子轮廓有两个,但是第一个是轮廓4.
  • Parent表示父轮廓,与First_Child相反即可

综上,没有父子结构,结果就是-1

轮廓查找模式

RETR_LIST:
最简单的基本方式,只提取所有轮廓,不建立父子关系。即所有轮廓都属于同一级。
所以,在此模式下。组织结构数组的第3,4个参数都是-1。但是,Next和Previous要有对应值。如下结果,第一行对应轮廓0,下一行对应轮廓1,所以Next=1,前面没有其他轮廓,所以Previous=0。剩下的两个参数是-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]]])


如果不需要轮廓的关系,可以使用此参数


RETR_EXTERNAL:

只返回最外边的轮廓,所有子轮廓会忽略。

上图使用此模式只返回最外的第0级轮廓,即轮廓0,1,2.

结果如下:


>>> hierarchy

array([[[ 1, -1, -1, -1],

        [ 2, 0, -1, -1],

        [-1, 1, -1, -1]]])

RETR_CCOMP:
此模式会返回所有轮廓,并分为两级结构。
一个对象的外轮廓为第一级结构,对象内部中空洞的轮廓为第二级结构,空洞中的任何对象的轮廓又是第一级结构。例如,黑底白字的数字0的图像,0的外边界属于第一级组织结构,0的内部属于第二级组织结构。

绿色为组织结构。
考虑轮廓0,它为第一级。其中有两个空洞1和2,它们属于第二级。所以和轮廓0属于用一级的为下一个(Next)轮廓为轮廓3,且没有Previous。它的First_Child为轮廓1,组织结构为2。由于它是第 1 级,所以没有父轮廓。因此它的组织结构数组为[3,-1,1,-1]。
考虑轮廓1,它属于第二级。同一级的轮廓又轮廓2,没有Previous也没有Child,父轮廓为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]

结构如下:

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

RETR_TREE:
此模式返回所以轮廓,并且创建完整组织列表。告诉你爷爷、父亲、儿子、孙子的关系。
橙色为轮廓序号,绿色为组织结构。

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

计算结果如下:

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


5 个回复

倒序浏览
奈斯,优秀
回复 使用道具 举报
回复 使用道具 举报
回复 使用道具 举报
回复 使用道具 举报
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马