【youcans 的 OpenCV 例程200篇】194.寻找图像轮廓(cv.findContours)

OpenCV 例程200篇 总目录-202205更新


【youcans 的 OpenCV 例程200篇】194.寻找图像轮廓(cv.findContours)


1. 轮廓

轮廓是一系列相连的像素点组成的曲线,代表了物体的基本外形。轮廓常用于形状分析和物体的检测和识别。

边缘检测根据灰度的突变检测边界,但检测到的边缘通常还是零散的片段,并未构成整体。从背景中分离目标,就要将边缘像素连接构成轮廓。也就是说,轮廓是连续的,边缘不一定都连续。边缘主要是作为图像的特征使用,而轮廓主要用来分析物体的形态。


1.1 轮廓的查找

OpenCV 提供函数 cv.findContours() 从二值图像中寻找轮廓,函数 cv2.drawContours() 绘制轮廓。

函数说明:

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

cv.findContours() 对黑色背景的二值图像操作,通常会先使用阈值分割或边缘检测得到二值图像。

参数说明:

  • image:原始图像,8 位单通道二值图像
  • mode: 轮廓检索模式
    • cv.RETR_EXTERNAL:只检索最外层轮廓
    • cv.RETR_LIST:检索所有轮廓,不建立任何层次关系
    • cv.RETR_CCOMP:检索所有轮廓,并将其组织为两层, 顶层是各部分的外部轮廓,次层是内层轮廓
    • cv.RETR_TREE:检索所有轮廓,并重建嵌套轮廓的完整层次结构
    • cv.RETR_FLOODFILL:漫水填充法(泛洪填充)
  • method: 轮廓近似方法
    • cv.CHAIN_APPROX_NONE:输出轮廓的每个像素点
    • cv.CHAIN_APPROX_SIMPLE:压缩水平、垂直和斜线,仅保留这些线段的端点
    • cv.CHAIN_APPROX_TC89_L1:应用 Teh-Chin 链近似算法 L1
    • cv.CHAIN_APPROX_TC89_KCOS:应用 Teh-Chin 链近似算法 KCOS
  • contours:检测到的所有轮廓,列表格式,每个轮廓存储为包含边界点坐标 (x,y) 的点向量
    • 列表(LIST)长度为 L,对应于找到的 L 个轮廓,按 0,…L-1 顺序排列
    • 列表中的第 i 个元素是一个形如 (k,1,2) 的 Numpy 数组,表示第 i 个轮廓,k 是第 i 个轮廓的边界点的数量
    • 数组 contours[i] 是构成第 i 个轮廓的各边界点坐标 (x,y) 的点向量
    • 注意边界点的坐标表达形式是 (x,y),而不是 OpenCV 中常用的像素坐标表达形式 (y,x)。
  • hierarchy:轮廓的层次结构和拓扑信息,是一个形如 (1,k,4) 的 Numpy 数组
    • k 对应于找到的轮廓数量
    • hierarchy[0][i] 表示第 i 个轮廓的层次结构,是包含 4个值的数组 [Next, Previous, First Child, Parent],分别代表第 i 个轮廓的同层的后一个轮廓、同层的前一个轮廓、第一个子轮廓、父轮廓的编号
  • offset:每个轮廓点的偏移量,可选项,

注意事项:

  • 原始图像 image 必须是单通道图像,其中的非 0 像素都被视为 1,因此图像被视为二值图像。在查找轮廓之前,可以使用 threshold、inRange、Canny 等方法从灰度或彩色图像中创建二值图像。
  • 通常将轮廓近似方法 method 设为 CHAIN_APPROX_SIMPLE,对轮廓的水平、垂直和斜线进行压缩,只保留这些线段的端点,因此轮廓是由一系列线段连接而成的闭合曲线。
  • 每一个轮廓都是一个 Numpy 数组,包含对象边界点 (x,y) 的坐标,注意不是 (y,x)。
  • 如果从图像 ROI 中提取轮廓,然后在图像上下文中进行分析,偏移量 offset 将非常有用。
  • 轮廓的层次结构的表达嵌套在顶级数组中,可以使用 hierarchy[0][i] 访问第 i 个轮廓的层次结构元素。
  • 对应于第 i 个轮廓 contours[i],hierarchy [i][0]~hierarchy[i][3] 分别代表它的同层的后一个轮廓、同层的前一个轮廓、第一个子轮廓、父轮廓的编号。

