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
相关产品推荐
相关产品推荐

