1. 模板匹配介绍
- 模板匹配就是在整个图像区域发现与给定子图像匹配的小块区域。所以模板匹配首先需要一个模板图像T(给定的子图像),另外需要一个待检测的图像-源图像S。
- 工作方法,在带检测图像上,从左到右,从上向下计算模板图像与重叠子图像的匹配度,匹配程度越大,两者相同的可能性越大。
1.1模板匹配的算法介绍
- 0到5分别为:平方差、归一化平方差、相关系数(会出现失真的情况,慎用)、归一化相关系数、互相关、归一化互相关。
- 算法对应的公式:
2. 相关API
2.1模板匹配matchTemplate()
matchTemplate(
InputArray image,// 源图像,必须是8-bit或者32-bit浮点数图像
InputArray templ,// 模板图像,类型与输入图像一致
OutputArray result,// 输出结果,必须是单通道32位浮点数,假设源图像WxH,模板图像wxh,则结果必须为W-w+1, H-h+1的大小。
int method,//使用的匹配方法,即上述六种之一,因为归一化的结果在0到1之间,便于设置阈值,所以推荐使用归一化的方法。
InputArray mask=noArray()//(optional)
)
2.2在矩阵中需找全局的最大最小数minMaxLoc()
void minMaxLoc(
InputArray src,//输入的单通道矩阵。
double* minVal, //指向返回的最小值的指针。NULL为不要求。
double* maxVal=0,//指向返回的最大值的指针。NULL为不要求。
Point* minLoc=0,//指向返回最小值的位置(2d情况下),NULL为不要求
Point* maxLoc=0, //指向返回最大值的位置(2d情况下),NULL为不要求
InputArray mask=noArray()//用于指定下级矩阵的操作掩码。
)
- 该函数不适用于多通道矩阵,如果你需要寻找所以通道的全局最大最小值,可首先使用Mat::reshape()重新诠释为但通道矩阵。如果你要检测特殊的同道可使用一下函数 ImageCOT(),minChannels(),spilt().
- 特别注意,返回的极值为double型。
3. 例程
#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
using namespace cv;
using namespace std;
int main() {
//输入模板图像temp和待检测图像src并显示
Mat src,temp, dst;
src = imread("D:/resource/images/face.jpg");
temp = imread("D:/resource/images/temp.jpg");
if (src.empty()) printf("src couldn't be loaded...");
if (temp.empty()) printf("temp couldn't be loaded...");
imshow("input", src);
namedWindow("temp", WINDOW_NORMAL);
imshow("temp", temp);
//模板匹配
int width = src.cols - temp.cols + 1;
int height = src.rows - temp.rows + 1;
Mat result(Size(width, height), CV_32FC1);
int method = TM_SQDIFF_NORMED;
matchTemplate(src, temp, result, method, Mat());
//在待测图像中框出模板
Point MinPoint;
Point MaxPoint;
Point FinalPoint;
double min, max;
minMaxLoc(result, &min, &max, &MinPoint, &MaxPoint);//获取result图像中像素的最大最小值,及所在位置
if (method == TM_SQDIFF || method == TM_SQDIFF_NORMED) FinalPoint = MinPoint;
else FinalPoint = MaxPoint;//如果采用平方差或平方差归一化的方法,像素最小值点为矩形框的左上角;否则像素最大值点为矩形框的左上角
rectangle(src, Rect(FinalPoint, Size(temp.cols, temp.rows)), Scalar(0, 0, 255), 2, LINE_8);
imshow("output", src);
waitKey(0);
return 0;
}