模板(TTemplate Match)匹配简介
- 模板匹配就是在整个图像区域发现与给定子图像匹配的小块区域
- 所以模板匹配首先需要一个模板图像T(给定的子图像)
- 另外需要一个待检测的图像-原图像S
- 工作方法,在待检测图像上,从左到右,从上到下计算模板图像与重叠子图像的匹配度,匹配度越大,两者相同的可能性越大
- opencv提供了六种常见的匹配算法:
- 计算平方不同,越小越好
- 计算相关性,越大越好
- 计算相关系数,越大越好
- 计算归一化平方不同,越小越好
- 计算归一化相关性,越大越好
- 计算归一化相关系数,越大越好
函数API
寻找最值:minMaxLoc()函数
功能:查找全局最小和最大数组元素并返回它们的值和它们的位置。
void minMaxLoc(
InputArray src,
CV_OUT double* minVal,
CV_OUT double* maxVal=0,
CV_OUT Point* minLoc=0,
CV_OUT Point* maxLoc=0,
InputArray mask=noArray()
);
参数介绍
- 参数1:InputArray类型的src,输入单通道数组(图像)。
- 参数2:double类型的minVal*,返回最小值的指针。若无须返回,此值置为NULL。
- 参数3:double类型的maxVal*,返回最大值的指针。若无须返回,此值置为NULL。
- 参数4:Point类型的minLoc*,返回最小位置的指针(二维情况下)。- 若无须返回,此值置为NULL。
- 参数5:Point类型的maxLoc*,返回最大位置的指针(二维情况下)。若无须返回,此值置为NULL。
- 参数6:InputArray类型的mask,用于选择子阵列的可选掩膜。
图像匹配函数API
void cv::matchTemplate(
InputArray image, // 用于搜索的输入图像, 8U 或 32F, 大小 W-H
InputArray templ, // 用于匹配的模板,和image类型相同, 大小 w-h
OutputArray result, // 匹配结果图像, 类型 32F, 大小 (W-w+1)-(H-h+1)
int method // 用于比较的方法
);
参数介绍
- 第一个参数是源图像
- 第二个参数是模板图像
- 第三个参数是匹配的结果图像,输出结果,必须是单通道32位浮点数,假设源图像WxH,模板图像wxh,则结果必须为W-w+1, H-h+1的大小。
- 第四个参数是用于指定比较的方法六种:
名称 | 宏 |
---|---|
平方不同 | TM_SQDIFF=0 |
归一化平方不同 | TM_SQDIFF_NORMED=1 |
相关性 | TM_CCORR=2 |
归一化相关性 | TM_CCORR_NORMED=3 |
相关系数 | TM_CCOEFF=4 |
归一化相关系数 | TM_CCOEFF_NORMED=5 |
## 代码演示
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
#define Pic_Path "/home/image/Pictures/my_picture/"
#define Pic_Name "model_1.jpeg"
#define Pic_Name1 "model_1_mouse.jpeg"
int type=0;
cv::Mat src,sub;
void Match_Demo(int ,void *);
int main(void)
{
string pic = string(Pic_Path) + string(Pic_Name);
cout << pic << endl;
string pic1 = string(Pic_Path) + string(Pic_Name1);
cout << pic1 << endl;
//读取原始图片
src = cv::imread(pic.c_str());
sub = cv::imread(pic1.c_str());
//判断图像是否存在
if( src.empty() || sub.empty())
{
cout << "图片不存在" << endl;
return -1;
}
//显示原始图像也就是检测图像
cv::namedWindow("原始图片",cv::WINDOW_AUTOSIZE);
cv::imshow("原始图片",src);
//显示模板图像
cv::namedWindow("子图片",cv::WINDOW_AUTOSIZE);
cv::imshow("子图片",sub);
//创建滑动条用来切换匹配方法
cv::createTrackbar("方法","原始图片",&type,5,Match_Demo);
Match_Demo(0,0); //调用回调函数一次 否则程序运行不调整滑动条匹配图片将不显示
cv::waitKey(0);
cv::destroyAllWindows();
}
void Match_Demo(int ,void *)
{
int width = src.cols - sub.cols + 1;
int height= src.rows - sub.rows + 1;
//目标图像大小
Mat match_result(width,height,CV_32FC1);
//图像匹配
cv::matchTemplate(src,sub,match_result,type);
//得出的匹配图像进行归一化处理
cv::normalize(match_result,match_result,0,1,cv::NORM_MINMAX,-1,Mat());
//查找位置
double min,max;
Point minLoc,maxLoc;
Point tmpLoc;
minMaxLoc(match_result,&min,&max,&minLoc,&maxLoc,Mat());
if(type == TM_SQDIFF || type == TM_SQDIFF_NORMED) //平方不同越小越好
{
tmpLoc = minLoc;
} else //相关因子 相关性 越大越好
{
tmpLoc = maxLoc;
}
Mat result;
//复制原图用来在原图显示检测位置
src.copyTo(result);
//在匹配图上绘制检测位置
cv::rectangle(match_result,Rect(tmpLoc.x,tmpLoc.y,sub.cols,sub.rows),Scalar(0,0,255),2,LINE_8,0);
cv::imshow("匹配结果",match_result);
//在原图上绘制检测位置
cv::rectangle(result,Rect(tmpLoc.x,tmpLoc.y,sub.cols,sub.rows),Scalar(0,0,255),2,LINE_8,0);
cv::imshow("原图匹配结果",result);
return;
}
程序运行结果
待检测图像与模板图像
检测结果