函数 cv.findContours

contours, hierarchy = cv.findContours( image, mode, method[, contours[, hierarchy[, offset]]] )

  1. 参数1:源图像
  2. 参数2:轮廓的检索方式,这篇文章主要讲解这个参数
  3. 参数3:一般用 cv.CHAIN_APPROX_SIMPLE,就表示用尽可能少的像素点表示轮廓
  4. contours:图像轮廓坐标,是一个链表
  5. hierarchy:[Next, Previous, First Child, Parent],文中有详细解释

我们使用cv.findContours()寻找轮廓时,参数2表示轮廓的检索方式(RetrievalModes),当我们传入的是cv.RETR_TREE,它表示什么意思呢?另外,函数返回值hierarchy有什么用途呢?下面我们就来研究下这两个问题。

理解轮廓层级


图中总共有8条轮廓,2和2a分别表示外层和里层的轮廓,3和3a也是一样。从图中看得出来:

  1. 轮廓0/1/2是最外层的轮廓,我们可以说它们处于同一轮廓等级:0级
  2. 轮廓2a是轮廓2的子轮廓,反过来说2是2a的父轮廓。轮廓2a算一个等级:1级
  3. 同样3是2a的子轮廓,轮廓3处于一个等级:2级
  4. 类似的,3a是3的子轮廓,等等…………
    这里面OpenCV关注的就是两个概念:同一轮廓等级和轮廓间的子属关系。

如果我们打印出cv.findContours()函数的返回值hierarchy,会发现它是一个包含4个值的数组:[Next, Previous, First Child, Parent]
Next:与当前轮廓处于同一层级的下一条轮廓
举例来说,前面图中跟0处于同一层级的下一条轮廓是1,所以Next=1;同理,对轮廓1来说,Next=2;那么对于轮廓2呢?没有与它同一层级的下一条轮廓了,此时Next=-1。
Previous:与当前轮廓处于同一层级的上一条轮廓
跟前面一样,对于轮廓1来说,Previous=0;对于轮廓2,Previous=1;对于轮廓2a,没有上一条轮廓了,所以Previous=-1。
First Child:当前轮廓的第一条子轮廓
比如对于轮廓2,第一条子轮廓就是轮廓2a,所以First Child=2a;对轮廓3,First Child=3a。
Parent:当前轮廓的父轮廓
比如2a的父轮廓是2,Parent=2;轮廓2没有父轮廓,所以Parent=-1。

OpenCV中找到的轮廓序号跟前面讲的不同

现在既然我们了解了轮廓层级的概念,那么类似cv.RETR_TREE的轮廓寻找方式又是啥意思呢?

轮廓寻找方式

OpenCV中有四种轮廓寻找方式RetrievalModes,下面分别来看下:

1. RETR_LIST

这是最简单的一种寻找方式,它不建立轮廓间的子属关系,也就是所有轮廓都属于同一层级。这样,hierarchy中的后两个值[First Child, Parent]都为-1。比如同样的图,我们使用cv.RETR_LIST来寻找轮廓:

contours, hierarchy = cv2.findContours(thresh, cv2.RETR_LIST, 2)
print(hierarchy)
# 结果如下
[[[ 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]]]

因为没有从属关系,所以轮廓0的下一条是1,1的下一条是2……

如果你不需要轮廓层级信息的话,cv.RETR_LIST更推荐使用,因为性能更好

2. RETR_TREE

cv.RETR_TREE就是之前我们一直在使用的方式,它会完整建立轮廓的层级从属关系,前面已经详细说明过了。

3. RETR_EXTERNAL

这种方式只寻找最高层级的轮廓,也就是它只会找到前面我们所说的3条0级轮廓:

实验讲解 RETR_EXTERNAL

contours, hierarchy = cv.findContours(thresh, cv.RETR_EXTERNAL, 2)
print(len(contours), hierarchy, sep='\n')
# 结果如下
3
[[[ 1 -1 -1 -1][ 2  0 -1 -1][-1  1 -1 -1]]]

实验结果

4. RETR_CCOMP

相比之下cv.RETR_CCOMP比较难理解,它把所有的轮廓只分为2个层级,不是外层的就是里层的。结合代码和图片,我们来理解下:

实验讲解 RETR_CCOMP

contours, hierarchy = cv.findContours(thresh, cv.RETR_CCOMP, 2)
print(hierarchy)
# 结果如下
[[[ 1 -1 -1 -1][ 2  0 -1 -1][ 4  1  3 -1][-1 -1 -1  2][ 6  2  5 -1][-1 -1 -1  4][ 7  4 -1 -1][-1  6 -1 -1]]]

实验结果


使用这个参数找到的轮廓序号与之前不同。
图中括号里面1代表外层轮廓,2代表里层轮廓。比如说对于轮廓2,Next就是4,Previous是1,它有里层的轮廓3,所以First Child=3,但因为只有两个层级,它本身就是外层轮廓,所以Parent=-1。大家可以针对其他的轮廓自己验证一下。

实验:绘制图像轮廓

