opencv中关于模板匹配的算法:
matchTemplate( const CvArr* image, constCvArr* templ,CvArr* result,int method );
Image 待搜索图像
Templ 模板图像
Result 匹配结果 用来存放通过以下方法计算出滑动窗口与模板的相似值
Method 计算匹配程度的方法 (关于匹配方法,使用不同的方法产生的结果的意义可能不太一样,有些返回的值越大表示匹配程度越好,而有些方法返回的值越小表示匹配程度越好)
关于参数 method:
TM_SQDIFF平方差匹配法:该方法采用平方差来进行匹配;最好的匹配值为0;匹配越差,匹配值越大。
TM_CCORR相关匹配法:该方法采用乘法操作;数值越大表明匹配程度越好。
TM_CCOEFF相关系数匹配法:1表示完美的匹配;-1表示最差的匹配。
TM_SQDIFF_NORMED归一化平方差匹配法
TM_CCORR_NORMED归一化相关匹配法
TM_CCOEFF_NORMED归一化相关系数匹配法
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc.hpp>
#include <math.h>
#include <iostream>
#include <vector>
using namespace std;
using namespace cv;
//计算下一个最小值
Point getNextMinLoc(Mat result, Point minLoc, int maxVaule, int templatW, int templatH)
{
// 先将第一个最小值点附近两倍模板宽度和高度的都设置为最大值防止产生干扰
int startX = minLoc.x - templatW;
int startY = minLoc.y - templatH;
int endX = minLoc.x + templatW;
int endY = minLoc.y + templatH;
if (startX < 0 || startY < 0)
{
startX = 0;
startY = 0;
}
if (endX > result.cols - 1 || endY > result.rows - 1)
{
endX = result.cols - 1;
endY = result.rows - 1;
}
for (int y = startY; y < endY; y++)
for (int x = startX; x < endX; x++)
{
//cvsetReal2D(result, y, x, maxVaule);
result.at<float>(y, x) = maxVaule;
}
double new_minVaule, new_maxValue;
Point new_minLoc, new_maxLoc;
minMaxLoc(result, &new_minVaule, &new_maxValue, &new_minLoc, &new_maxLoc);
return new_minLoc;
}
//模板匹配,多目标
int main()
{
//加载(读取)图片
Mat src = imread("src路径", 0); //待匹配源图片
Mat templat = imread("template路径", 0); //模板图片
Mat result; // 模板匹配结果
//取得源图片和模板图片各自的宽和高
int srcW, srcH, templatW, templatH;
srcW = src.cols;
srcH = src.rows;
templatW = templat.cols;
templatH = templat.rows;
//模板图片不能比源图小,否则无法匹配
if (srcW < templatW || srcH < templatH)
{
cout << "模板不能比原图小" << endl;
return 0;
}
int resultW = srcW - templatW + 1;
int resultH = srcH - templatH + 1;
result.create(resultW, resultH, CV_32FC1); //匹配方法计算的结果最小值为float
//开始模板匹配
matchTemplate(src, templat, result, TM_SQDIFF); //方差最小,匹配最好
normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat());
double minValue, maxValue;
Point minLoc, maxLoc;
minMaxLoc(result, &minValue, &maxValue, &minLoc, &maxLoc, Mat());
rectangle(src, minLoc, Point(minLoc.x + templatW, minLoc.y + templatH), Scalar(255, 0, 0), 2, 8, 0);
//保存结果1
Rect rect(minLoc.x, minLoc.y, templatW, templatH);//1
Mat image_roi = src(rect);
//for (int i = 0; i < 5; i++)
{
//计算下一个最小值
Point new_minLoc;
new_minLoc = getNextMinLoc(result, minLoc, maxValue, templatW, templatH);
rectangle(src, new_minLoc, Point(new_minLoc.x + templatW, new_minLoc.y + templatH), Scalar(255, 0, 0), 2, 8, 0);
//保存结果2
Rect rect2(new_minLoc.x, new_minLoc.y, templatW, templatH);//2
image_roi = src(rect2);
//再计算下一个最小值
new_minLoc = getNextMinLoc(result, new_minLoc, maxValue, templatW, templatH);
rectangle(src, new_minLoc, Point(new_minLoc.x + templatW, new_minLoc.y + templatH), Scalar(255, 0, 0), 2, 8, 0);
//保存结果3
Rect rect3(new_minLoc.x, new_minLoc.y, templatW, templatH);//3
image_roi = src(rect3);
}
imshow("匹配结果", src);//显示匹配结果(带匹配标识的源图)
imshow("模板", templat);//显示模板
waitKey(0);//鼠标按下,退出并释放资源
return 0;
}