OpenCV模板匹配相似对象

时间:2016-01-09 07:12:01

标签: c++ templates opencv matching

我目前正在尝试使用OpenCV模板匹配功能,使用模板检测给定图像中的所有类似对象。然而,即使它们非常相似和完全相同,我也没有检测到所有物体(血细胞)。我一直在互联网上寻找解决方案,但没有得到任何解决方案。

以下是我的代码:

cv::Mat ref = cv::imread("c:\\image.jpg");
cv::Mat tpl = cv::imread("c:\\template.jpg");

cv::Mat gref, gtpl;
cv::cvtColor(ref, gref, CV_BGR2GRAY);
cv::cvtColor(tpl, gtpl, CV_BGR2GRAY);

cv::Mat res(ref.rows-tpl.rows+1, ref.cols-tpl.cols+1, CV_32FC1);
cv::matchTemplate(gref, gtpl, res, CV_TM_CCOEFF_NORMED);
cv::threshold(res, res, 0.8, 1., CV_THRESH_TOZERO);

while (true)
{
    double minval, maxval, threshold = 0.8;
    cv::Point minloc, maxloc;
    cv::minMaxLoc(res, &minval, &maxval, &minloc, &maxloc);

    if (maxval >= threshold)
    {
        cv::rectangle(
            ref,
            maxloc,
            cv::Point(maxloc.x + tpl.cols, maxloc.y + tpl.rows),
            CV_RGB(0,255,0), 2
        );
        cv::floodFill(res, maxloc, cv::Scalar(0), 0, cv::Scalar(.1), cv::Scalar(1.));
    }
    else
        break;
}

cv::imshow("reference", ref);

这些是使用的结果和图像:

给定图像

Given Image

模板

Template

阈值设置较高的结果(0.8 / 0.8)

Result

阈值设置较低的结果(0.6 / 0.3)

enter image description here

我对模板匹配很新,有没有办法让图像中的所有对象都被检测到?

我需要模板匹配来检测更复杂图像中的细胞。

enter image description here

1 个答案:

答案 0 :(得分:2)

在您的特定情况下,您不需要使用模板匹配。您可以仅使用红色组件来检测blob。如果您使用OpenCV 3.0+,则可以使用cv::SimpleBlobDetector

无论如何,您可以使用cv::thresholdcv::findContours实现简单检测器。我尝试了以下代码:

int main()
{
  const int threshVal = 30;
  const int minArea = 15 * 15;
  const int maxArea = 100 * 100;
  cv::Mat img = cv::imread("input.jpg");

  cv::Mat bgr[3];
  cv::split(img, bgr);

  cv::Mat red_img = bgr[2];
  cv::threshold(red_img, red_img, threshVal, 255, cv::THRESH_BINARY);

  vector<vector<Point>> contours;
  vector<Vec4i> hierarchy;
  cv::findContours(red_img, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));

  for (int i = 0; i < contours.size(); i++)
  {
    int area = cv::contourArea(contours[i]);
    if (area < minArea || area > maxArea)
      continue;

    cv::Rect roi = cv::boundingRect(contours[i]);
    cv::rectangle(img, roi, cv::Scalar(0, 255, 0), 2);
  }

  cv::imshow("result", img);
  cv::waitKey(0);
  return 0;
}

此代码检测所有血细胞:

enter image description here

当然,您可能需要调整三个常量(threshValminAreamaxArea)的值,以便在所有样本上获得更好的结果。