import cv2 as cv
import numpy# 1.读入图片
img = cv.imread('test_contours.jpg')
img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
contours, thresh = cv.threshold(img_gray, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU)# 2.寻找轮廓
contours, hierarchy = cv.findContours(thresh, cv.RETR_LIST, 2)print(len(contours),hierarchy)# 3.绘制轮廓
cv.drawContours(img, contours, -1, (0, 0, 255), 2)cv.imshow('result',img)
cv.waitKey(0)
cv.destroyAllWindows()

实验结果

opencv cv.findContours 函数详解相关推荐

  1. OpenCV 图像卷积:cv.filter2D() 函数详解

    API 照例,我们搬一下官网的 API: C++ void cv::filter2D(InputArray src,OutputArray dst,int ddepth,InputArray kern ...

  2. OpenCV 图像缩放:cv.resize() 函数详解

    目录 系列前言 API 函数详解 参数列表 缩放方式其一 缩放方式其二 两种方式的优先级 关于插值方式 扩展 -- 相关函数 系列前言 这个系列是我第一个想要更下去的系列.每篇会全面介绍一个 Open ...

  3. 计算机视觉开源库OpenCV之threshold()函数详解

    cv2.threshold()函数作用:去掉噪,例如过滤很小或很大像素值的图像点. cv2.threshold()函数python版原型: retval, dst = cv.threshold(src ...

  4. OpenCV的waitKey函数详解

    waitKey函数功能是不断刷新图像,频率时间为delay,单位为ms:该函数通常用在显示图像函数之后. 格式: key = waitKey(delay=0); 参数:delay延时时间,单位ms: ...

  5. Opencv中的imshow函数详解

    前言 使用opencv对图像进行处理之后,通常调用imshow函数来显示处理结果.但是,我们经常会发现显示结果和我们预期的结果有些差别.这是由于opencv经常会涉及到对多种图像数据类型的处理,如果我 ...

  6. opencv imshow函数详解

    前言 使用opencv对图像进行处理之后,通常调用imshow函数来显示处理结果.但是,我们经常会发现显示结果和我们预期的结果有些差别.这是由于opencv经常会涉及到对多种图像数据类型的处理,如果我 ...

  7. OpenCV-Python学习之(一)waitKey()函数详解

    OpenCV-Python学习之(一)waitKey()函数详解 waitKey()函数详解 : 1.1 waitKey()--这个函数是在一个给定的时间内(单位ms)等待用户按键触发;如果用户没有按 ...

  8. OpenCV-Python直方图计算calcHist函数详解

    ☞ ░ 前往老猿Python博文目录 https://blog.csdn.net/LaoYuanPython ░ 一.引言 在<<数字图像处理>第三章学习总结感悟2:直方图处理: h ...

  9. OpenCV SIFT源码详解——总体概览

    OpenCV SIFT源码详解--总体概览 一.版本 二.章节系列 此系列文章源自本人硕士毕业论文,主要讲源码,对于SIFT理论知识默认大家有过了解.若文章中有不对之处还请读者指出. 一.版本 本系列 ...

最新文章

  1. Spark ThriftServer使用的大坑
  2. 使用wkwebview后,页面返回不刷新的问题
  3. qq邮箱使用outlook 2007
  4. 边缘计算应用场景_云计算与边缘计算协同九大应用场景(2019年)发布(附PPT解读)...
  5. ie 出现 append无效
  6. 交换局域网(链路层+以太网+交换机)
  7. Android物联网应用程序开发(智慧城市)—— 购物信息的存储界面开发
  8. 浅析数据中心交换机芯片,中国自主可控国产化交换机已是历史必然
  9. Fragstats 提示错误与警告
  10. rainmeter 修正天气插件信息不准确 设置居住城市
  11. Block-scoped declarations (let, const, function, class) not yet supported outs报错解决
  12. no-sql数据库之redis
  13. 为什么很难统一量子力学与广义相对论?
  14. 电网计算机面试专业题,国家电网计算机管理员面试经验|面试题 - 职朋职业圈...
  15. 用Kanban-Ace框架改进Scrum
  16. 基于WebSocket实现一个简易的群聊功能
  17. 【密码学探秘】EVM链和并行执行交易
  18. 液晶分子平行排列MATLAB程序,液晶百问:液晶分子排列方向如何改变
  19. SQL Studio:一款纯Web化SQL开发工具,关键是免安装还免费!
  20. 【第3版emWin教程】第3章 emWin介绍

热门文章

  1. python是什么意思-Python中%是什么意思?python中百分号如何使用?
  2. python在线发音-Python如何实现文本转语音
  3. ASRT:一个中文语音识别系统
  4. 基于阿里云实现简单的语音识别功能
  5. 微信小程序开发公司哪家好?
  6. 数据类型以及数据类型的转换---防止忘记
  7. echarts折线图y轴根据数值自动_Python matplotlib 绘制双Y轴曲线图的示例代码
  8. Web API-document
  9. 根据 key值查找数组对象中所有的符合的对象 (递归)
  10. Linux系统时间和java的时间不一致