OpenCV:多线程加速的多尺度模板匹配

OpenCV中的模板匹配 matchTemplate 一直被诟病,原因是不能多尺度识别且不能旋转识别,后者比较复杂,这里只讨论前者。网上多数示例都是从一张图上截取一个目标,然后进行匹配识别,效果很好但明显没有实用性。其实通过设置“尺度池” Scaling Pool可以很好的解决这个问题,用尺度不一的模板进行匹配不就可以了吗?再以多线程加速,各尺度独立匹配,最后取最佳结果,这就是多尺度的思路。
OpenCV:多线程加速的多尺度模板匹配_第1张图片
另外,基于特征(SIFT/SURF等)的目标匹配则不需要考虑尺度和角度问题,本文参考 holybin大神的博客 进行了代码移植,识别结果在后面一并展示。


本文环境:Win10 + OpenCV4.1 + Contrib4.1 + VS2019


直接上代码:(匹配的结果评价指标有很多,这里选的是TM_CCOEFF_NORMED

void TemplateMatching(cv::Mat& src, cv::Mat& tmpl) {
    vector<double> scales = { 0.5, 0.75, 1.25, 1.5 };
    vector<std::future<Result>> results(scales.size());
    for (int i = 0; i < scales.size(); ++i) {
        results[i] = std::async(launch::async, [this, &src, &tmpl, scales, i]() -> Result
            {
                Mat t;   
                Size2d size(tmpl.cols * scales[i], tmpl.rows * scales[i]);
                resize(tmpl, t, size);
                Mat dst(src.size(), src.type());
                matchTemplate(src, t, dst, TM_CCOEFF_NORMED);
                cv::Point minPoint, maxPoint, matchLoc;
                double minVal(-1), maxVal(-1), score(-1);
                cv::minMaxLoc(dst, &minVal, &maxVal, &minPoint, &maxPoint);
                double weight = scales[i] < 1. ? scales[i] : 1. / scales[i];
                score = maxVal * weight;
                matchLoc = maxPoint;
                return Result{ score , Rect(matchLoc.x, matchLoc.y,t.cols,t.rows) };
            });
    }

    Mat processImg = src.clone();
    Result maxRes;
    cv::RNG rng(time(0));
    for (int i = 0; i < scales.size(); ++i) {
        results[i].wait();
        Result res = results[i].get();
        Scalar color(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
        cv::putText(processImg, to_string(res.score), Point(res.bbox.x, res.bbox.y), 0, 1, color, 2);
        cv::rectangle(processImg, res.bbox, color, 2, 8);
        if (res.score > maxRes.score) {
            maxRes = res;
        }
    }
    cv::imshow("Template Matching Process", processImg);

    Mat img = src.clone();
    cv::putText(img, to_string(maxRes.score), Point(maxRes.bbox.x, maxRes.bbox.y), 0, 1, 255, 2);
    cv::rectangle(img, maxRes.bbox, Scalar(0, 255, 0), 2, 8);
    cv::imshow("Template Matching", img);
    cv::waitKey(1);
}

识别结果:
OpenCV:多线程加速的多尺度模板匹配_第2张图片

整个工程代码已经上传,包括两种识别方法:多线程加速的多尺度模板匹配SURF特征匹配

你可能感兴趣的:(数字图像处理,opencv,多尺度,模板匹配,多线程)