首页
/ OpenCV.js 图像轮廓特征全解:cv.moments、轮廓面积、周长、凸包与最小外接拟合

OpenCV.js 图像轮廓特征全解:cv.moments、轮廓面积、周长、凸包与最小外接拟合

2026-09-06 11:32:35作者:丁柯新Fawn

OpenCV 的 imgproc 模块提供了一组围绕轮廓(contour)提取形状特征的核心 API,覆盖质心与矩、面积、周长、多边形逼近、凸包、包围盒以及直线/椭圆拟合等常用操作。本文以 OpenCV.js 官方教程 Contour Features教程源文件)为主体,逐一讲解 cv.momentscv.contourAreacv.arcLengthcv.approxPolyDPcv.convexHull 等 10 个函数的参数含义、使用方式与底层实现原理,读完即可在前端环境中对任意轮廓完成从特征提取到几何拟合的完整分析。

1. 矩(Moments):提取质心与面积的第一站

图像矩(Image Moments)是计算物体重心(center of mass)、面积等特征的基础数学工具。OpenCV 中对应函数为 cv.moments(array, binaryImage = false)

参数 说明
array 光栅图像(单通道、8 位或浮点 2D 数组),或一个 2D 点数组(1×N 或 N×1)
binaryImage true 时,图像中所有非零像素均按 1 处理。该参数仅对图像输入有效

函数返回一个 Moments 对象 M,其中包含 M.m00M.m10M.m01 等元素。质心(centroid)由矩的比值给出:

  • Cx=M10M00C_x = \dfrac{M_{10}}{M_{00}}
  • Cy=M01M00C_y = \dfrac{M_{01}}{M_{00}}

对应 JS 代码(继承自原文档示例):

let M = cv.moments(cnt, true);
let cx = M.m10 / M.m00;
let cy = M.m01 / M.m00;

官方提供的交互式演示页面 js_contour_features_moments.html 在浏览器中加载 OpenCV.js 后对输入图像调用该函数,实时显示计算出的矩与质心坐标,可直接在页面上验证上述公式。

2. 轮廓面积:cv.contourArea

轮廓面积可以直接由矩得到(即 M.m00),但 OpenCV 提供了专门的函数 cv.contourArea(contour, oriented = false)

参数 说明
contour 输入 2D 点向量(轮廓顶点)
oriented 有向面积标志。为 true 时返回带符号的面积值,符号取决于轮廓方向(顺时针或逆时针),因此可通过面积符号判断轮廓的绕行方向;默认 false,返回面积的绝对值

交互式示例见 js_contour_features_area.html。从源码结构看,该函数与 momentsarcLength 等轮廓特征计算均实现于 imgproc 模块的 modules/imgproc/src/ 目录下,属于 C/C++ 内核能力,OpenCV.js 通过 JS 绑定层 将其暴露给浏览器端使用。

3. 轮廓周长(弧长):cv.arcLength

周长也称弧长(arc length),由 cv.arcLength(curve, closed) 计算:

参数 说明
curve 输入 2D 点向量
closed 标志位,指示曲线是否闭合。轮廓一般应传 true,否则首尾顶点之间的这段距离不会计入

交互式示例见 js_contour_features_perimeter.html。典型用法是 cv.arcLength(cnt, true),返回值是首尾相邻顶点间欧氏距离的累加。

4. 轮廓逼近:cv.approxPolyDP

cv.approxPolyDP(curve, approxCurve, epsilon, closed) 按指定精度将轮廓逼近为顶点更少的形状,其算法实现是 Douglas-Peucker(Ramer-Douglas-Peucker)折线简化算法:

