前言
简易的直线和圆的检测较为简单,当我们面对多边形例如手掌或海星的时候,明显圆和直线就无从下手了。对于形状较为复杂的物体,可以利用凸包近似表示。凸包是图形学中常见的概念,将二维平面上的点集最外层的点连接起来构成凸多边形称为凸包。虽然凸包检测也是对轮廓进行多边形逼近,但是逼近的结果一定是凸多边形。
一.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:
示例图像:
凸包检测结果:
大家可以根据自己的手,选择合适的参数进行凸包检测
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()