模板匹配是最简单易懂的图像匹配方法,可用于目标定位和分割,但由于其属于窗口滑动,基于灰度值统计的匹配,因此比较耗时。
高斯金字塔模型可以将高分辨率的图像通过不断下采样,获取低分辨率的图像,构成图像金字塔。通过对低分辨率的图像匹配,可以减少时间,最后对坐标反推可获取原图目标的坐标。
奉上网上下载代码
代码:
//-----------------------------------【头文件包含部分】---------------------------------------
// 描述:包含程序所依赖的头文件
//----------------------------------------------------------------------------------------------
#include
//#include
//#include "opencv2/highgui/highgui.hpp"
#include
//#include
//#include
//#include
#include
//全局变量
//-----------------------------------【命名空间声明部分】---------------------------------------
// 描述:包含程序所使用的命名空间
//-----------------------------------------------------------------------------------------------
using namespace cv;
using namespace std;
//全局变量
/*
Mat srcImage;//源图
Mat tmpImage;//源模板
*/
Mat dstImage1;//目标图1
Mat dstImage2;//目标图2
Mat resultImg; //匹配结果图像
Mat srcImg; //原始图像
Mat templImg; //模板图像
Mat srcImage1;//源图临时变量
Mat tmpImage1;//模板图临时变量
const char* imageWindow = "Source Image"; //原始图像显示窗口
const char* resultWindow = "Result Window"; //匹配结果图像显示窗口
int matchMethod; //匹配方法index
int maxTrackbar = 5; //滑动条范围(与匹配方法个数对应)
/// 函数声明 ///
void MatchingMethod(int, void*); //匹配函数
//-----------------------------------【main( )函数】--------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始
//-----------------------------------------------------------------------------------------------
int main()
{
double i, k, r;
// 加载原始图像和模板图像
srcImg = imread("yuan.png", 1);
templImg = imread("muban.png", 1);
srcImage1 = srcImg;
tmpImage1 = templImg;
// 创建显示窗口
namedWindow(imageWindow, WINDOW_AUTOSIZE);
namedWindow(resultWindow, WINDOW_AUTOSIZE);
// 创建滑动条
char* trackbarLabel =
"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";
//参数:滑动条名称 显示窗口名称 匹配方法index 滑动条范围 回调函数
createTrackbar(trackbarLabel, imageWindow, &matchMethod, maxTrackbar, MatchingMethod);
i = getTickCount();
//进行向下取样操作
pyrDown(srcImage1, dstImage1, Size(srcImage1.cols / 2, srcImage1.rows / 2));
pyrDown(tmpImage1, dstImage2, Size(tmpImage1.cols / 2, tmpImage1.rows / 2));
MatchingMethod(0, 0);
k = getTickCount();
r = k - i;
// cout << r << endl;
imshow("templImg", templImg);
waitKey(0);
return 0;
}
/// 函数定义 ///
void MatchingMethod(int, void*) //匹配函数
{
Mat imageROI;
// 深拷贝用于显示
Mat displayImg;
dstImage1.copyTo(displayImg);
// 创建匹配结果图像,为每个模板位置存储匹配结果
// 匹配结果图像大小为:(W-w+1)*(H-h+1)
int result_cols = dstImage1.cols - dstImage2.cols + 1;
int result_rows = dstImage1.rows - dstImage2.rows + 1;
resultImg.create(result_cols, result_rows, CV_32FC1);
// 进行匹配并归一化
matchTemplate(dstImage1, dstImage2, resultImg, matchMethod);
normalize(resultImg, resultImg, 0, 1, NORM_MINMAX, -1, Mat());
// 使用minMaxLoc找出最佳匹配
double minVal, maxVal;
Point minLoc, maxLoc, matchLoc;
minMaxLoc(resultImg, &minVal, &maxVal, &minLoc, &maxLoc, Mat());
// 对于CV_TM_SQDIFF和 CV_TM_SQDIFF_NORMED这两种方法,最小值为最佳匹配;对于别的方法最大值为最佳匹配
if (matchMethod == TM_SQDIFF || matchMethod == TM_SQDIFF_NORMED)
{
matchLoc = minLoc;
}
else
{
matchLoc = maxLoc;
}
cout << matchLoc.x << endl;
cout << matchLoc.y << endl;
imageROI = srcImage1(Rect(2 * matchLoc.x - 5, 2 * matchLoc.y - 5, tmpImage1.cols + 5, tmpImage1.rows + 5));
// 在原始图像和匹配结果图像中以最佳匹配点为左上角标出最佳匹配框
rectangle(displayImg, matchLoc, Point(matchLoc.x + dstImage2.cols, matchLoc.y + dstImage2.rows), Scalar::all(0), 2, 8, 0);
rectangle(resultImg, matchLoc, Point(matchLoc.x + dstImage2.cols, matchLoc.y + dstImage2.rows), Scalar::all(0), 2, 8, 0);
// rectangle(srcImage1, 2*matchLoc, Point(2*matchLoc.x + tmpImage1.cols, 2*matchLoc.y + tmpImage1.rows), Scalar::all(0), 2, 8, 0);
matchTemplate(imageROI, tmpImage1, resultImg, matchMethod);
// resize(resultImg, resultImg, Size(60, 20));
imshow(imageWindow, displayImg);
// imshow(resultWindow, resultImg);
imshow("【源图】", srcImg);
return;
}