【OpenCV-Python】教程:3-9 轮廓(5)轮廓层级

news2025/7/22 11:09:10

OpenCV Python 轮廓层次

【目标】

  • 学习轮廓的层次关系

在前几个课程里面,学习了 cv2.findContours() 函数, 传递了参数 Contour Retrieval Mode . 通常是 cv.RETR_LIST or cv.RETR_TREE 工作的很好,但是他们是什么意思呢?
hierarchy 到底是什么呢?
在某些情况下,有些形状是在其他形状内部,就像层级一样。我们称上层的为 parent,内部的为 child。表达这种“父-子”关系形状轮廓称之为 Hierarchy

一个例子如下:

在这里插入图片描述

在这个图像中,有许多形状,我们标号为 0~522a 表明外部轮廓和内部轮廓。

0,1,2 都是最外层的轮廓,层级为0

轮廓 22a 的父轮廓,2a2 的子轮廓,定义为层级1;轮廓 3 是轮廓 2a 的子轮廓。

轮廓 4 是 轮廓 3a 的第一个子轮廓。

OpenCV 用 [Next, Previous, First_Child, Parent] 表示轮廓层级关系信息。

Next: 下一个的意思就是同一层级里下一个轮廓。如果第 0 个轮廓的下一个轮廓是 1 ,那么 Next = 1; 如果同一层级没有下一个轮廓,简单的就设置 Next = -1

Previous: 同一层级里前一个轮廓,与 Next 相反;同样,没有前一个轮廓,也设置为 -1

First_Child: 第一个子轮廓,不需要过多解释,对于轮廓 2 来说, 2a 是其子轮廓;对于轮廓 3a 来说,有两个子轮廓,轮廓 4 是第一个子轮廓。

Parent: 父轮廓的索引,与 First_Child 相反。对于轮廓 4 和轮廓 5 来说,他们的父轮廓都是 3a;

如果没有父轮廓或子轮廓,都设置为 -1

所以,我们已经直到了OpenCV里的轮廓层级关系,cv.RETR_LIST, cv.RETR_TREE, cv.RETR_CCOMP, cv.RETR_EXTERNAL 等等是什么意思呢?

1. RETR_LIST

这是4个标志里最简单的,提取所有的轮廓并存储下来,没有父子关系,在这里,他们都是同一个级别。

所以,第 3 个和第 4 个参数始终为 -1;但是很明显,下一个和前一个都是对应的值。例如存储的 层次信息如下:

