模板匹配:
模板匹配就是在整个图像区域发现与给定子图像匹配的小块区域,所以模板匹配首先需要一个模板图像T(给定的子图像),另外需要一个待检测的图像-源图像s工作方法,在待检测图像上,从左到右,从上往下计算模板图像与重叠子图像的匹配度,匹配度越大两者相同的可能性就越大。
OpenCV中提供了六种常见的匹配算法如下:
- 计算平方不同 , 计算出来的值越小,越相关 TM_SQDIFF= 0
- 计算相关性 , 计算出来的值越大,越相关 TM_CCORR= 2
- 计算相关系数 , 计算出来的值越大,越相关 TM_CCOEFF = 4
- 计算归一化平方不同 , 计算出来的值越接近0,越相关 TM_SQDIFF_NORMED = 1
- 计算归一化相关性, 计算出来的值越接近1,越相关 TM_CCORR_NORMED = 3
- 计算归一化相关系数 , 计算出来的值越接近1,越相关 TM_CCOEFF_NORMED = 5
建议使用归一化的方法
API:
matchTemplate(
InputArray image,// 源图像,必须是8-bit或者32-bit浮点数图像
InputArray templ,// 模板图像,类型与输入图像一致
OutputArray result,// 输出结果,必须是单通道32位浮点数,假设源图像W*H,模板图像w*h, 则结果必须为W-w+1, H-h+1的大小。
int method,// 使用的匹配方法
InputArray mask=noArray()//(optional)
)
代码:
#include <opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
#include <string>
#include<fstream>
using namespace cv;
using namespace std;
Mat src, temp, dst;
int match_method = TM_SQDIFF;
int max_track = 5;
void match(int, void*) {
int width = src.cols - temp.cols + 1;
int height = src.rows - temp.rows + 1;
Mat result(width, height, CV_32FC1);
matchTemplate(src, temp, result, match_method);//模板匹配
normalize(result, result, 0, 1, NORM_MINMAX);//归一化
Point minLoc, maxLoc;
double min, max;
src.copyTo(dst);
minMaxLoc(result, &min, &max, &minLoc, &maxLoc);//寻找result中最大值和最小值以及他们的位置
Point temLoc;
if (match_method == TM_SQDIFF || match_method == TM_SQDIFF_NORMED) {
temLoc = minLoc;
}
else {
temLoc = maxLoc;
}
//绘制矩形
rectangle(dst, Rect(temLoc.x, temLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255));
rectangle(result, Rect(temLoc.x, temLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255));
imshow("result", result);
imshow("matchtemplate", dst);
}
int main() {
src = imread("C:\\Users\\Administrator\\Desktop\\pic\\5.jpg");
temp = imread("C:\\Users\\Administrator\\Desktop\\pic\\8.jpg");
imshow("temp", temp);
match(0, 0);
createTrackbar("match_method:", "result", &match_method, max_track, match);
waitKey(0);
}
结果: