opencv基础52-图像轮廓学习05-凸包获取-cv2.convexHull()

news2025/6/20 6:16:17

逼近多边形是轮廓的高度近似,但是有时候,我们希望使用一个多边形的凸包来简化它。
凸包跟逼近多边形很像,只不过它是物体最外层的“凸”多边形。凸包指的是完全包含原有轮 廓,并且仅由轮廓上的点所构成的多边形。凸包的每一处都是凸的,即在凸包内连接任意两点 的直线都在凸包的内部。在凸包内,任意连续三个点的内角小于 180°。

例如,在图 12-25 中,最外层的多边形为机械手的凸包,在机械手边缘与凸包之间的部分被称为凸缺陷(Convexity Defect),凸缺陷能够用来处理手势识别等问题。

在这里插入图片描述

获取凸包

OpenCV 提供函数 cv2.convexHull()用于获取轮廓的凸包。该函数的语法格式为:

hull = cv2.convexHull( points[, clockwise[, returnPoints]] )

式中的返回值 hull 为凸包角点。
式中的参数如下:

  • points:轮廓。
  • clockwise:布尔型值。该值为 True 时,凸包角点将按顺时针方向排列;该值为 False 时,则以逆时针方向排列凸包角点。
  • returnPoints:布尔型值。默认值是 True,函数返回凸包角点的 x/y 轴坐标;当为 False时,函数返回轮廓中凸包角点的索引。

示例:观察函数 cv2.convexHull()内参数 returnPoints 的使用情况

代码如下:

import cv2
o = cv2.imread('contours.bmp')
gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
hull = cv2.convexHull(contours[0]) # 返回坐标值
print("returnPoints 为默认值 True 时返回值 hull 的值:\n",hull)
hull2 = cv2.convexHull(contours[0], returnPoints=False) # 返回索引值
print("returnPoints 为 False 时返回值 hull 的值:\n",hull2)

运行结果:

returnPoints 为默认值 True 时返回值 hull 的值:
 [[[195 270]]

 [[195 383]]

 [[ 79 383]]

 [[ 79 270]]]
returnPoints 为 False 时返回值 hull 的值:
 [[3]
 [2]
 [1]
 [0]]

从程序运行结果可以看出,函数 cv2.convexHull()的可选参数returnPoints:

  • 为默认值 True 时,函数返回凸包角点的 x/y 轴坐标,本例中返回了 4 个轮廓的坐标值。
  • 为 False 时,函数返回轮廓中凸包角点的索引,本例中返回了 4 个轮廓的索引值。

示例2:使用函数 cv2.convexHull()获取轮廓的凸包。

代码如下:

import cv2
# --------------读取并绘制原始图像------------------
o = cv2.imread('hand.bmp')
cv2.imshow("original",o)
# --------------提取轮廓------------------
gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
# --------------寻找凸包,得到凸包的角点------------------
hull = cv2.convexHull(contours[0])
# --------------绘制凸包------------------
cv2.polylines(o, [hull], True, (0, 255, 0), 2)
# --------------显示凸包------------------
cv2.imshow("result",o)
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述

凸缺陷

凸包与轮廓之间的部分,称为凸缺陷。在 OpenCV 中使用函数 cv2.convexityDefects()获取凸缺陷。其语法格式如下:

convexityDefects = cv2.convexityDefects( contour, convexhull )

式中的返回值 convexityDefects 为凸缺陷点集。它是一个数组,每一行包含的值是[起点,终点,轮廓上距离凸包最远的点,最远点到凸包的近似距离]。

需要注意的是,返回结果中[起点,终点,轮廓上距离凸包最远的点,最远点到凸包的近似距离]的前三个值是轮廓点的索引,所以需要到轮廓点中去找它们。
式中的参数如下:

  • contour 是轮廓。
  • convexhull 是凸包。

需要注意的是,用 cv2.convexityDefects()计算凸缺陷时,要使用凸包作为参数。在查找该凸包时,所使用函数 cv2.convexHull()的参数 returnPoints 的值必须是 False。
为了让大家更直观地观察凸缺陷点集,我们尝试将凸缺陷点集在一幅图内显示出来。实现方式为,将起点和终点用一条线连接,在最远点画一个圆圈。下面我们通过一个例子来展示上述操作。

示例2:使用函数 cv2.convexityDefects()计算凸缺陷。

代码如下:

import cv2
#----------------原图--------------------------
img = cv2.imread('hand.bmp')
cv2.imshow('original',img)
#----------------构造轮廓--------------------------
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray, 127, 255,0)
contours, hierarchy = cv2.findContours(binary,
 cv2.RETR_TREE,
cv2.CHAIN_APPROX_SIMPLE)
#----------------凸包--------------------------
cnt = contours[0]
hull = cv2.convexHull(cnt,returnPoints = False)
defects = cv2.convexityDefects(cnt,hull)
print("defects=\n",defects)
#----------------构造凸缺陷--------------------------
for i in range(defects.shape[0]):
 s,e,f,d = defects[i,0]
 start = tuple(cnt[s][0])
 end = tuple(cnt[e][0])
 far = tuple(cnt[f][0])
 cv2.line(img,start,end,[0,0,255],2)
 cv2.circle(img,far,5,[255,0,0],-1)
#----------------显示结果,释放图像--------------------------
cv2.imshow('result',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果:

defects=
 [[[    0   102    51 21878]]

 [[  103   184   150 13876]]

 [[  185   233   220  4168]]

 [[  233   238   235   256]]

 [[  238   240   239   247]]

 [[  240   294   255  2715]]

 [[  294   302   295   281]]

 [[  302   304   303   217]]

 [[  305   311   306   114]]

 [[  311   385   342 13666]]

 [[  385   389   386   395]]

 [[  389   489   435 20327]]]

在这里插入图片描述

判断轮廓是否是凸形的

在 OpenCV 中,可以用函数 cv2.isContourConvex()来判断轮廓是否是凸形的,其语法格式为:

retval = cv2.isContourConvex( contour )

式中:

  • 返回值 retval 是布尔型值。该值为 True 时,表示轮廓为凸形的;否则,不是凸形的。
  • 参数 contour 为要判断的轮廓。

示例:使用函数 cv2.isContourConvex()来判断轮廓是否是凸形的。

代码如下:

import cv2
o = cv2.imread('hand.bmp')
cv2.imshow("original",o)
gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary,
 cv2.RETR_LIST,
cv2.CHAIN_APPROX_SIMPLE)
#--------------凸包----------------------
image1=o.copy()
hull = cv2.convexHull(contours[0])
cv2.polylines(image1, [hull], True, (0, 255, 0), 2)
print("使用函数 cv2.convexHull()构造的多边形是否是凸形的:",
cv2.isContourConvex(hull))
cv2.imshow("result1",image1)
#------------逼近多边形--------------------
image2=o.copy()
epsilon = 0.01*cv2.arcLength(contours[0],True)
approx = cv2.approxPolyDP(contours[0],epsilon,True)
image2=cv2.drawContours(image2,[approx],0,(0,0,255),2)
print("使用函数 cv2.approxPolyDP()构造的多边形是否是凸形的:",
 cv2.isContourConvex(approx))
cv2.imshow("result2",image2)
#------------释放窗口--------------------
cv2.waitKey()
cv2.destroyAllWindows()

运行结果:

使用函数 cv2.convexHull()构造的多边形是否是凸形的: True
使用函数 cv2.approxPolyDP()构造的多边形是否是凸形的: False

在这里插入图片描述

从以上运行结果可以看出:

  • 使用函数 cv2.convexHull()构造凸包后,对绘制的凸包使用函数 cv2.isContourConvex()判断,返回值为 True,说明该轮廓是凸形的。
  • 使用函数 cv2.approxPolyDP()构造逼近多边形后,对绘制的逼近多边形使用函数cv2.isContourConvex()判断,返回值为 False,说明该轮廓(多边形)不是凸形的。

实验原图:

在这里插入图片描述

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

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

相关文章

SpringBoot3分库分表

标签:ShardingSphere5.分库.分表; 一、简介 分库分表的设计和实现方式,在之前的内容中总结过很多,本文基于SpringBoot3和ShardingSphere5框架实现数据分库分表的能力; 不得不提ShardingSphere5文档中描述的两个基本概…

伪类和伪元素有何区别?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 伪类(Pseudo-class)⭐ 伪元素(Pseudo-element)⭐ 区别总结⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前…

.NET Core反射获取带有自定义特性的类,通过依赖注入根据Attribute元数据信息调用对应的方法

前言 前段时间有朋友问道一个这样的问题,.NET Core中如何通过Attribute的元数据信息来调用标记的对应方法。我第一时间想到的就是通过C#反射获取带有Custom Attribute标记的类,然后通过依赖注入(DI)的方式获取对应服务的方法并通过…

应用在智能仓储温湿度监测系统中的温度传感芯片

近年来各行各业越来越重视产品的仓库、冷库存储环境,食品、药品、化工产品的保存都离不开冷库。温湿度是影响冷库环境的主要因素,建立实时的温湿度监控系统,保存查看完整的历史温湿度数据十分必要。 物资的保存对存储环境的质量要求较为严格…

Spring IoC 详解

目录 一、引言二、Spring Bean三、将一个类声明为 Bean 所涉及的注解四、Component 和 Bean 的区别五、注入 Bean 的注解六、Autowired 和 Resource 的区别七、Bean7.1 作用域7.2 线程安全7.3 生命周期 一、引言 IoC(Inversion of Control:控制反转) 是…

JUC线程池的实战问题引出的一系列原理问题

1 我们为什么需要使用线程池 线程过多会带来额外的开销,其中包括创建销毁线程的开销、调度线程的开销等等,同时也降低了计算机的整体性能。线程池维护多个线程,等待、监督、管理、分配可并发执行的任务。这种做法,一方面避免了处…

