OpenCV.js 核心数据结构实战指南:Point、Scalar、Size、Circle、Rect 与 RotatedRect 完整解析
【免费下载链接】opencvOpen Source Computer Vision Library项目地址: https://gitcode.com/GitHub_Trending/opencv31/opencv
本篇指南基于 OpenCV.js 官方教程 js_some_data_structures 展开,系统讲解 OpenCV.js 中最常用的 6 种基础数据结构(Point、Scalar、Size、Circle、Rect、RotatedRect)的两种构造方式、各字段含义与取值约定,并结合 modules/js/src/core_bindings.cpp 中的 Emscripten 绑定源码印证每种结构在 JavaScript 侧的真实表现形式,帮助你在 Web 端图像绘制、轮廓分析、目标跟踪等场景中正确创建与使用这些几何类型。
一、总览:JS 中的两类构造形态
OpenCV.js 通过 Emscripten 将 C++ 的cv::类型映射到 JS 的cv.命名空间下。这些映射结构在 JavaScript 中分为两种类型,这是理解全部数据结构的钥匙:
- 数组类型(array type):只有Scalar一种,它在 JS 中就是一个普通数组;
- 对象类型(object type):Point、Size、Circle、Rect、RotatedRect 均为 JS 对象,由 Emscripten 的
value_object机制生成。
每种结构都支持两种完全等价的构造方式:一种是通过new cv.Xxx(...)调用构造函数,另一种是直接写普通 JS 字面量(对象或数组)。这一设计的意义在于:许多 OpenCV.js 函数直接返回这类结构(如轮廓检测返回的Rect、旋转矩形检测返回的RotatedRect),它们本质就是普通 JS 对象,因此你自己用字面量构造的值也能作为参数传回给 OpenCV.js 函数,两种形态互通。
从源码结构看,这些类型的字段绑定集中在 modules/js/src/core_bindings.cpp 中,使用宏统一注册,例如:
#define EMSCRIPTEN_CV_SIZE(type) \ emscripten::value_object<type>(#type) \ .field("width", &type::width) \ .field("height", &type::height); #define EMSCRIPTEN_CV_POINT(type) \ emscripten::value_object<type>(#type) \ .field("x", &type::x) \ .field("y", &type::y); #define EMSCRIPTEN_CV_RECT(type, name) \ emscripten::value_object<cv::Rect_<type>> (name) \ .field("x", &cv::Rect_<type>::x) \ .field("y", &cv::Rect_<type>::y) \ .field("width", &cv::Rect_<type>::width) \ .field("height", &cv::Rect_<type>::height);这些.field(...)声明直接决定了 JS 侧对象的属性名——width、height、x、y等字段名与文档一致,且同时映射到 C++ 类型的同名成员,这是"对象字面量可以直接当参数用"的底层原因。
二、Point:二维点
点是一切几何操作的原子单位。注意:OpenCV 的坐标原点位于图像的左上角,x 轴向右、y 轴向下,这与数学坐标系相反,读坐标时务必牢记。
两种等价构造方式:
// 方式一:构造函数 let point = new cv.Point(x, y); // 方式二:对象字面量 let point = {x: x, y: y};| 参数 | 含义 |
|---|---|
x | 点的 x 坐标,原点为图像左上角 |
y | 点的 y 坐标 |
对应的绑定注册为EMSCRIPTEN_CV_POINT(Point)(modules/js/src/core_bindings.cpp),宏同样用于Point2f、Point3f,即浮点版本的点结构字段完全相同。仓库教程资源中的 js_contour_features_boundingRect.html 就展示了典型用法:由Rect计算点坐标后new cv.Point(rect.x, rect.y)构造绘制锚点。
三、Scalar:标量(颜色值载体)
Scalar 在 JavaScript 中是数组类型,这是它与其余所有结构的最大区别。它常用来表示颜色,通道顺序为 BGR(A)。
两种等价构造方式:
// 方式一:构造函数 let scalar = new cv.Scalar(R, G, B, Alpha); // 方式二:数组字面量 let scalar = [R, G, B, Alpha];| 参数 | 含义 |
|---|---|
R | 红色通道像素值 |
G | 绿色通道像素值 |
B | 蓝色通道像素值 |
Alpha | alpha 通道像素值 |
源码中 Scalar 通过emscripten::value_array<cv::Scalar_<double>>("Scalar")注册并绑定 4 个索引元素(modules/js/src/core_bindings.cpp),这与文档"Scalar 是数组类型"的表述完全吻合——它本质上是一个cv::Scalar_<double>的数组视图。因此在 JS 侧你可以直接按索引访问scalar[0]~scalar[3]。实际使用非常频繁,例如 js_camshift.html 中用new cv.Scalar(30, 30, 0)与new cv.Scalar(180, 180, 180)定义颜色追踪的上下界,js_basic_ops_copymakeborder.html 中用new cv.Scalar(255, 0, 0, 255)指定边框颜色。
四、Size:尺寸
Size 表示宽与高两个维度,常见于 Mat 尺寸、RotatedRect 的 size 字段等场景。
两种等价构造方式:
// 方式一:构造函数 let size = new cv.Size(width, height); // 方式二:对象字面量 let size = {width: width, height: height};| 参数 | 含义 |
|---|---|
width | 宽度 |
height | 高度 |
注册宏EMSCRIPTEN_CV_SIZE同时作用于Size与Size2f(modules/js/src/core_bindings.cpp),即浮点尺寸Size2f拥有相同的width/height字段结构。
五、Circle:圆
Circle 由圆心与半径定义,常用于cv.minEnclosingCircle等轮廓拟合结果的表示与绘制(cv.circle的底层参数即由此而来)。
两种等价构造方式:
// 方式一:构造函数 let circle = new cv.Circle(center, radius); // 方式二:对象字面量 let circle = {center: center, radius: radius};| 参数 | 含义 |
|---|---|
center | 圆心(Point 类型) |
radius | 圆的半径 |
值得注意的是源码中 Circle 绑定的是辅助类型binding_utils::Circle(modules/js/src/core_bindings.cpp),字段仍为center与radius,与文档参数一一对应。
六、Rect:轴对齐矩形
Rect 是最常用的几何结构之一:ROI 裁剪、轮廓外接矩形(boundingRect)、目标跟踪窗口都依赖它。
两种等价构造方式:
// 方式一:构造函数 let rect = new cv.Rect(x, y, width, height); // 方式二:对象字面量 let rect = {x: x, y: y, width: width, height: height};| 参数 | 含义 |
|---|---|
x | 矩形左上角顶点的 x 坐标 |
y | 矩形左上角顶点的 y 坐标 |
width | 矩形宽度 |
height | 矩形高度 |
关键约定:x、y是左上角顶点坐标,而不是中心点——这与 RotatedRect 的center约定不同,混用时容易出错。源码中EMSCRIPTEN_CV_RECT宏还同时注册了Rect2f、Rect2d两个浮点变体(modules/js/src/core_bindings.cpp 对应 modules/js/src/core_bindings.cpp),字段结构完全相同。教程资源 js_basic_ops_roi.html 展示了let rect = new cv.Rect(100, 100, 200, 200)用于定义图像 ROI 的典型写法。
七、RotatedRect:旋转矩形及其两个派生函数
RotatedRect 表示一个可旋转的矩形,由中心点、尺寸和旋转角三元组定义,是cv.minAreaRect(最小外接旋转矩形)等轮廓分析函数的返回类型。
两种等价构造方式:
// 方式一:构造函数 let rotatedRect = new cv.RotatedRect(center, size, angle); // 方式二:对象字面量 let rotatedRect = {center: center, size: size, angle: angle};| 参数 | 含义 |
|---|---|
center | 矩形的质心(mass center) |
size | 矩形的宽和高(Size 类型) |
angle | 顺时针方向的旋转角;当角度为 0、90、180、270 等整 90 度时,旋转矩形退化为正放矩形 |
绑定源码中 RotatedRect 的三个字段逐一映射(modules/js/src/core_bindings.cpp):
emscripten::value_object<cv::RotatedRect>("RotatedRect") .field("center", &cv::RotatedRect::center) .field("size", &cv::RotatedRect::size) .field("angle", &cv::RotatedRect::angle);7.1 获取旋转矩形的 4 个顶点:cv.RotatedRect.points
使用函数cv.RotatedRect.points(rotatedRect),传入旋转矩形,返回其 4 个顶点组成的数组:
let vertices = cv.RotatedRect.points(rotatedRect); let point1 = vertices[0]; let point2 = vertices[1]; let point3 = vertices[2]; let point4 = vertices[3];@param rotatedRect旋转矩形。返回的每个顶点是Point2f类型的点(浮点坐标),可用cv.polylines等在图像上描出旋转后的矩形轮廓。
从源码结构看,该功能的底层实现是binding_utils::rotatedRectPoints(modules/js/src/core_bindings.cpp):调用 C++ 侧obj.points(points)得到cv::Point2f points[4],再逐个 push 进 Emscripten 数组返回,因此 JS 侧拿到的一定是长度 4 的数组,元素可直接按vertices[0..3]取用。该函数同时还注册为boxPoints别名(modules/js/src/core_bindings.cpp)。
7.2 获取旋转矩形的外接正放矩形:cv.RotatedRect.boundingRect
使用函数cv.RotatedRect.boundingRect(rotatedRect):
let boundingRect = cv.RotatedRect.boundingRect(rotatedRect);@param rotatedRect旋转矩形。返回值是包围该旋转矩形的轴对齐 Rect(整数坐标),可用于后续MatROI 裁剪、cv.rectangle绘制等只接受正放矩形的场景。
对应底层绑定为rotatedRectBoundingRect(返回整型Rect)与rotatedRectBoundingRect2f(返回Rect2f)(modules/js/src/core_bindings.cpp),二者分别调用 C++ 的obj.boundingRect()与obj.boundingRect2f(),区别仅在于坐标取整精度。
实践建议:当RotatedRect需要喂给要求整型Rect的 API 时(如Mat的ROI构造函数),先经boundingRect转换;当只需要在画布上画出精确的旋转轮廓时,直接取points的四点绘制多边形更精确。
八、六大结构速查表
| 结构 | JS 类型 | 构造方式一 | 构造方式二 | 字段 |
|---|---|---|---|---|
| Point | 对象 | new cv.Point(x, y) | {x: x, y: y} | x, y |
| Scalar | 数组 | new cv.Scalar(R, G, B, Alpha) | [R, G, B, Alpha] | 索引 0~3 |
| Size | 对象 | new cv.Size(width, height) | {width, height} | width, height |
| Circle | 对象 | new cv.Circle(center, radius) | {center, radius} | center, radius |
| Rect | 对象 | new cv.Rect(x, y, width, height) | {x, y, width, height} | x, y(左上角), width, height |
| RotatedRect | 对象 | new cv.RotatedRect(center, size, angle) | {center, size, angle} | center, size, angle(顺时针) |
九、小结
- 除 Scalar 为数组外,其余结构均为对象,且都支持"构造函数 / 字面量"两种等价写法,可自由混用;
- 坐标系统一以图像左上角为原点;
Rect的x、y是左上角坐标,RotatedRect的center是质心坐标,二者语义不同;RotatedRect的两个静态工具函数points(4 顶点)与boundingRect(外接正放矩形)是轮廓分析与绘制的关键桥梁,其底层实现在 modules/js/src/core_bindings.cpp 中均可追溯;- 更丰富的实战上下文可参考仓库教程资源目录 doc/js_tutorials/js_assets 下各示例页面(如 js_contour_features_minAreaRect.html 演示了从轮廓到
RotatedRect再到绘制的完整链路)。
【免费下载链接】opencvOpen Source Computer Vision Library项目地址: https://gitcode.com/GitHub_Trending/opencv31/opencv
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考