参数 说明
curve 存储 2D 点序列的输入(cv.Mat
approxCurve 逼近结果,类型需与输入曲线一致
epsilon 逼近精度参数,即原始曲线与其逼近之间的最大允许距离
closed true 时逼近后的曲线闭合(首尾顶点相连)

epsilon 越小,逼近结果保留的细节越多、顶点越密集;epsilon 越大,轮廓被简化得越厉害。该算法在 OpenCV C++ 内核中的实现可参考 contours_approx.cpp。浏览器端交互演示见 js_contour_features_approxPolyDP.html

一个常见的实战模式是:先 findContours,再对每个轮廓做 approxPolyDP,最后统计顶点数——三角形约 3 个、矩形 4 个,从而做多边形分类。

5. 凸包与凸性缺陷:cv.convexHull

凸包(Convex Hull)在外观上与轮廓逼近相似,但二者原理完全不同(个别情况下结果可能相同)。cv.convexHull(points, hull, clockwise = false, returnPoints = true) 会检查曲线的凸性缺陷并加以修正:

参数 说明
points 输入 2D 点集
hull 输出的凸包
clockwise 方向标志。为 true 时输出顺时针方向的凸包,否则为逆时针。约定的坐标系 X 轴向右、Y 轴向上
returnPoints 操作标志。当输出为矩阵时,true 返回凸包点本身,false 返回凸包点在输入点集中的索引

凸曲线总是向外凸出或至少是平的;向内凹陷的部分称为凸性缺陷(convexity defects),即凸包与轮廓之间的局部最大偏差。原文档以手部图像为例:红色折线勾勒出手的凸包,双向箭头标出的正是各指缝处的凸性缺陷。交互式示例见 js_contour_features_convexHull.html

需要区分的是:cv.convexHull 负责“求出凸包”,而缺陷的深度分析(cv.convexityDefects)属于后续教程 More functions 的范畴,可在 同系列的 next 教程 之后继续查阅。

6. 检查凸性:cv.isContourConvex

判断一条曲线是否凸出,只需调用 cv.isContourConvex(contour),返回布尔值:

cv.isContourConvex(cnt); // true 或 false

原文档对此的评价是“很简单,没什么大不了的”——它正是轮廓过滤中最轻量的谓词,例如在目标检测后快速剔除严重退化的非凸碎片。

7. 包围盒(Bounding Rectangle)

OpenCV 提供两种包围矩形,适用于不同场景。

7.a. 轴对齐矩形:cv.boundingRect

cv.boundingRect(points)points 为输入 2D 点集)返回一个与坐标轴平行的矩形。它不考虑物体旋转,因此其面积通常不是最小的。当物体基本正放时,它计算最快、语义最直观。交互演示:js_contour_features_boundingRect.html

7.b. 旋转矩形:cv.minAreaRect

cv.minAreaRect(points) 返回面积最小的旋转包围盒(cv.RotatedRect),其中包含矩形中心、宽高等尺寸与旋转角度。当目标存在明显倾斜时,minAreaRect 给出的贴合度显著优于 boundingRect,常用于倾斜文档检测、倾斜矫正前的角度估计等。交互演示:js_contour_features_minAreaRect.html

8. 最小外接圆:cv.minEnclosingCircle

cv.minEnclosingCircle(points) 求出一个能完全覆盖点集且面积最小的圆(circumcircle),返回圆心与半径。绘制时用 cv.circle(img, center, radius, color, thickness = 1, lineType = cv.LINE_8, shift = 0)

参数 说明
img 绘制目标图像
center 圆心
radius 半径
color 圆的颜色
thickness 轮廓线宽;为负值时绘制实心圆
lineType 圆边界的线型
shift 圆心坐标与半径中的小数位数(fractional bits)

交互演示:js_contour_features_minEnclosingCircle.html。最小外接圆在缺陷检测(判断零件近似度)、ROI 快速估计等场景中很常用。

9. 椭圆拟合:cv.fitEllipse

cv.fitEllipse(points) 对点集拟合椭圆,返回内接于一个旋转矩形的椭圆表示(cv.RotatedRect)。绘制使用 cv.ellipse(img, box, color, thickness = 1, lineType = cv.LINE_8)

参数 说明
img 图像
box 以 RotatedRect 表示的椭圆,函数绘制内接于该旋转矩形的椭圆
color 椭圆颜色
thickness 椭圆弧线线宽;为负值时绘制实心椭圆扇区
lineType 椭圆边界线型