使用说明:

函数 cv.findContours() 是常用的寻找轮廓函数,但在使用中要注意几个问题:

注意 1: OpenCV不同版本中本函数的返回值不同。OpenCV 3 中返回 3个值 image, contours, hierarchy,OpenCV2、OpenCV4、OpenCV5 中函数返回 2个值 contours, hierarchy。
注意2: OpenCV 3.2 之前的早期版本中,函数会对输入图像“原地”修改——这是 OpenCV5 官方文档中的提示,但本文作者认为 OpenCV2 及其它版本到底是否修改原图存疑。为了避免不同版本带来的错误,建议都采用原始图像的 copy 作为函数的输入图像。
注意3: cv.findContours() 对黑色背景的二值图像操作,也就是默认需要提取轮廓的目标为亮色、浅色。如果背景为亮色、浅色,如书本通常是白色背景深色文字,要在二值处理时选择取反操作。
注意4: 轮廓边界点的坐标表达形式是 (x,y),而不是 OpenCV 中常用的像素坐标表达形式 (y,x)。
注意5: 第 i 个轮廓 contours[i],hierarchy [i] 按照先外层后内层的顺序从 0~L-1 依次编号,但编号顺序并不体现嵌套结构关系。轮廓之间的嵌套结构关系是由 hierarchy [i] 的数值来表达的。
注意6: 查找轮廓时,推荐使用边缘检测 而不是阈值处理 cv.threshold() 得到二值图,其原因是:

  • 提取边缘与阈值处理不同,边缘提取可以识别图片中目标的形状、轮廓,而不是简单的区分出图片中的高光与暗调;
  • 使用边缘检测提取结果的白点数量更少,可以提高轮廓检测的性能;
  • 边缘检测也可以使用 cv.Sobel,cv.Scharr,cv.Laplacian 等方法,但 cv.Canny 的边缘检测效果往往更好。

例程 12.1:查找图像轮廓

    # 12.1 从二值图像中寻找轮廓img = cv2.imread("../images/pattern1.png", flags=1)gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 灰度图像_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_OTSU+cv2.THRESH_BINARY_INV)plt.figure(figsize=(9, 6))plt.subplot(131), plt.axis('off'), plt.title("Origin")plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))plt.subplot(132), plt.axis('off'), plt.title("BinaryInv")plt.imshow(binary, 'gray')# 寻找二值化图中的轮廓binary, contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)  # OpenCV3# contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)  # OpenCV4~# # 绘制轮廓contourPic = img.copy()  # OpenCV3.2 之前的早期版本,查找轮廓函数会修改原始图像contourPic = cv2.drawContours(contourPic, contours, -1, (0, 0, 255), 2)  # OpenCV3# contourPic = cv.drawContours(img, contours, -1, (0, 0, 255), thickness=cv.FILLED,maxLevel=1)print("len(contours) = ",len(contours))  # 所有轮廓的列表for i in range(len(contours)):print("i=", i, contours[i].shape)  # 第 i 个轮廓的边界点print("hierarchy.shape : ", hierarchy.shape)  # 层次结构print(hierarchy)plt.subplot(133), plt.axis('off'), plt.title("External contour")plt.imshow(cv2.cvtColor(contourPic, cv2.COLOR_BGR2RGB))plt.tight_layout()plt.show()

运行结果:

在这里插入图片描述

len(contours) =  6
hierarchy.shape :  (1, 6, 4)
i= 0 ,contours[i]: (5, 1, 2) ,hierarchy[0][i] = [ 1 -1 -1 -1]
i= 1 ,contours[i]: (5, 1, 2) ,hierarchy[0][i] = [ 2  0 -1 -1]
i= 2 ,contours[i]: (4, 1, 2) ,hierarchy[0][i] = [-1  1  3 -1]
i= 3 ,contours[i]: (8, 1, 2) ,hierarchy[0][i] = [-1 -1  4  2]
i= 4 ,contours[i]: (4, 1, 2) ,hierarchy[0][i] = [ 5 -1 -1  3]
i= 5 ,contours[i]: (5, 1, 2) ,hierarchy[0][i] = [-1  4 -1  3]

