【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;代表了物体的基本外形。轮廓常用于形状分析和物体的检测和识别。 边缘检测根据灰度的…

【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&#…

智能家居(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>…

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…

Redis 安装与配置

Redis 安装与配置 Window 下安装 下载地址&#xff1a;https://github.com/MSOpenTech/redis/releases。 这里我们下载 Redis-x64-xxx.zip 解压到指定目录&#xff1a;  打开命令行&#xff08;cmd&#xff09;跳转至解压路径,并运行安装命令&#xff0c;结果如图 C:\U…

智能家居(2)智能体验与智能交互

1. 智能体验的分析与讨论 随着信息和网络技术的发展&#xff0c;可以网络连接的电子电器产品越来越丰富&#xff0c;智能家居、智慧园区、智能汽车等智能控制系统和产品应用越来越广泛。 智能交互终端是智能控制系统的人机交互接口&#xff0c;既是实现智能功能的重要载体&am…

netbeans java9_Java 开发新选择?Apache NetBeans IDE 9.0 备受好评

Apache NetBeans 9.0 目前已发布 Beta 版本&#xff0c;离正式版本越来越近。9.0 版本的主要目标囊括 Oracle 捐赠的大量代码&#xff0c;以及提供 Java 9 和 10 支持。Apache NetBeans 近期在社区上发起了一项满意度调查&#xff0c;用于验收用户如何对 9.0 版本的看法&#x…

LaTex实战笔记 1-快速入门

LaTex插入 Python 程序代码块1. 为什么用 LaTeX&#xff1f;2. LaTeX 的安装与配置2.1 安装 TeXLive2.2 选择 LaTeX 编辑器3. LaTeX 的初次使用3.1 最短的 LaTeX 示例3.2 从模板创建文档3.3 编译生成 PDF 文件4. 基于模板编辑文档4.1 tex 模板的基本结构4.2 基于模板编辑排版5.…

java fx 皮肤_JavaFX 皮肤功能

作为RIA技术之一&#xff0c;为了让应用程序的界面看起来更加的漂亮或者更有个性&#xff0c;皮肤功能自然是必不可少的。在JavaFX中&#xff0c;可以使用CSS样式表来进行皮肤的更换。不过JavaFX中的CSS是基于W3C CSS version 2.1&#xff0c;但又不完全相同。JavaFX中的换肤有…

LaTex实战笔记 2-文档层次与结构

LaTeX 支持结构化文档的编写。 什么是结构化文档&#xff1f;会议论文、期刊论文、学位论文&#xff0c;这类有统一结构、统一版式的文档&#xff0c;是典型的结构化文档。而报刊文章的结构则因人而异&#xff0c;因文而异&#xff0c;是典型的非结构化文档。 1. 结构化文档的…

java爬取小说

使用Java爬取网站&#xff1a;http://www.shicimingju.com的小说内容 代码详解 1.在本地创建存储位置 2.编写正则表达式 3.循环获取内容 4.把内容存入文件夹中 5.判断成功或失败 效果演示 代码展示 package text;import java.io.BufferedReader;import java.io.BufferedWri…