注意输入点集至少需要 5 个点,否则拟合无意义。交互演示:js_contour_features_fitEllipse.html。椭圆拟合典型用途包括:倾斜圆形目标的角度估计、镜头畸变下的圆形分析等。

10. 直线拟合:cv.fitLine

cv.fitLine(points, line, distType, param, reps, aeps) 对点集做直线最小二乘/鲁棒拟合:

参数 说明
points 输入 2D 点集
line 输出直线参数,4 元素的 Mat [vx, vy, x0, y0][vx, vy] 是共线单位向量,[x0, y0] 是线上一点
distType M-估计器使用的距离类型(见 cv.DistanceTypes,如 cv.DIST_L2cv.DIST_L1cv.DIST_HUBERcv.DIST_FAIR
param 部分距离类型的数值参数 C;为 0 时选取最优值
reps 半径(坐标原点到直线的距离)的足够精度
aeps 角度的足够精度

原文档建议 repsaeps 的默认值取 0.01。绘制直线用 cv.line(img, pt1, pt2, color, thickness = 1, lineType = cv.LINE_8, shift = 0),其中 pt1pt2 为线段端点,shift 为点坐标的小数位数。得到 [vx, vy, x0, y0] 后,可沿方向向量向两端延伸足够长度,构造 pt1 = (x0 - 100*vx, y0 - 100*vy)pt2 = (x0 + 100*vx, y0 + 100*vy) 再调用 cv.line。交互演示:js_contour_features_fitLine.html

源码层面:这些函数在 OpenCV 中的位置

  • 上述轮廓特征 API 的 C++ 声明位于 imgproc 模块头文件 imgproc.hpp,实现集中于 modules/imgproc/src/(其中 contours_approx.cpp 承载了 approxPolyDP 等多边形逼近相关实现,contours_*.cpp 系列则是轮廓查找内核)。
  • OpenCV.js 并不是重新实现这些算法,而是通过 WASM 将同一套 C++ 内核编译到浏览器。绑定与加载逻辑可参考 core_bindings.cpploader.js,因此浏览器端教程中的每个“Try it”页面都运行与桌面版一致的算法代码。
  • 同一套 API 在 Python 教程中有平行版本,参数说明完全一致(cv2.momentscv2.contourAreacv2.approxPolyDP 等),可对照 py_contour_features.markdown 学习,便于前后端代码互译。

参数速查表

函数 输入 关键输出 适用场景
cv.moments 单通道图像或点集,binaryImage 标志 各阶矩;质心 = m10/m00m01/m00 质心、面积、形状矩
cv.contourArea 轮廓点集,oriented 标志 面积(可带符号) 轮廓大小、方向判断
cv.arcLength 曲线点集,closed 标志 周长 圆度、边界复杂度
cv.approxPolyDP 曲线、epsilonclosed 简化后的多边形 形状分类、降噪
cv.convexHull 点集、clockwisereturnPoints 凸包点或索引 缺陷分析、外形包络
cv.isContourConvex 轮廓 布尔值 快速过滤
cv.boundingRect 点集 轴对齐矩形 快速 ROI
cv.minAreaRect 点集 最小旋转矩形 倾斜目标定位
cv.minEnclosingCircle 点集 圆心 + 半径 圆形 ROI、近似度判断
cv.fitEllipse 点集(≥5 点) RotatedRect 表示的椭圆 角度估计
cv.fitLine 点集 + M-估计器参数 [vx, vy, x0, y0] 边缘/直线提取

小结

本文覆盖的 10 个函数构成了 OpenCV 轮廓特征提取的标准工具箱:矩负责描述性统计,contourArea/arcLength 给出尺度特征,approxPolyDP 做形状简化,convexHullisContourConvex 处理凸性,boundingRect/minAreaRect/minEnclosingCircle 提供三类包围几何,fitEllipse/fitLine 完成参数化拟合。所有函数在 OpenCV.js 中的行为与桌面版 C++/Python API 一一对应,交互式演示页面(js_assets 目录 下的 js_contour_features_*.html)可直接在浏览器中打开验证,是学习轮廓特征最快捷的路径。

登录后查看全文
热门项目推荐
相关项目推荐