OpenCV.js 实战教程:用 JavaScript 提取轮廓的 8 大几何属性(长宽比、填充度、等效直径等)
2026/9/5 18:17:21 网站建设 项目流程

OpenCV.js 实战教程:用 JavaScript 提取轮廓的 8 大几何属性(长宽比、填充度、等效直径等)

【免费下载链接】opencvOpen Source Computer Vision Library项目地址: https://gitcode.com/GitHub_Trending/opencv31/opencv

本文基于 OpenCV 官方 JavaScript 教程 Contour Properties 展开,讲解如何基于 OpenCV.js(OpenCV 的 WebAssembly 绑定)提取轮廓对象的常用几何属性:长宽比(Aspect Ratio)、填充度(Extent)、实心度(Solidity)、等效直径(Equivalent Diameter)、方向角(Orientation),以及基于 Mask 的极值点定位与平均颜色/灰度计算。读完后,你将掌握一套完整的“从检测到度量”的 Web 端轮廓分析流程,并能对照仓库中的绑定源码理解每个 JS API 背后的真实实现。

1. 前置知识:OpenCV.js 与轮廓系列教程的位置

OpenCV 官方提供基于 WebAssembly 的 JavaScript 绑定模块(位于 modules/js),加载后即可在浏览器中使用全局cv命名空间,调用与 C++ 版 OpenCV 高度同名的 API(如cv.boundingRectcv.contourAreacv.convexHullcv.fitEllipse等)。

本篇是 JS 版 imgproc 教程中“轮廓(Contours)”系列的中间环节:

  • 前置环节:使用cv.findContours找到轮廓、使用cv.contourArea/cv.boundingRect/cv.arcLength等基础轮廓特征函数(对应教程@prev_tutorial{tutorial_js_contour_features});
  • 本篇主题:在“轮廓”这一抽象之上,进一步派生出面向物体度量的 8 类常用属性;
  • 后续环节:更多轮廓函数,如凸性缺陷(@next_tutorial{tutorial_js_contours_more_functions})。

核心思想是:大多数高级形状描述符并不是新的底层算法,而是由“轮廓 + 基础几何 API”组合而成的派生量。理解了这一点,就能在 Web 场景中自行扩展出任意需要的形状指标。

2. 属性一:长宽比(Aspect Ratio)

长宽比定义为物体外接矩形(bounding rectangle)宽度与高度之比:

[Aspect ; Ratio = \frac{Width}{Height}]

JS 实现只需两步——先用cv.boundingRect(cnt)取得轮廓的最小外接轴对齐矩形,再取width / height

let rect = cv.boundingRect(cnt); let aspectRatio = rect.width / rect.height;

取值直觉:正方形 ≈ 1.0;横向长条物 > 1.0;纵向细长物 < 1.0。它是成本最低的粗筛指标,例如在工业视觉中先用长宽比区分“片状物/条状物”,再对可疑目标做精细测量。

3. 属性二:填充度(Extent)

填充度是轮廓面积与其外接矩形面积之比,刻画“物体填满了外接矩形多少”:

[Extent = \frac{Object ; Area}{Bounding ; Rectangle ; Area}]

let area = cv.contourArea(cnt, false); let rect = cv.boundingRect(cnt); let rectArea = rect.width * rect.height; let extent = area / rectArea;

参考值:实心矩形 ≈ 1.0,实心圆 ≈ π/4 ≈ 0.785,三角形 ≈ 0.5。实现要点是cv.contourArea(cnt, false)的第二个参数oriented:传false时按多边形顶点顺序计算(有向面积取绝对值),这与教程给出的签名一致。注意原文示例中cv.boundingRect(cnt));多写了一个右括号,正确写法如上。

4. 属性三:实心度(Solidity)

实心度是轮廓面积与其凸包(convex hull)面积之比,用于衡量物体“凹凸程度”:

[Solidity = \frac{Contour ; Area}{Convex ; Hull ; Area}]

let area = cv.contourArea(cnt, false); cv.convexHull(cnt, hull, false, true); let hullArea = cv.contourArea(hull, false); let solidity = area / hullArea;

要点说明:

  • 凸包面积永远 ≥ 轮廓面积,因此 Solidity ∈ (0, 1],凸多边形为 1.0,缺口越多值越小;典型应用是用“低 Solidity”识别被咬合、粘连或带凹槽的目标;
  • cv.convexHull(cnt, hull, false, true)的第三个参数clockwise控制凸包环绕方向,第四个参数returnPointstruehull输出凸包顶点集合,可直接再喂给cv.contourArea;为false时输出顶点的索引。

5. 属性四:等效直径(Equivalent Diameter)

等效直径定义为“与轮廓面积相同的圆”的直径:

[Equivalent ; Diameter = \sqrt{\frac{4 \times Contour ; Area}{\pi}}]

let area = cv.contourArea(cnt, false); let equiDiameter = Math.sqrt(4 * area / Math.PI);

它是把任意形状“归一化”为单一尺度指标的经典手段,在颗粒分析、缺陷面积量化中常用来与固定阈值直接比较,避免逐形状处理尺寸差异。

6. 属性五:方向角与主/次轴(Orientation)

方向角表示物体的朝向。教程使用cv.fitEllipse(最小二乘拟合椭圆)来获取,同时可得到主轴(Major Axis)与次轴(Minor Axis)长度:

let rotatedRect = cv.fitEllipse(cnt); let angle = rotatedRect.angle;

fitEllipse返回的RotatedRect包含centersize(对应主轴/次轴长度)与angle。若只需要轴对齐旋转矩形,也可以改用cv.minAreaRect(cnt);两者在轮廓点较少(少于 5 点)时行为不同,可按需选择。方向角常用于判断物体旋转姿态、统计缺陷裂纹走向等。

