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

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

相关文章

Leetcode-每日一题【剑指 Offer 13. 机器人的运动范围】

题目 地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例…

vue封装公共方法(export default install)—2

定义一validate.js文件内容如下: validate.js封装部分 const rules {email: {ex: /^\w([-.]\w)*\w([-.]\w)*\.\w([-.]\w)*$/,msg: 请输入正确的email地址},mobile: {ex: /^1[0-9]{10}$/,msg: 请输入正确的手机号}....此还可添加的其他的校验方法 }const compare…

Git介绍及常用命令详解

一、Git的概述 Git是一个分布式版本控制工具,通常用来对软件开发过程中的源代码文件进行管理。 Git 会跟踪我们对文件所做的更改,因此我们可以记录已完成的工作,并且可以在需要时恢复到特定或以前的版本。Git 还使多人协作变得更加容易&…

Zabbix自动注册服务器及部署代理服务器

文章目录 一.zabbix自动注册1.什么是自动注册2.环境准备3.zabbix客户端配置4.在 Web 页面配置自动注册5.验证自动注册 二.部署 zabbix 代理服务器1.分布式监控的作用:2.环境部署3.代理服务器配置4.客户端配置5.web页面配置5.1 删除原来配置5.2 添加代理5.3 创建主机…

仿到位|独立版家政上门预约服务小程序家政保洁师傅上门服务小程序上门服务在线派单源码

上门预约服务派单小程序家政 小程序 同城预约 开源代码 独立版. 程序完整,经过安装检测,可放心下载安装。 适合本地的一款上门预约服务小程序,功能丰富,适用多种场景。 程序功能:城市管理/小程序DIY/服务订单/师傅管理/会员卡功能/营销功能/文章功能等等

【腾讯云 Cloud Studio 实战训练营】一个新的趋势已来

写在前面:博主是一只经过实战开发历练后投身培训事业的“小山猪”,昵称取自动画片《狮子王》中的“彭彭”,总是以乐观、积极的心态对待周边的事物。本人的技术路线从Java全栈工程师一路奔向大数据开发、数据挖掘领域,如今终有小成…

C++项目:在线五子棋对战网页版--数据模块开发

数据模块开发设计 数据管理模块,基于mysql数据库进行数据管理以及封装数据管理模块实现数据库访问。因此,在数据库中,我需要为每一张表创建出对应类,通过类实例化的对象来访问这张数据库表中的数 据,这样的话当我们要…

环保行业如何开发废品回收微信小程序

废品回收是近年来受到越来越多人关注的环保行动。为了推动废品回收的普及和方便,我们可以利用微信小程序进行制作,方便人们随时随地参与废品回收。 首先,我们需要注册并登录乔拓云账号,并进入后台。乔拓云是一个提供微信小程序制作…