模板匹配matchTemplate()
matchTemplate()
是OpenCV中用于模板匹配的函数之一。它的主要作用是在一幅图像中搜索模板图像的位置,即找到模板在图像中的匹配位置。
函数原型如下:
void cv::matchTemplate(
InputArray image,
InputArray templ,
OutputArray result,
int method
);
其中:
image
是源图像,你要在这幅图像中搜索模板。templ
是模板图像,你要搜索的目标。result
是输出参数,用于存储匹配结果。method
是匹配方法,指定匹配时要使用的算法,可以是以下之一:TM_SQDIFF
: 平方差匹配,最匹配的位置是结果最小的位置。TM_SQDIFF_NORMED
: 标准化平方差匹配,最匹配的位置是结果最小的位置。TM_CCORR
: 相关性匹配,最匹配的位置是结果最大的位置。TM_CCORR_NORMED
: 标准化相关性匹配,最匹配的位置是结果最大的位置。TM_CCOEFF
: 系数匹配,最匹配的位置是结果最大的位置。TM_CCOEFF_NORMED
: 标准化系数匹配,最匹配的位置是结果最大的位置。
使用 matchTemplate()
后,result
图像中会包含匹配结果。你可以通过在 result
图像中找到最小(TM_SQDIFF
和 TM_SQDIFF_NORMED
)或最大(其他方法)的值的位置来定位匹配的区域。
这个函数对于目标检测、物体跟踪和模式识别等应用非常有用。
图像模板匹配
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
// 定义窗口标题
#define WINDOW_NAME1 "Original Image"
#define WINDOW_NAME2 "Matching Result"
// 全局变量
Mat g_srcImage;
Mat g_templateImage;
Mat g_resultImage;
int g_nMatchMethod;
int g_nMaxTrackbarNum = 5;
// 回调函数声明
void onMatching(int, void*);
int main()
{
// 载入原始图像和模板图像
g_srcImage = imread("1.jpg");
g_templateImage = imread("1112.jpg");
// 创建窗口
namedWindow(WINDOW_NAME1, CV_WINDOW_AUTOSIZE);
namedWindow(WINDOW_NAME2, CV_WINDOW_AUTOSIZE);
// 创建滑动条并进行一次初始化
createTrackbar("Method", WINDOW_NAME1, &g_nMatchMethod, g_nMaxTrackbarNum, onMatching);
onMatching(0, 0);
waitKey(0);
return 0;
}
void onMatching(int, void*)
{
// 给局部变量初始化
Mat srcImage;
g_srcImage.copyTo(srcImage);
// 初始化结果输出矩阵
int resultImageCols = g_srcImage.cols - g_templateImage.cols + 1;
int resultImageRows = g_srcImage.rows - g_templateImage.rows + 1;
g_resultImage.create(resultImageRows, resultImageCols, CV_32FC1);
// 执行模板匹配
matchTemplate(g_srcImage, g_templateImage, g_resultImage, g_nMatchMethod);
normalize(g_resultImage, g_resultImage, 0, 1, NORM_MINMAX, -1, Mat());
// 定位最佳匹配位置
double minValue, maxValue;
Point minLocation, maxLocation, matchLocation;
minMaxLoc(g_resultImage, &minValue, &maxValue, &minLocation, &maxLocation, Mat());
// 根据不同的匹配方法,计算匹配位置
if (g_nMatchMethod == TM_SQDIFF || g_nMatchMethod == TM_SQDIFF_NORMED)
{
matchLocation = minLocation;
}
else
{
matchLocation = maxLocation;
}
// 在原始图像上绘制匹配位置的矩形
rectangle(srcImage, matchLocation, Point(matchLocation.x + g_templateImage.cols, matchLocation.y + g_templateImage.rows), Scalar(0, 0, 255), 2, 8, 0);
// 在结果图像上绘制匹配位置的矩形
rectangle(g_resultImage, matchLocation, Point(matchLocation.x + g_templateImage.cols, matchLocation.y + g_templateImage.rows), Scalar(0, 0, 255), 2, 8, 0);
// 显示图像
imshow(WINDOW_NAME1, srcImage);
imshow(WINDOW_NAME2, g_resultImage);
}
调用本地相机进行模版匹配
#include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
int main()
{
VideoCapture cap(0); // 打开默认相机,0代表第一个摄像头
if (!cap.isOpened())
{
std::cout << "Could not open the camera!" << std::endl;
return -1;
}
Mat templateImage = imread("122.jpg", IMREAD_COLOR); // 读取要匹配的模板图像
if (templateImage.empty())
{
std::cout << "Could not open or find the template image!" << std::endl;
return -1;
}
int templateWidth = templateImage.cols;
int templateHeight = templateImage.rows;
while (true)
{
Mat frame;
cap >> frame; // 从摄像头捕获一帧
Mat result;
matchTemplate(frame, templateImage, result, TM_CCOEFF_NORMED);
double minVal, maxVal;
Point minLoc, maxLoc;
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);
Point matchLoc = maxLoc;
rectangle(frame, matchLoc, Point(matchLoc.x + templateWidth, matchLoc.y + templateHeight), Scalar(0, 0, 255), 2);
imshow("Camera", frame);
char key = waitKey(30);
if (key == 27) // 按ESC键退出
break;
}
cap.release();
destroyAllWindows();
return 0;
}