使用OpenCV中的matchTemplate函数实现模板匹配【C++版】

matchTemplate函数原型[0]

void cv::matchTemplate(InputArray 	image,
	InputArray 	templ,
	OutputArray 	result,
	int 	method,
	InputArray 	mask = noArray()
)
参数含义
image正在运行搜索的图像。 它必须是 8 位或 32 位浮点数。
templ搜索到的模板。 它必须不大于源图像并且具有相同的数据类型。
result比较结果图。 它必须是单通道 32 位浮点数。 如果 image 是 W×H 并且 templ 是 w×h ,那么结果是 (W−w+1)×(H−h+1)
method指定比较方法的参数,请参见TemplateMatchModes
mask搜索模板的掩码。 它必须与 templ 具有相同的数据类型和大小。 默认情况下未设置。 目前,仅支持 TM_SQDIFFTM_CCOEFF_NORMED 方法。

enum cv::TemplateMatchModes枚举量[0]

将模板与重叠的图像区域进行比较。
该函数在图像中滑动,使用指定的方法将大小为 w×h 的重叠块与 templ 进行比较,并将比较结果存储在 result 中。 以下是可用比较方法的公式(I 表示图像,T 是模板,R 是结果)。求和是在模板和/或图像块上完成的:x′=0…w−1,y′=0…h−1
函数完成比较后,可以使用 minMaxLoc 函数以全局最小值(使用 TM_SQDIFF 时)或最大值(使用 TM_CCORR 或 TM_CCOEFF 时)找到最佳匹配。 在彩色图像的情况下,分子中的模板总和和分母中的每个总和在所有通道上完成,并且每个通道使用单独的平均值。 即该函数可以获取一个颜色模板和一个彩色图像。 结果仍然是单通道图像,更易于分析。

normalize函数原型[0]

void cv::normalize(InputArray 	src,
	InputOutputArray 	dst,
	double 	alpha = 1,
	double 	beta = 0,
	int 	norm_type = NORM_L2,
	int 	dtype = -1,
	InputArray 	mask = noArray()
)
参数含义
src输入数组
dst与 src 大小相同的输出数组
alpha在范围归一化的情况下,规范值或范围下限。
beta范围归一化情况下的范围上限;它不用于规范标准化。
norm_type归一化类型,见cv::NormTypes
dtype当为负数时,输出数组的类型与 src 相同; 否则,它具有与 src 相同数量的通道和深度 =CV_MAT_DEPTH(dtype)。
mask可选操作掩码

归一化数组的范数或取值范围。

minMaxLoc函数原型[0]

void cv::minMaxLoc(InputArray 	src,
	double* minVal,
	double* maxVal = 0,
	Point* minLoc = 0,
	Point* maxLoc = 0,
	InputArray 	mask = noArray()
)
参数含义
src单通道输入数组
minVal指向返回的最小值的指针; 如果不需要,则使用 NULL。
maxVal指向返回的最大值的指针; 如果不需要,则使用 NULL。
minLoc指向返回的最小位置的指针(在 2D 情况下); 如果不需要,则使用 NULL。
maxLoc指向返回的最大位置的指针(在 2D 情况下); 如果不需要,则使用 NULL。
mask用于选择子数组的可选掩码

在数组中查找全局最小值和最大值。
函数 cv::minMaxLoc 查找最小和最大元素值及其位置。 在整个数组中搜索极值,如果 mask 不是空数组,则在指定的数组区域中搜索。
该功能不适用于多通道阵列。 如果您需要在所有通道中找到最小或最大元素,请先使用 Mat::reshape 将数组重新解释为单通道。 或者,您可以使用 extractImageCOI 或 mixChannels 或 split 提取特定通道。

Mat::create函数原型[0]

void cv::Mat::create(int rows,
	int cols,
	int type
)

这是 Mat 的关键方法之一。 大多数产生数组的新型 OpenCV 函数和方法为每个输出数组调用此方法。

模板匹配例程

参考官方例程:samples/cpp/tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp[0]

#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
	string srcPath = "./lena.jpg";
	string templPath = "./lena-templ.jpg";
	Mat result;
	Mat img = imread(srcPath);
	Mat templ = imread(templPath);

	int resultCols = img.cols - templ.cols + 1; //col = W - w + 1
	int resultRows = img.rows - templ.rows + 1; //row = H - h + 1

	result.create(resultRows, resultCols, CV_32FC1);

	int method = TM_CCORR_NORMED;
	matchTemplate(img, templ, result, method);

	normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat());

	double minVal, maxVal;
	Point minLoc, maxLoc;
	Point matchLoc;

	cout << "result_channel: " << result.channels() << endl;

	minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);

	if (method == TM_SQDIFF || method == TM_SQDIFF_NORMED) {
		matchLoc = minLoc;
	}
	else {
		matchLoc = maxLoc;
	}

	
	rectangle(img, matchLoc, Point(matchLoc.x + templ.cols, matchLoc.y + templ.rows), Scalar(255, 0, 0), 2, 8, 0);

	imshow("match-result", img);

	waitKey(0);
	return 0;
}

比赛结果

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
xiaoxingxing的头像xiaoxingxing管理团队
上一篇 2022年5月8日
下一篇 2022年5月8日

相关推荐