目录

一、轮廓检测基础概念

二、核心 API 详解:cv2.findContours ()

参数说明:

返回值说明:

三、轮廓检测实战步骤

1. 图像预处理(灰度化与二值化)

2. 查找轮廓

3. 绘制轮廓

四、轮廓的常用属性与操作

1. 轮廓面积与周长

2. 轮廓筛选与排序

3. 轮廓的外接形状

4. 轮廓近似

五、总结


在计算机视觉领域,轮廓检测是一项基础且重要的技术,它能够帮助我们识别图像中的物体边界,为后续的图像分析、目标识别等任务提供关键信息。本文将基于 OpenCV 库,详细介绍轮廓检测的原理、常用 API 及实战应用。


一、轮廓检测基础概念

轮廓可以理解为图像中具有相同颜色或灰度的连续点组成的曲线,它是物体边界的有效表达方式。在进行轮廓检测前,有一个重要的前提:需要将图片处理为二值图像(像素值只为 0 和 255),这是因为轮廓检测主要基于图像的边缘信息,二值化处理能简化后续的检测过程。


二、核心 API 详解:cv2.findContours ()

OpenCV 提供了 cv2.findContours() 函数用于检测图像轮廓,其语法格式如下:

参数说明:

  1. img:需要进行轮廓检测的输入图像(必须是二值图像)

  2. mode:轮廓的检索模式,常用的有以下四种:

    • cv2.RETR_EXTERNAL:只检测外轮廓,忽略所有子轮廓
    • cv2.RETR_LIST:检测所有轮廓,但不建立等级关系
    • cv2.RETR_CCOMP:返回所有轮廓,仅建立两级层次结构(外轮廓为第 1 级,内部中空轮廓为第 2 级)
    • cv2.RETR_TREE:返回所有轮廓,建立完整的层级组织结构
  3. method:轮廓的近似方法:

    • cv2.CHAIN_APPROX_NONE:存储所有的轮廓点
    • cv2.CHAIN_APPROX_SIMPLE:压缩模式,只保留轮廓方向的终点坐标(如矩形仅保留 4 个顶点)

返回值说明:

  • image:处理后的图像(与输入图像相关)
  • contours:包含所有轮廓的列表,每个轮廓是由边界点坐标 (x,y) 组成的 numpy 数组
  • hierarchy:轮廓的层次结构,每个元素是包含 4 个值的数组 [Next, Previous, First Child, Parent],分别表示:
    • Next:同一层级的下一条轮廓
    • Previous:同一层级的上一条轮廓
    • First Child:当前轮廓的第一条子轮廓
    • Parent:当前轮廓的父轮廓

注意:在新版 OpenCV(如 4.x 版本)中,该函数返回值为 (contours, hierarchy),可使用 contours = cv2.findContours(...)[-2] 兼容不同版本。


三、轮廓检测实战步骤

1. 图像预处理(灰度化与二值化)

轮廓检测前必须进行预处理,将彩色图像转为灰度图,再进一步转为二值图:

import cv2# 读取原图
phone = cv2.imread('phone.png')
# 转为灰度图
phone_gray = cv2.cvtColor(phone, cv2.COLOR_BGR2GRAY)
# 二值化处理(阈值 120,最大值 255,二值化方式)
ret, phone_binary = cv2.threshold(phone_gray, 120, 255, cv2.THRESH_BINARY)# 显示处理结果
cv2.imshow('phone_gray', phone_gray)
cv2.imshow('phone_binary', phone_binary)
cv2.waitKey(0)

2. 查找轮廓

使用 cv2.findContours() 函数检测轮廓:

