使用OpenCV进行模板匹配(原图-模板图)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用OpenCV进行模板匹配(原图-模板图)相关的知识,希望对你有一定的参考价值。
描述:采集被匹配原图,获取原图中的一块区域作为模板,用模板进行对不断采集的图像进行匹配;
问题:1、使用哪些算法 匹配的结果好;
2、算法的过程是什么?
3、能够对不同情况下的模板匹配都比较有效;
原图->图像处理(算法?),
模板->图像处理(算法?),
模板匹配?,
得到匹配结果坐标。
但是这种方法稍微有一点旋转和光照变化结果就会很差。
为了改进这个,有了SAD算法。
然后SAD相似的SSD。
再然后是计算区域互相关性的NCC算法。
以上三种算法中,SAD算法最简单,因此当模板大小确定后,SAD算法的速度最快。NCC算法与SAD算法相比要复杂得多。
至于算法的过程,这三个算法都是很好理解的算法,我觉得还是自学比较好。追问
恩 谢谢啊~~~我使用的是NCC算法, 但是当原图中有旋转时,匹配不到。有什么好的解决方法吗?
追答旋转的话匹配不到太正常了,因为NCC就不是为旋转设计的啊。
所以现在也有用旋转不变性做的。
比如SURF来匹配,虽然已经是关键点匹配的快速算法了,但是,但是,还是很慢。
恩恩呢~~太感谢了啊!我查查surf算法。。。在匹配前,对原图和模板图做怎样的处理,匹配的效果会更好呢?
本回答被提问者采纳使用 Open CV C++ 进行模板匹配
【中文标题】使用 Open CV C++ 进行模板匹配【英文标题】:Template Matching Using Open CV C++ 【发布时间】:2015-04-14 03:19:19 【问题描述】:我正在尝试在货架图图像中执行模板匹配, 这是我的图片- 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 个匹配项,它只给出一个。
我怎样才能找到这两个图像,因为它们是相同的。
【问题讨论】:
【参考方案1】:您的问题的解决方案可以在以下链接中找到:
Using OpenCV MatchTemplate On Blister Pack
【讨论】:
以上是关于使用OpenCV进行模板匹配(原图-模板图)的主要内容,如果未能解决你的问题,请参考以下文章