7. 属性六:Mask 与像素点集(cv.transpose 演示)

在很多后续统计(极值、均值)中,我们需要把物体内部的像素单独“圈”出来作为掩码(Mask)子集。教程 JS 版用cv.transpose(src, dst)演示了“整幅矩阵按行列转置”这类像素级重排操作:

  • src:输入数组;
  • dst:与src同类型的输出数组。

教程配套了一个可交互的 HTML 演示页 js_contour_properties_transpose.html,内置完整示例代码:

let src = cv.imread('canvasInput'); let dst = new cv.Mat(); cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0); cv.threshold(src, src, 120, 200, cv.THRESH_BINARY); cv.transpose(src, dst); cv.imshow('canvasOutput', dst); src.delete(); dst.delete();

这段代码的典型用法链条是:cvtColor灰度化 →threshold二值化得到前景掩码 → 对矩阵做变换处理 →imshow渲染到<canvas>。演示页通过utils.executeCode在浏览器中直接执行修改后的代码(见该 HTML 内的Try it按钮逻辑),是理解 OpenCV.js 内存管理(src.delete()/dst.delete()手动释放 Wasm 堆内存)的现成样板。

8. 属性七:极值及其位置(cv.minMaxLoc)

在得到掩码后,常用cv.minMaxLoc求出(子区域)内的最大/最小值及其坐标:

let result = cv.minMaxLoc(src, mask); let minVal = result.minVal; let maxVal = result.maxVal; let minLoc = result.minLoc; let maxLoc = result.maxLoc;

参数说明:src为单通道输入数组;mask为可选掩码,用于只统计子区域。

源码佐证:在 OpenCV.js 的 C++ 绑定层 modules/js/src/core_bindings.cpp 中可以看到该函数有两个重载——带掩码的minMaxLoc(src, mask)与不带掩码的minMaxLoc(src),内部都调用cv::minMaxLoc填充MinMaxLoc结构体(minVal/maxVal/minLoc/maxLoc四个字段),并在 绑定注册处 通过function("minMaxLoc", select_overload<...>)select_overload区分两个重载导出给 JS 侧。这解释了为何教程示例的返回值是一个含四个字段的对象。

9. 属性八:平均颜色 / 平均灰度(cv.mean)

最后,用同一个掩码计算物体的平均颜色(彩色图)或平均灰度(灰度图):

let average = cv.mean(src, mask);

参数说明:src的通道数为 1~4,这样结果才能存入Scalarmask为可选运算掩码。对 RGBA/RGB 输入,返回的Scalar逐通道给出均值,可用于颜色聚类、光照一致性校验等场景。

10. 组合实战:一次性计算全部形状指标

把上述 API 串起来,即得到一段可直接在浏览器控制台运行的度量代码(假设cnt已由cv.findContours产生,hullnew cv.MatIntVector()):

// 1) 基础量 let area = cv.contourArea(cnt, false); let rect = cv.boundingRect(cnt); let hull = new cv.MatIntVector(); cv.convexHull(cnt, hull, false, true); let hullArea = cv.contourArea(hull, false); let ellipse = cv.fitEllipse(cnt); // 2) 派生属性 let aspectRatio = rect.width / rect.height; let extent = area / (rect.width * rect.height); let solidity = area / hullArea; let equiDiameter = Math.sqrt(4 * area / Math.PI); let orientation = ellipse.angle; // 3) 基于 Mask 的统计(src 为原始灰度图,mask 为二值化前景) let mm = cv.minMaxLoc(src, mask); let mean = cv.mean(src, mask); console.log({ aspectRatio, extent, solidity, equiDiameter, orientation, minVal: mm.minVal, maxLoc: mm.maxLoc, mean });

工程上的三条实用建议:

  1. 先粗筛后精测extentaspectRatio计算代价最低,先用它们过滤,再对少量候选目标计算solidity(需凸包)与fitEllipse
  2. 掩码复用mask一次生成后,minMaxLocmean可多次复用,避免重复二值化;
  3. Wasm 内存纪律:所有new cv.Mat()/new cv.MatIntVector()创建的对象用完后必须delete()(见第 7 节示例的写法),否则会累积 WebAssembly 堆内存,这与 js_assets 下各示例 的统一风格一致。

11. 小结与延伸阅读

本文完整覆盖了教程中的 8 个轮廓属性:

属性公式核心关键 API
长宽比Width / Heightcv.boundingRect
填充度轮廓面积 / 外接矩形面积cv.contourArea+cv.boundingRect
实心度轮廓面积 / 凸包面积cv.convexHull+cv.contourArea
等效直径√(4·Area/π)cv.contourArea
方向角拟合椭圆角度cv.fitEllipse
Mask/像素点掩码区域重排演示cv.transpose
极值与位置区域 min/max 及坐标cv.minMaxLoc
平均颜色/灰度区域均值cv.mean

所有度量都构建在findContours输出之上,属于“派生指标”而非独立算法。想继续深入,可以从以下仓库位置入手:

  • 教程原文:本节全部内容的官方表述;
  • 交互演示页:可在浏览器中直接改代码运行的cv.transpose示例;
  • modules/js/src/core_bindings.cpp:OpenCV.js 手写绑定层,minMaxLocmean等函数的 Wasm 导出实现;
  • modules/js/generator/embindgen.py:JS 绑定的自动生成脚本,说明大部分cv.*API 由 C++ 头文件扫描后批量生成。

【免费下载链接】opencvOpen Source Computer Vision Library项目地址: https://gitcode.com/GitHub_Trending/opencv31/opencv

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询