# 查找轮廓(建立完整层级,压缩轮廓点)
_, contours, hierarchy = cv2.findContours(phone_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# 打印轮廓信息
print("轮廓层次结构:", hierarchy)
print("轮廓数量:", len(contours))
轮廓层次结构: [[[ 6 -1  1 -1][ 2 -1 -1  0][ 3  1 -1  0][ 4  2 -1  0][ 5  3 -1  0][-1  4 -1  0][ 7  0 -1 -1][ 8  6 -1 -1][-1  7 -1 -1]]]
轮廓数量: 9

3. 绘制轮廓

通过 cv2.drawContours() 函数可以将检测到的轮廓绘制在图像上:

# 函数语法
# cv2.drawContours(image, contours, contourIdx, color, thickness)# 复制原图避免修改原图
image_copy = phone.copy()
# 绘制所有轮廓(contourIdx=-1),绿色(0,255,0),线宽 2
cv2.drawContours(image_copy, contours, -1, (0,255,0), 2)
cv2.imshow('contours_result', image_copy)
cv2.waitKey(0)


四、轮廓的常用属性与操作

1. 轮廓面积与周长

  • 轮廓面积:使用 cv2.contourArea() 计算
  • 轮廓周长:使用 cv2.arcLength() 计算(参数 closed=True 表示闭合轮廓)
# 计算第一个轮廓的面积
area_0 = cv2.contourArea(contours[0])
print("第一个轮廓的面积:", area_0)# 计算第一个轮廓的周长
length = cv2.arcLength(contours[0], closed=True)
print("第一个轮廓的周长:", length)
第一个轮廓的面积: 50716.5
第一个轮廓的周长: 952.4377244710922

2. 轮廓筛选与排序

可以根据轮廓面积等属性筛选特定轮廓,或对轮廓进行排序:

# 筛选面积大于 10000 的轮廓
large_contours = []
for cnt in contours:if cv2.contourArea(cnt) > 10000:large_contours.append(cnt)# 绘制筛选后的轮廓
image_copy = phone.copy()
cv2.drawContours(image_copy, large_contours, -1, (0,255,0), 3)
cv2.imshow('contours_larger_10000', image_copy)
cv2.waitKey(0)# 按面积降序排序,取最大面积的轮廓
largest_cnt = sorted(contours, key=cv2.contourArea, reverse=True)[0]
image_copy = phone.copy()
cv2.drawContours(image_copy, [largest_cnt], -1, (0,255,0), 3)
cv2.imshow('largest_contour', image_copy)
cv2.waitKey(0)

3. 轮廓的外接形状

可以计算轮廓的外接圆和最小外接矩形:

# 以外接圆为例(选取第三个轮廓)
cnt = contours[2]
# 计算外接圆
(x, y), r = cv2.minEnclosingCircle(cnt)
# 绘制外接圆
phone_circle = cv2.circle(phone, (int(x), int(y)), int(r), (0,255,0), 2)
cv2.imshow('contour_circle', phone_circle)
cv2.waitKey(0)# 计算最小外接矩形
x, y, w, h = cv2.boundingRect(cnt)
# 绘制矩形
phone_rect = cv2.rectangle(phone, (x, y), (x+w, y+h), (0,255,0), 2)
cv2.imshow('contour_rectangle', phone_rect)
cv2.waitKey(0)

4. 轮廓近似

使用 cv2.approxPolyDP() 函数可以对轮廓进行近似处理,简化轮廓形状:

# 函数语法
# approx = cv2.approxPolyDP(curve, epsilon, closed)# 计算近似精度(取轮廓周长的 0.01 倍)
epsilon = 0.01 * cv2.arcLength(contours[0], True)
# 对第一个轮廓进行近似
approx = cv2.approxPolyDP(contours[0], epsilon, True)# 对比原始轮廓与近似轮廓的点数量
print("原始轮廓点数量:", contours[0].shape[0])
print("近似轮廓点数量:", approx.shape[0])# 绘制近似轮廓
phone_new = phone.copy()
cv2.drawContours(phone_new, [approx], -1, (0,255,0), 3)
cv2.imshow('contour_approx', phone_new)
cv2.waitKey(0)
原始轮廓点数量: 235
近似轮廓点数量: 8

其中,epsilon 参数决定了近似精度:值越小,近似结果越接近原始轮廓;值越大,轮廓越简化。


五、总结

本文详细介绍了 OpenCV 中轮廓检测的核心技术,包括轮廓检测的预处理步骤、cv2.findContours() 函数的使用、轮廓绘制方法以及轮廓的各种属性计算与操作(面积、周长、筛选、排序、外接形状、轮廓近似等)。

轮廓检测在目标识别、图像分割、物体测量等领域有着广泛的应用,掌握这些基础操作是进行更复杂计算机视觉任务的前提。实际应用中,需要根据具体场景选择合适的轮廓检索模式和近似方法,以达到最佳的检测效果。

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

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

相关文章

【图论】 Graph.jl 概览

文章目录安装基础使用基本操作全局图的指标顶点性质边性质读写图按照 .lgz 格式存储图数据(压缩格式)按照 .lg 格式存储图数据(非压缩格式)图的绘制TikzGraphs.jl Latex 论文风格GraphPlot.jl 通常与 Compose.jl 一起使用SGtSNEpi…

[java] 控制三个线程按顺序交替输出数字123123…

控制三个线程按顺序交替输出数字123123… synchronized(配合专用锁对象) 通过共享锁和 volatile 变量控制执行顺序,每个线程按指定顺序打印指定内容,确保输出序列如 “123123…”。使用 synchronized 和 wait/notifyAll 实现线程间…

[C#]winform基于yolov8-seg实现的指甲分割实现源码

【测试环境】 vs2019 net framework4.7.2 onnxruntime1.16.3 opencvsharp 注意源码运行在CPU上不支持GPU运行,由于net framework限制GPU会很慢因此没有GPU版本提供。 【运行步骤】 打开sln项目 选择x64 debug运行即可 如需要再x64 release运行可以将x64 debu…

数据结构——线性表(链表,力扣中等篇,增删查改)

文章目录一、增删查改1.1增(插入节点)1.1.1两数后插入公约数1.1.2循环有序链表的插入1.2删(移除节点)1.2.1删除已知的node节点【交换val值】1.2.2移除数组中已存在的节点【unordered_set】1.2.3删除和为0的节点【前缀和】1.3改&am…

【Android】OkHttp发起GET请求 POST请求

三三要成为安卓糕手 一:OkHttp介绍 OkHttp 是一个开源的、强大且高效的 HTTP 客户端库,主要用于在 Java后端和Android 项目中进行网络请求。 //在gradle中添加依赖 com.squareup.okhttp3:okhttp:4.12.0二:GET请求/*** 使用OkHttp发起get请求*…

[Mysql数据库] 知识点总结8

1. 请详细描述在复制拓扑中参与复制的线程类型以及各自所承担的功能。答:当从属服务器连接到主服务器时,在主服务器上会创建 Binlog 转储线程,在从属服务器上会默 认创建 I/O 线程和 SQL 线程。- Binlog 转储线程用于从二进制日志读取事件并将…

250829-Gitlab数据备份与恢复

下面给你一份可落地的迁移方案,保证 GitLab 的数据和配置完整迁移到服务器 B。你当前用的是 GitLab Omnibus(docker 版),数据都在你映射的 3 个目录里(/etc/gitlab, /var/log/gitlab, /var/opt/gitlab)&…

吴恩达机器学习作业十一:异常检测

数据集在作业一异常检测异常检测就是发现与大部分对象不同的对象,其实就是发现离群点。异常检测有时也称偏差检测。异常对象是相对罕见的。用数据集建立概率模型p ( x ),如果新的测试数据在这个模型上小于某个阈值,则说它极大可能为异常点算法…

2000w 的数据量,mysql要进行几次IO操作,为什么

在 MySQL 中,2000 万数据量的表在进行查询时所需的 ​​IO 操作次数​​主要取决于 ​​索引结构(B树层级)​​、​​查询类型​​和 ​​数据分布特征​​。以下是具体分析:一、B树层级与 IO 次数的关系InnoDB 引擎通过 B树索引管…

【代码随想录day 22】 力扣 39. 组合总和

视频讲解:https://www.bilibili.com/video/BV1KT4y1M7HJ/?vd_sourcea935eaede74a204ec74fd041b917810c 文档讲解:https://programmercarl.com/0039.%E7%BB%84%E5%90%88%E6%80%BB%E5%92%8C.html#%E6%80%9D%E8%B7%AF 力扣题目:https://leetcod…

DrissionPage 实战:动态 IP 代理与百度翻译 API 数据抓取

本文将详细介绍如何使用 DrissionPage 实现动态 IP 代理访问,并结合百度翻译 API 进行数据抓取与处理。一、技术选型与架构设计1.1 为什么选择 DrissionPage?DrissionPage 作为新一代网络自动化工具,相比传统 Selenium Requests 方案具有显著…

策略模式:灵活应对算法动态切换

引言 在软件开发中,我们常常会遇到需要在运行时动态选择和切换算法或行为的场景。例如,电商系统中的多种支付方式、游戏中的不同难度设置,或是计算器中的各种运算符。传统的方法可能会使用复杂的条件判断语句(如if-else或switch-c…

【C++ 】string类:深拷贝与浅拷贝解析

【C 】string类操作全解析-CSDN博客 1.stirng类的模拟实现 1.1 经典的string类问题 上面已经对string类进行了简单的介绍,大家只要能够正常使用即可。在面试中,面试官总喜欢要求自己来模拟实现string类,最主要是实现string类的构造、拷贝…

Decoder 解码器

Decoder 解码器&#xff1a; #include <stdio.h> #include <stdlib.h> #include <string.h>#include <libavformat/avformat.h> #include <libavcodec/avcodec.h> #include <libswscale/swscale.h>#define WORD uint16_t #define DWORD ui…

globals() 小技巧

scheduler_class globals()[scheduler_class_name] Python 中一种 动态获取类对象 的常用技巧&#xff0c;属于 反射&#xff08;reflection&#xff09; 编程的范畴globals()Python 内置函数&#xff0c;返回一个 字典&#xff08;dict&#xff09;&#xff0c;包含当前模块&…

Android Studio 9.png制作

一、新建 二、把要做的图png导入进去 png图片建议 根据内容预留1像素可拉伸区域 eg:纯色或可渐变底色 三、右边创建.9.png 四、双击打开 1、绘制黑边 参考视频 2、缩放到800% ,移至右下 3、在下面和右边绘制整根黑线 4、根据png 位置左侧和上侧黑线 4.1 分析 红色方框为…

【百度】C++开发(25届提前批 一面)面经

文章目录1. 代码实现&#xff1a;说说LRU&#xff0c;并代码实现LRU为什么使用哈希表&#xff1f;&#xff08;有两个原因&#xff09;1. 仅用双向链表的缺陷2. 引入哈希表的作用1. 快速查找&#xff1a;2. 快速插入与删除&#xff1a;双向链表 哈希表的协作过程举例说明代码实…

Word文档怎么打印?Word打印技巧?【图文详解】单面/双面/指定页面/逆序等Word打印选项

一、问题背景 在日常办公、学习场景中&#xff0c;Word文档作为常用的文字处理载体&#xff0c;经常需要将电子内容转化为纸质版本&#xff0c;比如提交报告、打印学习资料、整理文档存档等。 但不少用户在尝试打印Word文档时&#xff0c;常会遇到各种阻碍&#xff1a;有的不清…

漫谈《数字图像处理》之基函数与基图像

在数字图像处理领域&#xff0c;基函数与基图像是贯穿理论分析与实际应用的核心概念 —— 它们如同 “乐高积木”&#xff0c;将复杂的图像信号拆解为可解释、可操作的基本单元&#xff0c;支撑起压缩、去噪、特征提取等一系列关键任务。从传统的傅里叶变换到前沿的因子场理论&…

打开多个Excel文件后快速关闭所有的文档,并且退出Excel应用

打开多个Excel文件后如果要快速关闭所有的文档&#xff0c;并且退出Excel应用&#xff0c;可以按住Shift键右上角的号&#xff08;关闭按钮&#xff09;。Word和PowerPoint也是一样的操作。如果有文档修改后没有保存&#xff0c;会提示是否保存。作为补充&#xff0c;先来看看两…