原理
- 什么是模板匹配?
你有一副原图像,还有一小块模板(很小的图像,有可能来源于原图像),通过模板找出原图中和模板相似的位置。 - 如何实现匹配?
原图(I):我们需要在上面找到和模板匹配的图像
模板(T):一小块图像,是我们需要在原图中找到和它相似的区域位置的图像
方法:一直用模板在原图上进行移动,从左到右,从上到下,每移动一个像素,便去在模板区域内计算 “一种度量(度量)”,然后将"度量"结果存到Mat 对象中,最大值(或者最小值,根据计算方法不同)的位置,就是原图中最佳的匹配位置
代码
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
const char* src_window = "src";
const char* image_window = "ResultInSrc";
const char* pathch_window = "template";
const char* result_wimdow = "ResulIntMatch";
Mat image,temp;
int method = 0;
#define MAX_METHOD 5
void Mathching(int, void*);
int main(void)
{
image = imread("../res/image.jpg",cv::IMREAD_COLOR);
temp = imread("../res/template.jpg",IMREAD_COLOR);
if(image.empty() || temp.empty())
{
cout << "can't load the image" << endl;
}
namedWindow(src_window,cv::WINDOW_AUTOSIZE);
namedWindow(pathch_window,WINDOW_AUTOSIZE);
const char* Trackbar_Label = "method: \n 0:SQDIFF \n 1:SQDIFF NORMED \n 2: TM CCORR \n 3: TM CCORR NORMED \n 4: TM COEFF \n 5: TM COEFF NORMED";
createTrackbar(Trackbar_Label, src_window, &method, MAX_METHOD, Mathching); //选择匹配方法
imshow(pathch_window, temp);
imshow(src_window,image);
Mathching(0,0);
waitKey();
return 0;
};
void Mathching(int, void*)
{
int result_cols = image.cols-temp.cols+1;
int result_rows = image.rows-temp.rows+1;
Mat image_display ; //copy原图,用来显示匹配结果
image.copyTo(image_display);
Mat result;
result.create(result_rows,result_cols,CV_32FC1);
cv::matchTemplate(image, temp, result,method); //进行匹配
normalize(result,result,0,1,NORM_MINMAX, -1,Mat()); //归一化
double minValue, maxValue; Point minLoc, maxLoc; Point matchLoc;
cv::minMaxLoc(result,&minValue, &maxValue, &minLoc, &maxLoc,Mat()); //在结果中找最大和最小值 和他们位置
if(method == cv::TM_SQDIFF || method == cv::TM_CCORR_NORMED) //这两种匹配方法,最小值才是最佳匹配
matchLoc = minLoc;
else
matchLoc = maxLoc;
//将匹配在原图和结果中画出来
cv::rectangle(image_display, matchLoc,Point(matchLoc.x+temp.cols, matchLoc.y+temp.rows),Scalar::all(0),2,8,0);
cv::rectangle(result, matchLoc,Point(matchLoc.x+temp.cols, matchLoc.y+temp.rows),Scalar::all(0),2,8,0);
imshow(image_window, image_display);
imshow(result_wimdow,result);
}
结果:
只有在第5种方法的时候才得到很好的匹配,其他都效果不好

OpenCV API
-
模板匹配,返回匹配结果(存在result中)
void cv::matchTemplate
(
InputArray image, // 输入图像,必须是8位或者32float型
InputArray templ, //模板,不能大于输入图像,且和它具有相同的数据类型
OutputArray result, // 输出结果,必须是单通道的32位float类型,输入:W × \times ×H,模板:w × \times ×h,结果: W − w + 1 , H − h + 1 W-w+1,H-h+1 W−w+1,H−h+1,每个点代表的不是模板在原图的中心,而是左上
int method, // 使用匹配的方法,见下面
InputArray mask = noArray()
)

-
在一副图像中找全局最大和最小值和他们的位置
void cv::minMaxLoc
(
InputArray src, // 输入的单通道的图像
double * minVal, // 指向最小值,如果不需要填NULL
double * maxVal = 0, //指向最大值如,果不需要填NULL
Point * minLoc = 0, //指向最小值的位置,如果不需要填NULL
Point * maxLoc = 0, //指向最大值的位置,如果不需要填NULL
InputArray mask = noArray() //掩膜,用来选择子区域
)
本文介绍了模板匹配的基本原理,即通过在原图像上滑动模板并计算匹配度来寻找相似区域。讨论了如何实现匹配,并指出在使用OpenCV的matchTemplate函数时,第五种方法提供了最佳匹配效果。同时,提到了利用minMaxLoc函数来寻找全局最大匹配位置。
667

被折叠的 条评论
为什么被折叠?



