You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

opencv.js中轮廓Mat与Scalar相乘实现坐标缩放的问题咨询

OpenCV.js 轮廓缩放最简实现方案

你对轮廓Mat的type判断存在错误:OpenCV的type计算公式为 type = 深度值 + (通道数 - 1) * 8,返回值12对应的是CV_32SC2(2通道32位有符号整数),这是findContours返回轮廓的标准格式,存储的是轮廓点的(x,y)整数坐标,并非你以为的CV_8UC130。

下面是两种可直接落地的实现方案:

方案1:直接遍历轮廓点缩放(最稳妥)

轮廓点的数量通常非常少,遍历完全不会产生性能压力,逻辑清晰不易出问题:

// ratio为原图与缩小帧的缩放比,计算方式:ratio = 原图像素宽度 / 缩小后帧的像素宽度
const scaledCnt = new cv.Mat(cnt.rows, cnt.cols, cv.CV_32SC2);
for (let i = 0; i < cnt.rows; i++) {
  const x = Math.round(cnt.intAt(i, 0) * ratio);
  const y = Math.round(cnt.intAt(i, 1) * ratio);
  scaledCnt.intAt(i, 0, x);
  scaledCnt.intAt(i, 1, y);
}
// 后续可直接使用scaledCnt绘制轮廓,用完记得释放Mat避免内存泄漏
cv.drawContours(originalFrame, [scaledCnt], 0, new cv.Scalar(0,255,0,255), 2);
cnt.delete();
scaledCnt.delete();

方案2:使用内置API完成缩放(无需手动遍历)

如果不想手动遍历,可以用convertTo+cv.multiply实现,不需要额外创建全1矩阵:

const floatCnt = new cv.Mat();
cnt.convertTo(floatCnt, cv.CV_32FC2);
const scaledFloatCnt = new cv.Mat();
// 直接传入缩放系数标量,两通道分别乘ratio即可
cv.multiply(floatCnt, new cv.Scalar(ratio, ratio, 1, 1), scaledFloatCnt);
// 转回整数类型适配后续drawContours等操作
const scaledCnt = new cv.Mat();
scaledFloatCnt.convertTo(scaledCnt, cv.CV_32SC2);
// 释放中间变量
floatCnt.delete();
scaledFloatCnt.delete();
cnt.delete();

内容的提问来源于stack exchange,提问作者Olivier Maire

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 14:24:02