分享3款屏幕录制软件,一定要来看!

在数字化时代,屏幕录制软件成为了一个必不可少的工具。它可以帮助用户捕捉并记录计算机屏幕上的活动,因此选择一款功能强大、易于使用的屏幕录制软件至关重要。本文将介绍3款备受好评的屏幕录制软件,通过本文的阅读,您将了解到它们…

Android图形-刷新与显示

目录 屏幕显示原理: 显示刷新的过程 VSYNC机制具体实现 小结: 屏幕显示原理: 过程描述: 应用向系统服务申请buffer 系统服务返回一个buffer给应用 应用开始绘制,绘制完成就提交buffer,系统服务把buffer数据…

两年了^

我也想不到是到了现在 记得刚来腾讯工作半年时候,我写了一篇文章 在腾讯的这半年 之后,又经过了半年时间,我又写了一篇总结文章 一年了 现在又过了一年多,本想把两年的入职截图留下,之前因为微信存储太大把微信卸载后重…

实现功能:ChatGPT 微信助手可以自动搜索网络信息回答问题

“ ChatGPT微信助手升级内测功能上线!原先只能回答通用问题,现在遇到需要查询具体信息的问题也不愁啦。” 01 — 最近,上线了ChatGPT微信助手的体验群:《ChatGPT 微信助手上线!问答更便捷,功能持续升级中。》&#xff…

Android高手进阶教程(一)-------Android常用名令集锦(图文并茂)!

大家好,今天我们要讲的是android开发中,比较常用的名令集锦, 在我们开发中难免用到Android命令,有些确实命令确实很有用处。 特别对于一些初学者来说,命令根本没有想过用也不会用,比如他们想安装一个.apk文…

以太网网络安全协议(十三)

一、IPsec协议 IPsec。它是指在IP首部的后面追加“封装安全有效载荷”(ESP)和“认证首部”(AH) ,从而对此后的数据进行加密,不被盗取者轻易解读。 二、TLS/SLL协议 SSL最早由网景公司提出,标准化…

架构设计第42讲:美团 - 可视化全链路日志追踪

架构设计第42讲:美团 - 可视化全链路日志追踪 目前在分布式场景下,业务追踪的主流实现方式包括两类,一类是基于日志的ELK方案,一类是基于单次请求调用的会话跟踪方案。然而随着业务逻辑的日益复杂,上述方案越来越不适用…

8月10日,每日信息差

1、菜鸟国际快递“承诺达、晚必赔”覆盖22国。具体来讲,菜鸟国际快递对无忧、经济和简易三种标准产品全面升级,其中英国、意大利、加拿大、美国四国时效平均提升30%以上。凡使用这三种快递产品发货至22国的商家,其货物在速卖通电商平台享有“…

网络安全 Day29-运维安全项目-iptables防火墙

iptables防火墙 1. 防火墙概述2. 防火墙2.1 防火墙种类及使用说明2.2 必须熟悉的名词2.3 iptables 执行过程※※※※※2.4 表与链※※※※※2.4.1 简介2.4.2 每个表说明2.4.2.1 filter表 :star::star::star::star::star:2.4.2.2 nat表 2.5 环境准备及命令2.6 案例01&#xff1a…

月度资金预算情况表取的数和结算页面不一样,是为什么?

月度资金预算情况表取的数和结算页面不一样,如下图,是为什么? 取数公式: CMPRFS(‘[收支项目01030101] ‘,K(‘单位’),’’,‘’,‘0’,ZDATEQC(‘-’),ZDATE(‘-’),‘1’,‘’,‘’)CMPRFS(‘[收支项目01030102] ‘,K(‘单位…

最新版本2023UI千月影视APP源码 开源完美版前后端完美匹配 后端基于ThinkPHP框架

最新版本的2023UI千月影视APP源码是一款开源的完美版应用程序,具备前后端完美匹配的特点。该应用的后端开发基于ThinkPHP框架,这是一个广泛使用的PHP开发框架,具有稳定性和安全性方面的优势。 2023UI千月影视APP是一款提供电影、电视剧、综艺…

文旅虚拟IP内卷国风,底层流量密码是什么?

数字化浪潮下,文旅虚拟IP已逐渐成为数字经济时代全新的增长风口以及传统文化传播载体。 虚拟IP具有极高的辨识度和可塑性,既可以作为虚拟主播在线上直播聊天互动,又可以化身虚拟解说员带你学习传统文化,还可以化身虚拟向导带你玩…

我与金融 —— 境外支付系统之安全测试实践(一)

😏作者简介:博主是一位测试管理者,同时也是一名对外企业兼职讲师。 📡主页地址:【Austin_zhai】 🙆目的与景愿:旨在于能帮助更多的测试行业人员提升软硬技能,分享行业相关最新信息。…

【雕爷学编程】Arduino动手做(12)---霍尔模块之霍尔磁感应声光报警器(磁控开关,接220V)

37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的&#x…