[[  [ 1, -1, -1, -1],  # contours- 0
    [ 2,  0, -1, -1],  # contours- 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]]] # contours- 7

2. RETR_EXTERNAL

如果使用这个标志,那么只提取轮廓的最外层轮廓,所有子轮廓将不被存储,换句话说,一个轮廓有子轮廓和孙轮廓,一直向上回溯到该父轮廓没有父轮廓,才保留下来(一个轮廓家族留下最老的 😃)。

上图中,只有 0, 1, 2 才是最外层(最老的,没有父轮廓,层级为0)。

[[  [ 1, -1, -1, -1],   # contours- 0
    [ 2,  0, -1, -1],   # contours- 1
    [-1,  1, -1, -1]]]  # contours- 2

3. RETR_CCOMP

使用该标志时,将轮廓赋值为 2 个级别。最外层的级别为 1, 内部的层级为 2; 如果内部还有其他内部层级,循环使用级别 1 和 2

如下图所示:

在这里插入图片描述

绿色数字表示层级,外层的橙色表示轮廓序号;

轮廓 0 的层级为 1, 有两个洞(层级都是2),分别是轮廓 1 和轮廓 2,对于轮廓 0 来说,下一个轮廓是轮廓 3, 没有上一个轮廓; [3, -1, 1, -1]

[[  [ 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

这是最后一个标志,也是最完美的。检索所有轮廓并创建一个家族,告诉谁是儿子,谁是孙子,谁是父亲,谁是祖父等等。

结果如下:

在这里插入图片描述

对于轮廓 0 来说,层级为 0, 下一个同级轮廓为 7, 没有上一个轮廓,子轮廓为 1, 没有父轮廓,所以存储为

[7, -1, 1, -1]

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

【代码】

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

import cv2 

img = cv2.imread("contours.png", 0)
imgcolor = cv2.imread("contours.png", 1)
ret, thresh = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)

# RETR_LIST
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
colorRETR_LIST = imgcolor.copy()

print("\n")
print("RETR_LIST 轮廓的个数:", len(contours))
print("RETR_LIST 层级关系如下: ")
print(hierarchy)

font = cv2.FONT_HERSHEY_SIMPLEX
for i in range(len(contours)):
    # print("contour ", i, " contours pt =  ", contours[i][0, 0])
    # print("contour ", i, " hierarchy = ", hierarchy[0][i])
    textstr = str(i) + '-' + str(hierarchy[0][i])
    showpt = (contours[i][0, 0, 0] - 3, contours[i][0, 0, 1] + 3)
    cv2.putText(colorRETR_LIST, textstr, showpt, font, 0.4,
                (0, 0, 255), 1, cv2.LINE_AA)
cv2.imshow("colorRETR_LIST", colorRETR_LIST)
    
# RETR_EXTERNAL
contours, hierarchy = cv2.findContours(
    thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
colorRETR_EXTERNAL = imgcolor.copy()

print("\n")
print("RETR_EXTERNAL 轮廓的个数:", len(contours))
print("RETR_EXTERNAL 层级关系如下: ")
print(hierarchy)

font = cv2.FONT_HERSHEY_SIMPLEX
for i in range(len(contours)):
    textstr = str(i) + '-' + str(hierarchy[0][i])
    showpt = (contours[i][0, 0, 0] - 3, contours[i][0, 0, 1] + 3)
    cv2.putText(colorRETR_EXTERNAL, textstr, showpt, font, 0.4,
                (0, 0, 255), 1, cv2.LINE_AA)
cv2.imshow("colorRETR_EXTERNAL", colorRETR_EXTERNAL)


# RETR_CCOMP
contours, hierarchy = cv2.findContours(
    thresh, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
colorRETR_CCOMP = imgcolor.copy()

print("\n")
print("RETR_CCOMP 轮廓的个数:", len(contours))
print("RETR_CCOMP 层级关系如下: ")
print(hierarchy)

font = cv2.FONT_HERSHEY_SIMPLEX
for i in range(len(contours)):
    textstr = str(i) + '-' + str(hierarchy[0][i])
    showpt = (contours[i][0, 0, 0] - 3, contours[i][0, 0, 1] + 3)
    cv2.putText(colorRETR_CCOMP, textstr, showpt, font, 0.4,
                (0, 0, 255), 1, cv2.LINE_AA)
cv2.imshow("colorRETR_CCOMP", colorRETR_CCOMP)    
            
            
# RETR_TREE
contours, hierarchy = cv2.findContours(
    thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
colorRETR_TREE = imgcolor.copy()

print("\n")
print("RETR_TREE 轮廓的个数:", len(contours))
print("RETR_TREE 层级关系如下: ")
print(hierarchy)

font = cv2.FONT_HERSHEY_SIMPLEX
for i in range(len(contours)):
    textstr = str(i) + '-' + str(hierarchy[0][i])
    showpt = (contours[i][0, 0, 0] - 3, contours[i][0, 0, 1] + 3)
    cv2.putText(colorRETR_TREE, textstr, showpt, font, 0.4,
                (0, 0, 255), 1, cv2.LINE_AA)
cv2.imshow("colorRETR_TREE", colorRETR_TREE)


# cv2.imshow("img", thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()

输出结果如下:

RETR_LIST 轮廓的个数: 10
RETR_LIST 层级关系如下: 
[[[ 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]
  [ 8  6 -1 -1]
  [ 9  7 -1 -1]
  [-1  8 -1 -1]]]


RETR_EXTERNAL 轮廓的个数: 5
RETR_EXTERNAL 层级关系如下: 
[[[ 1 -1 -1 -1]
  [ 2  0 -1 -1]
  [ 3  1 -1 -1]
  [ 4  2 -1 -1]
  [-1  3 -1 -1]]]


RETR_CCOMP 轮廓的个数: 10
RETR_CCOMP 层级关系如下: 
[[[ 2 -1  1 -1]
  [-1 -1 -1  0]
  [ 3  0 -1 -1]
  [ 5  2  4 -1]
  [-1 -1 -1  3]
  [ 7  3  6 -1]
  [-1 -1 -1  5]
  [ 8  5 -1 -1]
  [ 9  7 -1 -1]
  [-1  8 -1 -1]]]


RETR_TREE 轮廓的个数: 10
RETR_TREE 层级关系如下: 
[[[ 1 -1 -1 -1]
  [ 7  0  2 -1]
  [-1 -1  3  1]
  [ 5 -1  4  2]
  [-1 -1 -1  3]
  [-1  3  6  2]
  [-1 -1 -1  5]
  [ 8  1 -1 -1]
  [ 9  7 -1 -1]
  [-1  8 -1 -1]]]

【参考】

  1. OpenCV官方文档

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/35625.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于DMF推荐算法的推荐系统 代码+数据 (可作为毕设)

案例知识点 推荐系统任务描述:通过用户的历史行为(比如浏览记录、购买记录等等)准确的预测出用户未来的行为;好的推荐系统不仅如此,而且能够拓展用户的视野,帮助他们发现可能感兴趣的却不容易发现的item;同时将埋没在长尾中的好商品推荐给可能感兴趣的用户。DMF推荐方法…

C语言既然可以自动为变量分配内存,为什么还要用动态分配内存呢?

一、前言 不知道大家在学习C语言动态分配内存的时候有没有过这样的疑问,既然系统可以自动帮我们分配内存,为什么还需要我们程序员自己去分配内存呢? 如果想要弄清楚这些问题,我们首先就要了解静态内存和动态内存有什么区别&…

python学习笔记

第一个python程序 pycharm使用 pycharm下载链接: https://www.jetbrains.com/zh-cn/pycharm/download/#sectionwindows 1. 新建项目 右键test—> 点击new 输入文件名 运行 结果 2. 调节字体大小快捷键设置 右键添加鼠标快捷键 按住ctrl鼠标向上滑动 放…

计算机网络 应用层

概述 为特定应用程序提供数据服务,例如HTTP、FTP(File Transfer Protocol , 文件传输协议)、DNS (Domain Name System,域名系统)等。 域名系统 DNS DNS 全名叫 Domain Name Server,中文俗称“域名服务器” 在 Internet 上域名…

Docker搭建Nginx实现SpringBoot+Nginx集群

1,首先聊聊什么Nginx? Nginx 是一个高性能的HTTP和反向代理web服务器,因它的稳定性、丰富的功能集、简单的配置文件和低系统资源的消耗而闻名。2011年6月1日,nginx 1.0.4发布。 Nginx是一款轻量级的Web 服务器/反向代理服务器及电…

linux三剑客awk、sed、grep与cut的总结

在Linux中,一切皆文件,对Linux的操作就是对文件的处理。对文件操作处理最重要的三个命令是grep、sed、awk,它们在业界被称为“三剑客”。 三剑客的功能非常强大,但它们各自有分别擅长的功能: grep擅长对文件或字符串进…

【操作系统】2.3 进程同步与互斥

这一节大概是操作系统中最难的一节了。 2.3.1 进程的同步与互斥 2.3.1 进程的同步与互斥_StudyWinter的博客-CSDN博客_进程同步思维导图 进程同步:在多道程序环境下,进程是并发执行的,不同进程之间存在着不同的相互制约关系。为了协调进程之…

C#界面里Form.Language 属性的使用

C#界面里Form.Language 属性的使用 现在面向全球化的应用软件、应用系统越来越多。 比如游戏正在走向全球化时代,很多游戏的服务器也会安装到各个国家去,也会请当地人来管理游戏的服务器。 这时开发的软件,就需要面向各种语言,比如英语、日语、阿拉佰语等等。 如果你正在…

什么叫共同富裕,刘强东给老板们打了个样

这两天,热搜上最火的男人,除了汪小菲,就是刘强东无疑了。 11月22日,刘强东发出了一封京东内部员工信,引发热议。 信里主要说了4点: 1、自明年1月1日起,为所有德邦员工缴齐五险一金&#xff1…

YOLOv5识别图像内苹果和香蕉

YOLOv5为目标检测带来了极大的方便。通过简单地训练YOLOv5,即可以实现一个速度快、性能高的目标检测系统。 下面介绍如何从头开始构造一个简单的目标检测系统,用来识别图像内的苹果和香蕉,并标注他们所在的位置。 特别强调的是,…

HTML5学习笔记(三)

离线应用 HTML5新增了一个离线存储的API,用于实现本地数据的缓存,从而使得开发离线应用成为可能。 所谓“离线存储”,指的是建立一个URL列表,该列表可以包含HTML文件、CSS文件、JavaScript文件和图片等。当与服务器建立连接时&am…

dragTabs(vue)

vue实现tabs拖拽 效果图 dragTab.vue <template><div class"yh-tabs"><draggable :list"tabList" :group"groupName" animation"300" item-key"id" end"dragEnd"><template #item"{ …

CANoe-vTESTstudio之Test Diagram编辑器(功能介绍)

1. 阶段 Test Diagram从测试设计到测试执行,分为5个阶段: Test Design 在测试设计阶段,测试设计人员使用图形元素和分配的测试代码对测试用例进行建模。这个阶段的结果是生成一个测试图表 Evaluation 生成的测试图表,需要评估其正确性。在评估期间,将验证各个元素及其…

3.7 学会这2招,让你的笔记分分钟上热门 【玩赚小红书】

什么是上热门&#xff1f; 上热门之前&#xff0c;我们先了解一下什么是上热门。上热门就是笔记被系统主动推荐&#xff0c;并在很长一段时间里&#xff0c;有源源不断的粉丝点赞、收藏&#xff0c;相当于平台给你的笔记开了专属流量口&#xff0c;推送给那些平常关注该笔记类型…

vue实战项目之vue-cli脚手架搭建过程详解

目录 1.可以参考vue-cli的中文文档进行下载安装 2.查看node和npm版本 3.安装依赖包 4.依赖包以前版本太老&#xff0c;如何更新&#xff1f; 5.创建一个项目 6.图形化界面 1.可以参考vue-cli的中文文档进行下载安装 vue-cli中文文档 2.查看node和npm版本 在cmd或者编译…

【数据库原理及应用】——关系数据库的规范化理论(学习笔记)

&#x1f4d6; 前言&#xff1a;关系数据库的规范化理论是数据库设计的一个理论指南&#xff0c;提供了判断一个关系模式优劣的理论依据。本章讨论的关系数据库的规范化理论主要包含三方面内容&#xff1a;函数依赖、范式和模式分解准则。函数依赖起着核心作用&#xff0c;是模…

易基因|TSD物种全基因组DNA甲基化模式对孵育性别和过去孵育温度的响应 | 性别决定

易基因&#xff5c;TSD物种全基因组DNA甲基化模式对孵育性别和过去孵育温度的响应 | 性别决定 大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 2022年8月23日&#xff0c;《MOLECULAR ECOLOGY》杂志发表题为“Genome-wide DNA methyla…

[附源码]java毕业设计幼儿园管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

[附源码]Python计算机毕业设计二手书交易软件设计与实现

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

嵌入式驱动初级-字符设备驱动基础

文章目录前言一、驱动学习预备知识1.什么是设备驱动程序2.向内核添加新功能方法2.1新功能源码与Linux内核源码不在同目录下2.2在Ubuntu下加载和删除ko文件步骤2.3在开发板下加载和删除ko文件步骤2.4内核模块基础代码解析二、字符设备驱动框架2.1Linux内核对设备的分类2.2字符设…