在opencv.js中创建带有点数组的凸包

时间:2018-04-06 13:50:33

标签: javascript opencv

我试图用带有点的数组创建一个带有opencv.js的凸包,有没有人知道如何正确有效地做到这一点?数组看起来像这样:

[
    [5,5],
    [10,10],
    [15,15]
    ...
] 

- >其中第一个值为x,第二个值为y值,但将此格式更改为更合适的格式不会有问题。

Thnx的帮助:)

2 个答案:

答案 0 :(得分:0)

让我们说你的点代表一个轮廓:

var contours = new cv.MatVector();
for (var i = 0; i < points.size(); ++i) {
   contours.push_back(new cv.Mat(points[i][0], points[i][1])
}

现在关注opencv网站的this tutorial

// approximates each contour to convex hull
for (var i = 0; i < contours.size(); ++i) {
    var tmp = new cv.Mat();
    var cnt = contours.get(i);
    // You can try more different parameters
    cv.convexHull(cnt, tmp, false, true);
    hull.push_back(tmp);
    cnt.delete(); tmp.delete();
}

答案 1 :(得分:0)

到目前为止,我可以尝试使用OpenCV以Mat格式存储CV_32SC2类型的轮廓/船体数据:本质上是[x1,y1,x2,y2,x3,y3,...]顺序的32位短整数的简单列表。

请注意32S C2 的两个通道/平面部分:一个通道用于所有x值,另一通道用于所有y值

您可以手动创建一个Mat,访问其data32S属性并填写每个值:

let testHull = cv.Mat.ones(4, 1, cv.CV_32SC2);
testHull.data32S[0] = 100;
testHull.data32S[1] = 100;
testHull.data32S[2] = 200;
testHull.data32S[3] = 100;
testHull.data32S[4] = 200;
testHull.data32S[5] = 200;
testHull.data32S[6] = 100;
testHull.data32S[7] = 200;

但是OpenCV.js附带了一种方便的方法,可以将平面值数组转换为这样的Mat:

let testHull = cv.matFromArray(4, 1, cv.CV_32SC2, [100,100,200,100,200,200,100,200])

如果数组是嵌套的,则可以简单地使用JS Array的flat()方法将其从2D数组([[x1,y1]...])展平为一维数组([x1,y1,...])。

因此,您不必担心Mat类型以及所有可以包装到一个不错的函数中的东西,例如:

function nestedPointsArrayToMat(points){
   return cv.matFromArray(points.length, 1, cv.CV_32SC2, points.flat());
}

这是一个快速演示:

function onOpenCvReady(){
  cv.then(test);
}

function nestedPointsArrayToMat(points){
   return cv.matFromArray(points.length, 1, cv.CV_32SC2, points.flat());
}

function test(cv){
  

  console.log("cv loaded");
  // make a Mat to draw into
  let mainMat = cv.Mat.zeros(30, 30, cv.CV_8UC3);
  // make a fake hull
  let points = [
                  [ 5, 5],
                  [25, 5],
                  [25,25],
                  [ 5,25]
                ]
  let hull = nestedPointsArrayToMat(points);
  console.log("hull data", hull.data32S);
  // make a fake hulls vector 
  let hulls = new cv.MatVector();
  // add the recently created hull
  hulls.push_back(hull);
  // test drawing it
  cv.drawContours(mainMat, hulls, 0, [192,64,0,0], -1, 8);
  // output to canvas
  cv.imshow('canvasOutput', mainMat);  
}
<script async src="https://docs.opencv.org/4.4.0/opencv.js" onload="onOpenCvReady();" type="text/javascript"></script>
<canvas id="canvasOutput" width="30" height="30"></canvas>

请注意,以上只是一个粗略的示例,没有数据验证或任何其他更高级的检查,但希望它能说明这一思想,以便可以根据需要进行稳健的扩展。