使用 Open CV C++ 进行模板匹配

Template Matching Using Open CV C++

我正在尝试在货架图图像中执行模板匹配, 这是我的图像 - 1 -

2 - 我的模板图片 -

   #include "stdio.h"
#include "opencv2/highgui/highgui.hpp"
#include "iostream"
#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/nonfree/nonfree.hpp"
#include "opencv/cv.h"

using namespace cv;
using namespace std;

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"

/**
 * Function to perform fast template matching with image pyramid
 */

void fastMatchTemplate(cv::Mat& srca,  // The reference image
                       cv::Mat& srcb,  // The template image
                       cv::Mat& dst,   // Template matching result
                       int maxlevel)   // Number of levels
{
    std::vector<cv::Mat> refs, tpls, results;

    // Build Gaussian pyramid
    cv::buildPyramid(srca, refs, maxlevel);
    cv::buildPyramid(srcb, tpls, maxlevel);

    cv::Mat ref, tpl, res;

    // Process each level
    for (int level = maxlevel; level >= 0; level--)
    {
        ref = refs[level];
        tpl = tpls[level];
        res = cv::Mat::zeros(ref.size() + cv::Size(1,1) - tpl.size(), CV_32FC1);

        if (level == maxlevel)
        {
            // On the smallest level, just perform regular template matching
            cv::matchTemplate(ref, tpl, res, CV_TM_CCORR_NORMED);
        }
        else
        {
            // On the next layers, template matching is performed on pre-defined 
            // ROI areas.  We define the ROI using the template matching result 
            // from the previous layer.

            cv::Mat mask;
            cv::pyrUp(results.back(), mask);

            cv::Mat mask8u;
            mask.convertTo(mask8u, CV_8U);

            // Find matches from previous layer
            std::vector<std::vector<cv::Point> > contours;
            cv::findContours(mask8u, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

            // Use the contours to define region of interest and 
            // perform template matching on the areas
            for (int i = 0; i < contours.size(); i++)
            {
                cv::Rect r = cv::boundingRect(contours[i]);
                cv::matchTemplate(
                    ref(r + (tpl.size() - cv::Size(1,1))), 
                    tpl, 
                    res(r), 
                    CV_TM_CCORR_NORMED
                );
            }
        }

        // Only keep good matches
        cv::threshold(res, res, 0.80, 1., CV_THRESH_TOZERO);
        results.push_back(res);
    }

    res.copyTo(dst);
}


int main()
{
        /* string path;
     string path1;
    cout << "Please enter image template: ";
    cin >> path;
    cout << "Please enter image reference: ";
    cin >> path1;*/
    cv::Mat ref = cv::imread("E:\CodeImage\plan1.png");
    cv::Mat tpl = cv::imread("E:\CodeImage\t.png");
    if (ref.empty() || tpl.empty())
        return -1;

    cv::Mat ref_gray, tpl_gray;
    cv::cvtColor(ref, ref_gray, CV_BGR2GRAY);
    cv::cvtColor(tpl, tpl_gray, CV_BGR2GRAY);

    cv::Mat dst;
    fastMatchTemplate(ref_gray, tpl_gray, dst, 2);

    while (true)
    {
        double minval, maxval;
        cv::Point minloc, maxloc;
        cv::minMaxLoc(dst, &minval, &maxval, &minloc, &maxloc);

        if (maxval >= 0.9)
        {
            cv::rectangle(
                ref, maxloc, 
                cv::Point(maxloc.x + tpl.cols, maxloc.y + tpl.rows), 
                CV_RGB(0,255,0), 2
            );
            cv::floodFill(
                dst, maxloc, 
                cv::Scalar(0), 0, 
                cv::Scalar(.1), 
                cv::Scalar(1.)
            );
        }
        else
        {
         cout << "No match found ";
         break;
        }
    }

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

我的结果图片是 -

您可以在生成的图像中看到绿色矩形,但应该有 2 个匹配项,但它只给出了一个。

我怎样才能找到这两张图片,因为两张图片是一样的。

可以在以下Link找到您的问题的解决方案:

Using OpenCV MatchTemplate On Blister Pack