我目前正在尝试使用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);
这些是使用的结果和图像:
给定图像
模板
阈值设置较高的结果(0.8 / 0.8)
阈值设置较低的结果(0.6 / 0.3)
我对模板匹配很新,有没有办法让图像中的所有对象都被检测到?
我需要模板匹配来检测更复杂图像中的细胞。
答案 0 :(得分:2)
在您的特定情况下,您不需要使用模板匹配。您可以仅使用红色组件来检测blob。如果您使用OpenCV 3.0+,则可以使用cv::SimpleBlobDetector
。
无论如何,您可以使用cv::threshold
和cv::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;
}
此代码检测所有血细胞:
当然,您可能需要调整三个常量(threshVal
,minArea
,maxArea
)的值,以便在所有样本上获得更好的结果。