轮廓的层次结构
目标
  现在我们要学习轮廓的层次结构了,比如轮廓之间的父子关系。
  
原理
  在前面的内容中我们使用函数 cv2.findContours 来查找轮廓,我们需要传入一个参数:轮廓提取模式(Contour_Retrieval_Mode)。我们总是把它设置为 cv2.RETR_LIST 或者是 cv2.RETR_TREE,效果还可以。但是它们到底代表什么呢?
  
  同时,我们得到的结果包含 3 个数组,第一个图像,第二个是轮廓,第三个是层次结构。但是我们从来没有用过层次结构。层次结构是用来干嘛的呢?层次结构与轮廓提取模式有什么关系呢?

什么是层次结构
  
  通常我们使用函数 cv2.findContours 在图片中查找一个对象。有时对象可能位于不同的位置。还有些情况,一个形状在另外一个形状的内部。这种情况下我们称外部的形状为父,内部的形状为子。按照这种方式分类,一幅图像中的所有轮廓之间就建立父子关系。这样我们就可以确定一个轮廓与其他轮廓是怎样连接的,比如它是不是某个轮廓的子轮廓,或者是父轮廓。这种关系就成为组织结构

下图就是一个简单的例子:

  在这幅图像中,我给这几个形状编号为 0-5。2 和 2a 分别代表最外边矩形的外轮廓和内轮廓。
  
  在这里边轮廓 0,1,2 在外部或最外边。我们可以称他们为(组织结构)0 级,简单来说就是他们属于同一级。
  接下来轮廓 2a。我们把它当成轮廓 2 的子轮廓。它就成为(组织结构)第1 级。同样轮廓 3 是轮廓 2 的子轮廓,成为(组织结构)第 3 级。最后轮廓4,5 是轮廓 3a 的子轮廓,成为(组织结构)4 级(最后一级)。按照这种方式给这些形状编号,我们可以说轮廓 4 是轮廓 3a 的子轮廓(当然轮廓 5 也是)。
  
  我说这么多就是为了解释层次结构,外轮廓,子轮廓,父轮廓,子轮廓等。现在让我们进入 OpenCV 吧。
  
  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。

现在我们了解了 OpenCV 中的轮廓组织结构。我们还是根据上边的图片再学习一下 OpenCV 中的轮廓检索模式。
cv2.RETR_LIST,cv2.RETR_TREE,cv2.RETR_CCOMP,cv2.RETR_EXTERNAL到底代表什么意思?

轮廓检索模式
  RETR_LIST 从解释的角度来看,这中应是最简单的。它只是提取所有的轮廓,而不去创建任何父子关系。换句话说就是“人人平等”,它们属于同一级组织轮廓。
  
  所以在这种情况下,组织结构数组的第三和第四个数都是 -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 在这种模式下会返回所有的轮廓并将轮廓分为两级组织结构。例如,一个对象的外轮廓为第 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]
下面是我得到的答案:

>>> 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 终于到最后一个了,也是最完美的一个。这种模式下会返回所有轮廓,并且创建一个完整的组织结构列表。它甚至会告诉你谁是爷爷,爸爸,儿子,孙子等。

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


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

