我正在做一个项目,我必须检查药品泡罩包装中的药片是否丢失。

我正在尝试使用opencv的matchTemplate函数。让我显示代码,然后显示一些结果。

int match(string filename, string templatename)
{
    Mat ref = cv::imread(filename + ".jpg");
    Mat tpl = cv::imread(templatename + ".jpg");
    if (ref.empty() || tpl.empty())
    {
        cout << "Error reading file(s)!" << endl;
        return -1;
    }

    imshow("file", ref);
    imshow("template", tpl);

    Mat res_32f(ref.rows - tpl.rows + 1, ref.cols - tpl.cols + 1, CV_32FC1);
    matchTemplate(ref, tpl, res_32f, CV_TM_CCOEFF_NORMED);

    Mat res;
    res_32f.convertTo(res, CV_8U, 255.0);
    imshow("result", res);

    int size = ((tpl.cols + tpl.rows) / 4) * 2 + 1; //force size to be odd
    adaptiveThreshold(res, res, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, size, -128);
    imshow("result_thresh", res);

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

        if (maxval >= threshold)
        {
            rectangle(ref, maxloc, Point(maxloc.x + tpl.cols, maxloc.y + tpl.rows), CV_RGB(0,255,0), 2);
            floodFill(res, maxloc, 0); //mark drawn blob
        }
        else
            break;
    }

    imshow("final", ref);
    waitKey(0);

    return 0;
}

这是一些图片。

好的泡罩包装的“样本”图像:

从“样本”图像裁剪的模板:

结果与“样本”图像:

检测到此包中缺少平板电脑:

但是这里有问题:



我目前不知道为什么会这样。任何建议和/或帮助,不胜感激。

我遵循和修改的原始代码在这里:http://opencv-code.com/quick-tips/how-to-handle-template-matching-with-multiple-occurences/

最佳答案

我为自己的问题找到了解决方案。我只需要在图像和模板上都应用Canny边缘检测器,然后再将它们扔到matchTemplate函数即可。完整的工作代码:

int match(string filename, string templatename)
{
    Mat ref = cv::imread(filename + ".jpg");
    Mat tpl = cv::imread(templatename + ".jpg");
    if(ref.empty() || tpl.empty())
    {
        cout << "Error reading file(s)!" << endl;
        return -1;
    }

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

    const int low_canny = 110;
    Canny(gref, gref, low_canny, low_canny*3);
    Canny(gtpl, gtpl, low_canny, low_canny*3);

    imshow("file", gref);
    imshow("template", gtpl);

    Mat res_32f(ref.rows - tpl.rows + 1, ref.cols - tpl.cols + 1, CV_32FC1);
    matchTemplate(gref, gtpl, res_32f, CV_TM_CCOEFF_NORMED);

    Mat res;
    res_32f.convertTo(res, CV_8U, 255.0);
    imshow("result", res);

    int size = ((tpl.cols + tpl.rows) / 4) * 2 + 1; //force size to be odd
    adaptiveThreshold(res, res, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, size, -64);
    imshow("result_thresh", res);

    while(1)
    {
        double minval, maxval;
        Point minloc, maxloc;
        minMaxLoc(res, &minval, &maxval, &minloc, &maxloc);

        if(maxval > 0)
        {
            rectangle(ref, maxloc, Point(maxloc.x + tpl.cols, maxloc.y + tpl.rows), Scalar(0,255,0), 2);
            floodFill(res, maxloc, 0); //mark drawn blob
        }
        else
            break;
    }

    imshow("final", ref);
    waitKey(0);

    return 0;
}

任何改进的建议均表示赞赏。我非常担心代码的性能和健壮性,因此我正在寻找所有想法。

现在有两件事让我感到不安:较低的Canny阈值和adaptiveThreshold函数的负常数。

编辑:这是结果,如您所问:)

模板:

测试图片,缺少2个平板电脑:

模板和测试图像的Canny结果:



matchTemplate结果(转换为CV_8U):

在AdaptiveThreshold之后:

最后结果:

10-08 08:13