3.5 多边形逼近与形状识别
总目录:1.1 OpenCV介绍与学习路线 | 第三章:边缘、轮廓与几何 | 编号:3.5
← 上一节:3.4 轮廓几何特征 | 下一节:3.6 外接矩形与透视变换 →
3.5 多边形逼近与形状识别
轮廓沿着像素边界走,哪怕是一条直线也可能保存很多点。多边形逼近会把这些点压缩成“足以描述形状的几个拐角”。
一、为什么要把轮廓简化成多边形
原始轮廓:很多细碎像素点
↓ approxPolyDP
逼近轮廓:少量关键顶点
顶点变少后,我们可以粗略判断三角形、四边形等,也能减少后续点排序和透视变换的计算。
二、approxPolyDP 与 epsilon
perimeter = cv2.arcLength(contour, True)
epsilon = 0.02 * perimeter
approx = cv2.approxPolyDP(contour, epsilon, True)
curve:原轮廓;epsilon:允许逼近曲线与原曲线之间的最大距离;closed=True:按闭合形状处理。
epsilon 小 → 更贴近原轮廓 → 顶点更多
epsilon 大 → 简化更强 → 顶点更少
0.02 * perimeter 是常见起点,不是固定答案。边缘抖动大时先改善二值图和轮廓,不要一味增大 epsilon 把错误“压平”。
三、顶点数只能做初步判断
vertices = len(approx)
最简单的规则:
3 个点 → 可能是三角形
4 个点 → 可能是四边形
更多点 → 可能是圆、星形或复杂轮廓
“大于 4 就当圆”只适合非常干净的教学图。一个五角星、一块锯齿噪声、一个六边形都能轻松骗过它。
四、矩形、圆形和凹形怎样区分
四边形
先确认:
- 4 个顶点;
cv2.isContourConvex(approx)为真;- 面积足够大;
- 角度或边长关系大致合理。
正方形与长方形可以用旋转外接矩形的长宽比初筛,比轴对齐框更不怕旋转:
rect = cv2.minAreaRect(approx)
w, h = rect[1]
ratio = max(w, h) / min(w, h) if min(w, h) > 0 else float("inf")
ratio 接近 1 时像正方形,但透视会让真实正方形变成一般四边形。
圆形
圆形优先看 圆度,不要只数顶点:
circularity = 4 * np.pi * area / (perimeter ** 2)
凹形
is_convex = cv2.isContourConvex(approx)
五角星、十字形等会出现凹陷。进一步区别见 3.7 凸包凸缺陷与Solidity。
五、一个更稳妥的分类函数
下面仍是教学级规则,但比“只看顶点数”完整:
import cv2
import numpy as np
def classify_contour(contour):
area = cv2.contourArea(contour)
if area < 500:
return "noise"
perimeter = cv2.arcLength(contour, True)
if perimeter <= 0:
return "degenerate"
approx = cv2.approxPolyDP(contour, 0.02 * perimeter, True)
vertices = len(approx)
convex = cv2.isContourConvex(approx)
circularity = 4 * np.pi * area / (perimeter ** 2)
if vertices == 3 and convex:
return "triangle"
if vertices == 4 and convex:
_, (w, h), _ = cv2.minAreaRect(approx)
if min(w, h) == 0:
return "quadrilateral"
ratio = max(w, h) / min(w, h)
return "square" if ratio < 1.12 else "rectangle"
if circularity > 0.80:
return "circle"
if not convex:
return "concave"
return "polygon"
这里的 500、1.12、0.80 都是需要用自己数据验证的经验阈值。


原图与输出图可以留下来当结果示意,但原笔记里大量重复的函数截图已经改成正文代码。
分类失败时先查什么
顶点乱跳 → 二值边缘抖动、epsilon 太小
矩形变圆 → epsilon 太大或轮廓本来就糊
圆被当多边形 → 圆度阈值太高、轮廓破损
星形被当圆 → 只看顶点数,没有检查凸性/solidity
← 上一节:3.4 轮廓几何特征 | 下一节:3.6 外接矩形与透视变换 →
留言区
不收集任何个人信息;昵称只绑定浏览器里的随机 Cookie。