原图为白色背景深色目标,先进行二值化处理,并取反成为黑色背景白色目标。用 findContours() 寻找轮廓并显示,关于构造和显示轮廓图像函数 drawContours() 在下一节介绍。

轮廓检索模式 mode 设为 RETR_TREE,查找所有的轮廓(树状结构);mode 设为 RETR_EXTERNAL,只查找最外层的轮廓,不查找图中内层菱形目标的轮廓。

返回值 contours 是所有轮廓的列表:

  • 列表长度为 6,对应于找到的 6 个轮廓。
  • 列表中的第 i 个元素表示第 i 个轮廓,是一个形如 (k,1,2) 的 Numpy 数组。
  • 数组 contours[i] 是构成第 i 个轮廓的各边界点坐标 (x,y) 的点向量,k 是描述第 i 个轮廓的边界点的个数。
  • 注意边界点的坐标表达形式是 (x,y),而不是 OpenCV 中常用的像素坐标表达形式 (y,x)。

通常将轮廓近似方法 method 设为 CHAIN_APPROX_SIMPLE,对轮廓的水平、垂直和斜线进行压缩,只保留这些线段的端点,因此轮廓是由一系列线段连接而成的闭合曲线。一个矩形轮廓最少可以用 4 个边界点表示,如例程的结果中 i=2 的轮廓只有 4个顶点。但由于图像本身和轮廓查找的算法的影响,一个看起来是矩形的目标,其轮廓也可能多于 4个边界点。

返回值 hierarchy 是轮廓的层次结构和拓扑信息,是一个形如 (1,k,4) 的 Numpy 数组:

  • k 对应于找到的轮廓数量。
  • hierarchy[0][i]表示第 i 个轮廓的层次结构,hierarchy [0][i][0]~hierarchy[0][i][3] 分别代表第 i 个轮廓的同层的后一个轮廓、同层的前一个轮廓、第一个子轮廓、父轮廓的编号。-1 表示没有/不适用。

第 i 个轮廓 contours[i],hierarchy [i] 按照 0~L-1 顺序编号,编号顺序并不体现嵌套结构关系。轮廓之间的嵌套结构关系是由 hierarchy [i] 的数值来表达的。

例程找到 6个轮廓,返回值 hierarchy 的形状为 (1, 6, 4) 。
hierarchy[0][0]=[ 1 -1 -1 -1],表示第 0 个轮廓同层后一个轮廓编号为 1,没有同层前一个轮廓,没有子轮廓,没有父轮廓;
hierarchy[0][1]=[ 2 0 -1 -1],表示第 1 个轮廓同层后一个轮廓编号为 2,同层前一个轮廓编号为 0,没有子轮廓,没有父轮廓;
hierarchy[0][2]=[-1 1 3 -1],表示第 2 个轮廓没有同层后一个轮廓,同层前一个轮廓编号为 1,子轮廓编号为 3,没有父轮廓;
hierarchy[0][3]=[-1 -1 4 2],表示第 3 个轮廓没有同层后一个轮廓,没有同层前一个轮廓,子轮廓编号为 4,父轮廓编号为 2;
hierarchy[0][4]=[ 5 -1 -1 3],表示第 4 个轮廓同层后一个轮廓编号为 5,没有同层前一个轮廓,没有子轮廓,父轮廓编号为 3;
hierarchy[0][5]= [-1 4 -1 3],表示第 5 个轮廓没有同层后一个轮廓,同层前一个轮廓编号为4,没有子轮廓,父轮廓编号为 3。


(本节完)


版权声明:

OpenCV 例程200篇 总目录-202205更新
youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/124970610)

Copyright 2022 youcans, XUPT
Crated:2022-5-25


欢迎关注 『youcans 的 OpenCV 例程 200 篇』 系列,持续更新中
欢迎关注 『youcans 的 OpenCV学习课』 系列,持续更新中

【youcans 的 OpenCV 例程200篇】194.寻找图像轮廓(cv.findContours)
【youcans 的 OpenCV 例程200篇】195.绘制图像轮廓(cv.drawContours)
【youcans 的 OpenCV 例程200篇】196.图像的矩和不变矩(cv.moments)
【youcans 的 OpenCV 例程200篇】197.轮廓的基本特征
【youcans 的 OpenCV 例程200篇】198.基于不变矩的形状相似性检测
【youcans 的 OpenCV 例程200篇】199.轮廓的外接边界框
【youcans 的 OpenCV 例程200篇】200.轮廓的基本属性
更多内容,请见:
【OpenCV 例程200篇 总目录-202206更新】

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

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

