📜  模板匹配输出的多个边界框只需要一个 - TypeScript (1)

📅  最后修改于: 2023-12-03 14:55:53.107000             🧑  作者: Mango

模板匹配输出的多个边界框只需要一个 - TypeScript

在图像处理中,模板匹配是一种常用的技术,它可以识别图像中的特定模式。在模板匹配过程中,我们需要使用一个模板图像来与目标图像进行比较,找出与模板图像最匹配的部分。

在 TypeScript 中,我们可以使用 OpenCV.js 库来实现模板匹配。这个库是 OpenCV 的 JavaScript 版本,它提供了许多图像处理和计算机视觉算法。

对于模板匹配输出的多个边界框,我们可以通过以下步骤将它们转化为一个单独的边界框:

  1. 找到所有的边界框 我们可以使用 OpenCV.js 中的 cv.matchTemplate() 函数来找到所有匹配的位置,并将它们存储在数组中。

  2. 计算平均值 对于所有的边界框,我们可以计算它们的平均值,得到一个新的边界框。我们可以使用以下代码来实现这一步骤:

    function getAverageBoundingBox(boundingBoxes: cv.Rect[]): cv.Rect {
      let x = 0, y = 0, w = 0, h = 0;
      for (const b of boundingBoxes) {
        x += b.x;
        y += b.y;
        w += b.width;
        h += b.height;
      }
      const n = boundingBoxes.length;
      return new cv.Rect(x / n, y / n, w / n, h / n);
    }
    

    这个函数接受一个边界框数组作为参数,返回一个新的边界框。

  3. 绘制新的边界框 最后一步是在图像上绘制这个新的边界框。我们可以使用 OpenCV.js 中的 cv.rectangle() 函数来绘制矩形。以下代码展示了如何使用该函数来绘制矩形:

    cv.rectangle(
      img,                       // 要绘制矩形的图像
      new cv.Point(x, y),        // 矩形左上角的坐标
      new cv.Point(x + w, y + h),// 矩形右下角的坐标
      [0, 255, 0, 255],          // 矩形的颜色
      2                          // 线宽
    );
    

    这个函数接受一个图像、矩形的左上角和右下角坐标、颜色、线宽等参数。

最终,我们得到了一个新的边界框,它是所有边界框的平均值。将这个边界框绘制到图像上,就可以得到最终的结果。

完整代码片段如下:

function getAverageBoundingBox(boundingBoxes: cv.Rect[]): cv.Rect {
  let x = 0, y = 0, w = 0, h = 0;
  for (const b of boundingBoxes) {
    x += b.x;
    y += b.y;
    w += b.width;
    h += b.height;
  }
  const n = boundingBoxes.length;
  return new cv.Rect(x / n, y / n, w / n, h / n);
}

const img = cv.imread('canvasInput');
const templ = cv.imread('template');
const mask = new cv.Mat();

const resultMat = new cv.Mat();
cv.matchTemplate(img, templ, resultMat, cv.TM_CCOEFF_NORMED, mask);

const threshold = 0.8;
const location = new cv.Mat();
cv.threshold(resultMat, location, threshold, 1, cv.THRESH_BINARY);

const contours = new cv.MatVector();
const hierarchy = new cv.Mat();
cv.findContours(
  location, contours, hierarchy,
  cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE
);

const boundingBoxes = contours.map((contour) => cv.boundingRect(contour));
const averageBox = getAverageBoundingBox(boundingBoxes);

cv.rectangle(
  img,
  new cv.Point(averageBox.x, averageBox.y),
  new cv.Point(averageBox.x + averageBox.width, averageBox.y + averageBox.height),
  [0, 255, 0, 255],
  2
);

cv.imshow('canvasOutput', img);
cv.waitKey();

注意,这个代码片段假设你已经正确加载了 OpenCV.js 库和要处理的图像和模板图像。