3.7 凸包、凸缺陷与 Solidity
总目录:1.1 OpenCV介绍与学习路线 | 第三章:边缘、轮廓与几何 | 编号:3.7
← 上一节:3.6 外接矩形与透视变换 | 下一节:4.1 完整的形状检测流程 →
3.7 凸包、凸缺陷与 Solidity
想象用一根橡皮筋把五角星紧紧套住。橡皮筋不会钻进星星的凹口,而是直接跨过去。绷紧后的外轮廓就是凸包,星星与橡皮筋之间的凹口就是凸缺陷。
一、凸包:用橡皮筋包住轮廓

hull_points = cv2.convexHull(contour)
cv2.drawContours(result, [hull_points], 0, (0, 255, 0), 2)
凸图形的凸包大致就是自己;凹图形的凸包会跨过凹陷。
二、凸缺陷:原轮廓凹进去的地方

每个凸缺陷由:
- 起点索引;
- 终点索引;
- 最远凹点索引;
- 最远点到凸包边的近似深度;
组成。手势识别中,手指之间的凹口就是经典例子。
三、convexHull 的两种返回形式
返回凸包点:
hull_points = cv2.convexHull(contour, returnPoints=True)
返回凸包点在原轮廓里的索引:
hull_indices = cv2.convexHull(contour, returnPoints=False)
画凸包需要点;计算凸缺陷需要索引。两个不要拿反。
四、convexityDefects 的四个值
hull_indices = cv2.convexHull(contour, returnPoints=False)
if hull_indices is not None and len(hull_indices) >= 3:
defects = cv2.convexityDefects(contour, hull_indices)
else:
defects = None
遍历:
if defects is not None:
for defect in defects[:, 0, :]:
start_i, end_i, far_i, depth_fixed = defect
start = tuple(contour[start_i, 0])
end = tuple(contour[end_i, 0])
far = tuple(contour[far_i, 0])
depth = depth_fixed / 256.0
if depth > 10:
cv2.line(result, start, end, (0, 255, 0), 2)
cv2.circle(result, far, 4, (0, 0, 255), -1)
深度除以 256,是因为 OpenCV 用带 8 位小数部分的定点表示保存它。
五、Solidity:轮廓把凸包装满了多少
Solidity 常定义为:
轮廓面积 / 凸包面积
area = cv2.contourArea(contour)
hull = cv2.convexHull(contour)
hull_area = cv2.contourArea(hull)
solidity = area / hull_area if hull_area > 0 else 0.0
- 接近 1:轮廓很凸、很饱满;
- 较小:凹陷多或凹陷深。
矩形、圆、三角形理论上都比较接近 1;五角星通常更低。但具体数值受分辨率、边缘噪声、旋转和二值化影响,原笔记中的经验区间不能当通用标准。
六、这些特征适合怎样使用
判断是不是凹形
is_convex = cv2.isContourConvex(contour)
区分十字形与五角星
可以组合:
isContourConvex;- solidity;
- 深凸缺陷数量;
- 多边形逼近顶点;
- 旋转归一化后的形状匹配。
def concavity_features(contour):
area = cv2.contourArea(contour)
hull_points = cv2.convexHull(contour)
hull_area = cv2.contourArea(hull_points)
return {
"convex": cv2.isContourConvex(contour),
"solidity": area / hull_area if hull_area > 0 else 0.0,
}
调参原则
先过滤小轮廓
↓
再计算凸包与缺陷
↓
按“相对尺寸”设深度阈值,而不是只写固定 10 像素
↓
用自己的样本统计 solidity 分布
相对深度示例:
x, y, w, h = cv2.boundingRect(contour)
scale = max(w, h)
deep = depth / scale > 0.05 if scale > 0 else False
七、参考
← 上一节:3.6 外接矩形与透视变换 | 下一节:4.1 完整的形状检测流程 →
留言区
不收集任何个人信息;昵称只绑定浏览器里的随机 Cookie。