相关文章

java线程池执行器_Java线程池ThreadPoolExecutor的使用

Java线程池ThreadPoolExecutor的使用ThreadPoolExecutor就是我们用来实现线程的一个执行器,它实现了Excutor和ExecutorService接口。Excutor接口只定义了一个方法就是execute用来执行任务。ExecutorService继承于Excutor并添加了一些其他的执行任务的方法和管理线程…

密码强度显示

使用HTML,CSS及JS实现注册功能中密码强度的显示&#xff0c;根据输入的密码判断并显示用户输入密码的强度等级是高还是低等。 效果演示 代码演示 html内容 <div class"container"><div class"userName-wrapper"><label for"userN…

【youcans 的 OpenCV 例程200篇】195.绘制图像轮廓(cv.drawContours)

OpenCV 例程200篇 总目录-202205更新 【youcans 的 OpenCV 例程200篇】195.绘制图像轮廓&#xff08;cv.drawContours&#xff09; 1. 轮廓 轮廓是一系列相连的像素点组成的曲线&#xff0c;代表了物体的基本外形。轮廓常用于形状分析和物体的检测和识别。 边缘检测根据灰度的…

java终结方法_Java终结任务:Callable和Future

在这里首先介绍下Callable和Future&#xff0c;我们知道通常创建线程的2种方式&#xff0c;一种是直接继承Thread&#xff0c;另外一种就是实现Runnable接口&#xff0c;但是这两种方式创建的线程不返回结果&#xff0c;而Callable是和Runnable类似的接口定义&#xff0c;但是通…

【youcans 的 OpenCV 例程200篇】196.图像的矩和不变矩(cv.moments)

OpenCV 例程200篇 总目录-202205更新 【youcans 的 OpenCV 例程200篇】196.图像的矩和不变矩&#xff08;cv.moments&#xff09; 2. 轮廓的特征描述 在对实际图像进行轮廓查找时&#xff0c;得到的轮廓数量很多。获取轮廓后&#xff0c;通常基于轮廓的特征进行筛选、识别和处…

Spring boot 项目目录结构详解

对SpringBoot项目目录进行分层显示能够使我们的开发思路更加的明确&#xff0c;代码内容更加清晰易懂&#xff0c;下面向大家讲解一下项目目录结构。 代码层的结构 根目录&#xff1a;com.springboot 1.工程启动类(ApplicationServer.java)置于com.springboot.build包下 2.实…

【youcans 的 OpenCV 例程200篇】197.轮廓的基本特征

OpenCV 例程200篇 总目录-202205更新 文章目录【youcans 的 OpenCV 例程200篇】197.轮廓的基本特征2. 轮廓的特征描述2.2 轮廓的面积、周长、质心和近似多边形2.2.1 轮廓的面积2.2.2 轮廓的周长2.2.3 轮廓的质心2.2.4 轮廓的近似2.2.5 轮廓的凸包&#xff08;凸壳&#xff09;例…

Idea 项目导入

我们在刚开始使用新的开发工具IDEA的时候会遇到我们想要导入一个外部项目却不知从何下手&#xff0c;下面我就教给大家如何使用IDEA导入一个外部的项目。 Idea 导入 外部项目 1.点击 file — new 2.打开路径地址&#xff0c;选择需要导入的项目 3.选择创建—next 4.默认—…

【youcans 的 OpenCV 例程200篇】198.基于不变矩的形状相似性检测

OpenCV 例程200篇 总目录-202206更新 【youcans 的 OpenCV 例程200篇】198.基于不变矩的形状相似性检测 3. 基于不变矩检测的图像识别 形状匹配也称为形状相似度检测&#xff0c;用于比较两个形状或两个轮廓。 函数 cv2.matchShapes() 基于 Hu 不变矩检测两个形状之间的相似度…

spring boot 如何修改默认端口号和context path