OpenCV 中的轮廓-轮廓的层次结构相关推荐

  1. android opencv画轮廓,如何在Android的OpenCV中从每个轮廓提取线条?

    我想检查每个Canny检测到的边缘,并在其中寻找主线(以检查它们是否看起来像一个矩形,例如,两对线是否平行等). Imgproc.HoughLinesP可以满足我的要求,但是它给出了整个图像中的线条, ...

  2. opencv补全边缘_为什么OpenCV中绘制的轮廓不能填充图像边缘的轮廓?

    编辑:我绕过了这个问题,在图像中添加了一个2位帧,然后使用我的代码,最后剪切图像以删除多余的帧.这是一个丑陋的解决方案,但它的工作! 我遇到了一个问题,我不确定这是一个错误还是我缺乏经验.我会尽量把它 ...

  3. OpenCV-Python 中文教程15——OpenCV 中的轮廓

    OpenCV-Python 中文教程15--OpenCV 中的轮廓 一.初识轮廓 目标 • 理解什么是轮廓 • 学习找轮廓,绘制轮廓等 • 函数: cv2.findContours(), cv2.dr ...

  4. (三)OpenCV中的图像处理之轮廓

    注释:本文翻译自OpenCV3.0.0 document->OpenCV-Python Tutorials,包括对原文档种错误代码的纠正 该章节分为以下四个小节: (一)     Contour ...

  5. OpenCV学习笔记(12)——OpenCV中的轮廓

    什么是轮廓 找轮廓.绘制轮廓等 1.什么是轮廓 轮廓可看做将连续的点(连着边界)连在一起的曲线,具有相同的颜色和灰度.轮廓在形态分析和物体的检测和识别中很有用. 为了更加准确,要使用二值化图像.在寻找 ...

  6. OpenCV中的轮廓及性质

    转:https://www.kancloud.cn/aollo/aolloopencv/272892 OpenCV中的轮廓 1.1什么是轮廓 轮廓可以简单认为成连续的点(连着边界)连在一起的曲线,具有 ...

  7. opencv+Recorder︱OpenCV 中的 Canny 边界检测+轮廓、拉普拉斯变换

    本文来自于段力辉 译<OpenCV-Python 中文教程> 边缘检测是图像处理和计算机视觉中的基本问题,通过标识数字图像中亮度变化明显的点,来捕捉图像属性中的显著变化,包括深度上的不连续 ...

  8. opencv 查找并绘制轮廓

    一个轮廓一般对应一系列的点, 也就是图像中的一条曲线.其表示方法可能根据不同的情况而有所不同. 在opencv中可以用findContours()函数从二值图像查找轮廓 findContours()函 ...

  9. Python-OpenCV中的图像处理 » 轮廓:入门

    目标: 了解什么是轮廓 学习查找轮廓,绘制轮廓 函数: cv.findContours(), cv.drawContours() 什么是轮廓? 轮廓可以简单地解释为连接所有具有相同的颜色或强度的连续点 ...

  10. 【opencv】(6) 图像轮廓处理

    各位同学好,今天和大家分享一下opencv中如何获取图像轮廓,以及对轮廓的一些其他操作.内容有: (1)轮廓检测:cv2.findContours():(2)轮廓绘制:cv2.drawContours ...

最新文章

  1. HelloServlet
  2. boost::hana::make_pair用法的测试程序
  3. python进程池调用实例方法_Python 多进程并发操作中进程池Pool的实例
  4. 【内核模块auth_rpcgss】netns引用计数泄露导致容器弹性网卡残留
  5. BZOJ 1113: [Poi2008]海报PLA
  6. python时间序列模型有哪些_时间序列模型(ARIMA)
  7. UnitySendMessage
  8. 台达A2/B2伺服电机编码器改功率 台达A2/B2伺服电机编码修改
  9. 自学通过CISSP备考心得
  10. Eviews的基本使用,简单线性回归分析
  11. 从学生到职场,这位百万爬虫博主都经历了什么?
  12. xshell 批量创建.xsh会话文件
  13. windows命令行将应用程序加入环境变量
  14. 8051蜂鸣器程序c语言,单片机有源蜂鸣器试验程序(带电路图)
  15. Ubuntu终端Terminator的安装与配置使用
  16. 程序员转行适合做什么?
  17. CORBA 架构体系指南(通用对象请求代理体系架构)
  18. python 颜色表
  19. 一键安装nginx脚本
  20. 1.已知本原多项式,利用Matlb中的simulink构成m序列产生器。2.已知任意本原多项式,利用matlb软件编程求解其对应的m序列以及m序列产生过程。

热门文章

  1. 记一次ubuntu系统崩溃的修复
  2. CA-IS3721HS 双通道标准数字隔离器简介
  3. mysql create default_MySQL中create table DEFAULT 用法
  4. SpringBoot下载网络文件并重命名,比如:excel
  5. idea忽略指定文件编译错误_Intellij IDEA设置忽略部分类编译错误
  6. msxml3.dll 错误 80072ee2解决方法 The operation timed out
  7. 两台电脑之间如何直接传资料
  8. mysql子查询重命名
  9. Linux(程序设计):55---非阻塞connect(EINPROGRESS)
  10. jQuery 子元素选择器 find() 和 children()