凸包检测的小应用——手掌检测

387 阅读2分钟

前言

    简易的直线和圆的检测较为简单,当我们面对多边形例如手掌或海星的时候,明显圆和直线就无从下手了。对于形状较为复杂的物体,可以利用凸包近似表示。凸包是图形学中常见的概念,将二维平面上的点集最外层的点连接起来构成凸多边形称为凸包。虽然凸包检测也是对轮廓进行多边形逼近,但是逼近的结果一定是凸多边形。

一.convexHull说明

convexHull(InputArray  points,
           OutPutArray  hull,
           bool  clockwise = false,
           bool  returnPoints = true)

points: 输入的二维点集或轮廓坐标.
hull: 输出凸包的顶点
clockwise方向标志。当参数值为Ture时,凸包顺序为顺时针方向,当参数取值为False时为逆时针
returnPoints 输出数据的类型标志。当参数为True时,第二个参数输出的结果是凸包顶点坐标;当参数取值为Flase时间,第二个参数输出的结果是凸包顶点的索引。

二.凸包检测流程

2.1 输入图像(三通道或单通道)
2.2 图像二值化(三通道2单通道再二值化)
2.3 开运算消除细小区域
2.4 轮廓发现
----2.4.1 计算凸包
----2.4.2 绘制凸包
----2.4.3 绘制凸包顶点
----2.4.4 连接凸包
2.5 展示图像

三 demo:

示例图像:

0.jpg 凸包检测结果: contours.jpg 大家可以根据自己的手,选择合适的参数进行凸包检测

import cv2


img = cv2.imread('0.jpg')  # 读入图像
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 图像灰度化
dst_img = cv2.equalizeHist(gray_img)# 应用直方图均衡化
gaussian_img = cv2.GaussianBlur(dst_img, (11, 11), 0)# 高斯滤波降噪
ret, thresh_img = cv2.threshold(gaussian_img, 90, 255, cv2.THRESH_BINARY)  # 二值化,取阈值为235
dst_thresh_img = cv2.bitwise_not(thresh_img)  # 二值图像取反
#
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 1))  # 设置核
opening_img = cv2.morphologyEx(dst_thresh_img, cv2.MORPH_OPEN, kernel)  # 开运算
_, contours, hierarchy = cv2.findContours(opening_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

cnt = contours[0]
for c in range(len(contours)):
   # 是否为凸包
   ret = cv2.isContourConvex(contours[c])
   # 凸包检测
   points = cv2.convexHull(contours[c])
   total = len(points)
   for i in range(len(points)):
       x1, y1 = points[i % total][0]
       x2, y2 = points[(i+1) % total][0]
       cv2.circle(img, (x1, y1), 4, (255, 0, 0), 2, 8, 0)
       cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2, 8, 0)
# 显示
cv2.imshow("contours", img)
cv2.waitKey(0)
cv2.destroyAllWindows()