创建了SpringBoot项目之后进行运行&#xff0c;当我们需要使用游览器进行访问的时候要输入端口号&#xff0c;那麽我们如何来修改这个端口号呢&#xff1f;&#xff1f;&#xff1f; 1.在src/main/resources目录下新建文件application.properties&#xff0c;并进行配置,来重写…

【youcans 的 OpenCV 例程200篇】199.轮廓的外接边界框

OpenCV 例程200篇 总目录-202206更新 【youcans 的 OpenCV 例程200篇】199.轮廓的外接边界框 文章目录【youcans 的 OpenCV 例程200篇】199.轮廓的外接边界框2. 轮廓的特征描述2.3 轮廓的外接边界框2.3.1 轮廓的垂直矩形边界框2.3.2 轮廓的最小矩形边界框2.3.3 轮廓的最小外接圆…

单级联动

想要实现联动的效果首先我们要知道什么是单机联动&#xff0c;所谓的单级联动就是点击输入框的时候&#xff0c;下面会出现多个单级联动的列表供你选择自己所要选择的数据。 我们使用html写主题内容&#xff0c;使用CSS添加样式&#xff0c;使用Jquery实现联动等相关的事件和效…

【youcans 的 OpenCV 例程200篇】200.轮廓的基本属性

OpenCV 例程200篇 总目录-202206更新 文章目录【youcans 的 OpenCV 例程200篇】200.轮廓的基本属性2.4 轮廓的基本属性2.4.1 轮廓的宽高比&#xff08;Aspect Ratio&#xff09;2.4.2 轮廓的面积比&#xff08;Extent&#xff09;2.4.3 轮廓的坚实度&#xff08;Solidity&#…

mysql c api example_The MySQL C API 编程实例

在网上找了一些MYSQL C API编程的文章&#xff0c;看了后认为还是写的不够充分&#xff0c;依据自己经验写了这篇《The MySQL C API 编程实例》&#xff0c;希望对须要调用到MYSQL的C的API的朋友有所帮助&#xff0c;附例中的环境为RedHat在这篇文章里&#xff0c;我们将学会怎…

【youcans 的 OpenCV 例程200篇】结束语

【youcans 的 OpenCV 例程200篇】总目录 【youcans 的 OpenCV 例程200篇】结束语 【youcans 的 OpenCV 例程】真的写到了 200篇&#xff0c;迎来了“结束语”。 本系列原名【OpenCV 例程 100篇】&#xff0c;从 2021年 11月开始写作&#xff0c;原计划每天写一篇&#xff0c;写…

java aspose 导出word_使用aspose.word 第三方的插件实现导出word

#region 生成的excel文件命名和确保文件的唯一性Random rd new Random();DateTime dtime DateTime.Now;string Filename "培训需求表" dtime.Year.ToString() dtime.Month.ToString() dtime.Day.ToString() dtime.Hour.ToString() dtime.Minute.ToString() …

智能家居(1)行业发展分析

1 智能家居系统 智能家居是基于物联网技术&#xff0c;由硬件系统、软件系统、云计算平台构成一个家庭生态圈&#xff0c;为用户提供安全、便利、舒适的家居生活环境。 具体而言&#xff0c;智能家居以住宅为单位、以家庭生活为背景&#xff0c;以综合布线技术、网络通信技术…

redis 高级实用教程

一、设置redis外网访问 更改redis.conf 文件 # vim redis.conf bind 127.0.0.1 # 注释掉改行 protected-mode yes # 更改模式为no&#xff08;redis3.2后&#xff09;二、设置密码验证 更改redis.conf配置文件 requirepass redhat或者通过set设置 127.0.0.1:6284>…

java学到哪里最容易蒙,蒙哥比vs蒙克(目前最好的哪个)

Im planning to integrate mongodb based migration tool in my spring boot application which is having spring-data dependency in project. I found main two libraries 1) Mongobee 2) Mongock.I need some feedback which one should i choose ? Thanks in advance!解决…

LaTex实战笔记 4-插入 Python 程序代码块

LaTex插入 Python 程序代码块1. 需求描述和解决方案2. minted 包的安装与配置2.1 安装 Python 第三方库 Pygments2.2 下载和安装 minted 宏包2.3 配置 LaTeX 编译环境3. minted 包的使用3.1 基本使用3.2 扩展使用3.2.1 \mint 命令行3.2.2 \mintinline 行内使用3.2.3 \inputmint…