cv模板匹配

1、形状检测

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

using namespace std;
using namespace cv;

/*
 contourArea() 计算整个或部分轮廓的面积
*/

Mat imgGray, imgBlur, imgCanny, imgDil, imgErode;
void getContours(Mat imgDil, Mat img)
{
	//里面是一些向量  点
	//{ {},
	//	{}, 
	//	{}}
	vector<vector<Point>> contours;

	//四个整数值   Vec4i是Vec<int,4>的别名,定义了一个“向量内每一个元素包含了4个int型变量”的向量。
	vector<Vec4i>hierarchy;

	//findContours :https://blog.csdn.net/dcrmg/article/details/51987348
	findContours(imgDil, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

	//画轮廓  -1  绘制所有  2---厚度
	//drawContours(img, contours, -1, Scalar(255, 241, 29), 3);

	//过滤

	vector<vector<Point>> conPoly(contours.size());
	vector<Rect>boundRect(contours.size());
	string objectType;
	//首先遍历所有轮廓
	for (int i = 0; i < contours.size(); i++)
	{
		//计算整个或部分轮廓的面积
		int  area = contourArea(contours[i]);
		cout << area << endl;

		if (area > 1000)
		{
			/**
			 * @brief 计算轮廓的周长.
			 * 
			 * \param contours 表示图像的轮廓
			 * \param true  封闭的
			 */
			float peri = arcLength(contours[i], true);
	
			//找到角点  一个连续光滑曲线折线化,对图像轮廓点进行多边形拟合
			approxPolyDP(contours[i], conPoly[i], 0.02 * peri, true);


			drawContours(img, conPoly, i, Scalar(255, 21, 250), 2);
			cout << conPoly[i].size() << endl;

			//边界框
			boundRect[i] = boundingRect(conPoly[i]);
			//rectangle(img, boundRect[i].tl(), boundRect[i].br(), Scalar(241, 130, 200), 3);

			int objCol = (int)conPoly[i].size();
			if (objCol == 3) { objectType = "Triangle"; }
			if (objCol == 4) {
				float aspRatio = (float)boundRect[i].width / (float)boundRect[i].height;
				if (aspRatio >= 0.95 && aspRatio <= 1.05)
					objectType = "Square";
				else

					objectType = "Rect";
			}
			if (objCol > 4) { objectType = "Circle"; }
			putText(img, objectType, { boundRect[i].x + 20,boundRect[i].y + 10 }, FONT_HERSHEY_DUPLEX, 0.75, Scalar(219, 219, 200));

		}
	}
}

/   Color Detection  ///
void main()
{
	string path = "Resources/shapes.png";

	Mat img = imread(path);
	if (img.empty())
	{
		cout << "找不到相关图像,检查路径" << endl;
		return ;
	}
	//预处理
	cvtColor(img, imgGray, COLOR_BGR2GRAY);
	GaussianBlur(imgGray, imgBlur, Size(3, 3), 3, 0);
	Canny(imgBlur, imgCanny, 25, 75);
	Mat Kernel = getStructuringElement(MORPH_RECT, Size(5, 5));
	dilate(imgCanny, imgDil, Kernel);

	//获取轮廓
	getContours(imgDil, img);

	imshow("Image", img);
	//imshow("Image Gray", imgGray);
	//imshow("Image Blur", imgBlur);
	//imshow("Image Canny", imgCanny);
	//imshow("Image Dil", imgDil);
	//imshow("Image Dil", imgDil);
	waitKey(0);

}


效果图:
在这里插入图片描述

1、灰度匹配

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

using namespace std;
using namespace cv;
/* 基于灰度匹配的程序实现——使用滑条选择 method */
int match_method2 = 1;
int max_Trackbar = 5;
const char* match_method = "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";
void MatchingMethod(int, void*);
class Histogram_Matching
{
public:
	Histogram_Matching();
	~Histogram_Matching();

	void ImgMatch2();/*基于滑动条进行多种灰度方法匹配*/

	void Histogram_Matching_Demo();/* 基于灰度匹配的程序实现 */
	void Histogram_Matching_Template_coder();/* 基于灰度匹配的程序提炼模板 */
private:

};

Histogram_Matching::Histogram_Matching()
{
}

Histogram_Matching::~Histogram_Matching()
{
}

Mat resize_srcImg(cv::Mat inputImg, cv::Mat outputImg)
{
	int width = inputImg.cols;//图像宽度  
	int height = inputImg.rows;//图像高度
	if (width > 1920 || height > 1080)
	{
		float factor = min((float)1920 / width, (float)1080 / height);
		resize(inputImg, outputImg, Size(factor * width, factor * height));
		width *= factor;
		height *= factor;
	}
	return outputImg;
}

void MatchingMethod(int, void*)
{
	//Mat srcImg = imread("images/ipad_test04.jpg");
	Mat srcImg = imread("images/temp2.bmp");
	Mat tempImg = imread("images/tempImg.png");

	int width = srcImg.cols - tempImg.cols + 1;
	int height = srcImg.rows - tempImg.rows + 1;

	int src_width = srcImg.cols;//图像宽度  
	int src_height = srcImg.rows;//图像高度
	if (src_width > 1920 || src_height > 1080)
	{
		float factor = min((float)1920 / src_width, (float)1080 / src_height);
		resize(srcImg, srcImg, Size(factor * src_width, factor * src_height));
		src_width *= factor;
		src_height *= factor;
	}

	Mat resultImg(Size(width, height), CV_32FC1);
	//2.模版匹配
	matchTemplate(srcImg, tempImg, resultImg, match_method2);
	//3.正则化(归一化到0-1)
	normalize(resultImg, resultImg, 0, 1, NORM_MINMAX, -1);
	//4.找出resultImg中的最大值及其位置
	double minValue = 0;
	double maxValue = 0;
	Point minPosition;
	Point maxPosition;
	minMaxLoc(resultImg, &minValue, &maxValue, &minPosition, &maxPosition);
	/// 对于方法 SQDIFF 和 SQDIFF_NORMED, 越小的数值代表更高的匹配结果. 而对于其他方法, 数值越大匹配越好
	if (match_method2 == TM_SQDIFF || match_method2 == TM_SQDIFF_NORMED)
	{
		maxPosition = minPosition;
	}
	else
	{
		maxPosition = maxPosition;
	}

	//4.遍历resultImg,给定筛选条件,筛选出前几个匹配位置
	int tempX = 0;
	int tempY = 0;
	char prob[10] = { 0 };
	//4.1遍历resultImg
	for (int i = 0; i < resultImg.rows; i++)
	{
		for (int j = 0; j < resultImg.cols; j++)
		{
			//4.2获得resultImg中(j,x)位置的匹配值matchValue
			double matchValue = resultImg.at<float>(i, j);
			sprintf_s(prob, "%.4f", matchValue);
			//4.3给定筛选条件
			//条件1:概率值大于0.9
			//条件2:任何选中的点在x方向和y方向上都要比上一个点大5
			if (matchValue > 0.9001 && abs(i - tempY) > 5 && abs(j - tempX) > 5)
			{
				//5.给筛选出的点画出边框和文字
				rectangle(srcImg, Point(j, i), Point(j + tempImg.cols, i + tempImg.rows), Scalar(0, 255, 0), 1, 8);
				putText(srcImg, prob, Point(j, i + 100), FONT_HERSHEY_COMPLEX, 1, Scalar(0), 2);
				tempX = j;
				tempY = i;
			}
		}
	}

	//5.根据resultImg中的最大值位置在源图上画出矩形
	rectangle(srcImg, maxPosition, Point(maxPosition.x + tempImg.cols, maxPosition.y + tempImg.rows), Scalar(0, 0, 255), 2, 8);
	imshow("image_window", srcImg);
	imshow("temp_window", tempImg);
}


/*基于滑动条进行多种灰度方法匹配*/
void Histogram_Matching::ImgMatch2()//24.图像匹配2
{
	/// 创建窗口
	namedWindow("image_window", WINDOW_AUTOSIZE);
	namedWindow("temp_window", WINDOW_AUTOSIZE);
	/// 创建滑动条
	createTrackbar("match_method", "image_window", &match_method2, max_Trackbar, MatchingMethod);
	MatchingMethod(0, 0);
	waitKey(0);
}

/* 基于灰度匹配的程序实现 */
void Histogram_Matching::Histogram_Matching_Demo()//24.图像匹配3
{

	Mat srcImg = imread("images/2D_srcImg/temp11.bmp");
	//Mat srcImg = imread("images/ipad_test03.jpg");
	Mat tempImg = imread("images/wxTemp.png");
	//1.构建结果图像resultImg(注意大小和类型)
	//如果原图(待搜索图像)尺寸为W x H, 而模版尺寸为 w x h, 则结果图像尺寸一定是(W-w+1)x(H-h+1)
	//结果图像必须为单通道32位浮点型图像
	int width = srcImg.cols - tempImg.cols + 1;
	int height = srcImg.rows - tempImg.rows + 1;

	int src_width = srcImg.cols;//图像宽度  
	int src_height = srcImg.rows;//图像高度
	if (src_width > 1920 || src_height > 1080)
	{
		float factor = min((float)1920 / src_width, (float)1080 / src_height);
		resize(srcImg, srcImg, Size(factor * src_width, factor * src_height));
		src_width *= factor;
		src_height *= factor;
	}
	//cout << srcImg.rows << "," << srcImg.cols << endl;

	Mat resultImg(Size(width, height), CV_32FC1);
	//2.模版匹配
	matchTemplate(srcImg, tempImg, resultImg, TM_CCOEFF_NORMED);
	imshow("result", resultImg);
	//3.正则化(归一化到0-1)
	normalize(resultImg, resultImg, 0, 1, NORM_MINMAX, -1);
	//4.遍历resultImg,给定筛选条件,筛选出前几个匹配位置
	int tempX = 0;
	int tempY = 0;
	char prob[10] = { 0 };
	//4.1遍历resultImg
	
	//4.找出resultImg中的最大值及其位置
	double minValue = 0;
	double maxValue = 0;
	Point minPosition;
	Point maxPosition;
	minMaxLoc(resultImg, &minValue, &maxValue, &minPosition, &maxPosition);


	//for (int i = 0; i < resultImg.rows; i++)
	//{
	//	for (int j = 0; j < resultImg.cols; j++)
	//	{
	//		//4.2获得resultImg中(j,x)位置的匹配值matchValue
	//		double matchValue = resultImg.at<float>(i, j);
	//		/*sprintf_s(prob, "%.2f", matchValue);*/
	//		sprintf_s(prob, "%.4f", matchValue);
	//		//4.3给定筛选条件
	//		//条件1:概率值大于0.9
	//		//条件2:任何选中的点在x方向和y方向上都要比上一个点大5
	//		if (matchValue > 0.9 && abs(i - tempY) > 5 && abs(j - tempX) > 5)
	//		{
	//			//5.给筛选出的点画出边框和文字
	//			rectangle(srcImg, Point(j, i), Point(j + tempImg.cols, i + tempImg.rows), Scalar(0, 255, 0), 1, 8);
	//			putText(srcImg, prob, Point(j, i + 100), FONT_HERSHEY_COMPLEX, 1, Scalar(0), 2);
	//			tempX = j;
	//			tempY = i;
	//		}
	//	}
	//}
	rectangle(srcImg, maxPosition, Point(maxPosition.x + tempImg.cols, maxPosition.y + tempImg.rows), Scalar(0, 0, 255), 2, 8);
	cout << "目标中心位置:" << maxPosition.x + tempImg.cols / 2 << "," << maxPosition.y + tempImg.rows / 2 << endl;
	imshow("srcImg", srcImg);
	imshow("template", tempImg);
	waitKey(0);
}

/* 基于灰度匹配的程序提炼模板 */
//method: 
//    CV_TM_SQDIFF   : 平方差匹配,最好时候为0;——不具备旋转
//    CV_TM_SQDIFF_NORMED :归一化平方差匹配,最好时候为0;——不具备旋转
//    CV_TM_CCORR      :相关性匹配法,最差为0;
//    CV_TM_CCORR_NORMED  :归一化相关性匹配法,最差为0;
//    CV_TM_CCOEFF     :系数匹配法,最好匹配为1;
//    CV_TM_CCOEFF_NORMED  :化相关系数匹配法,最好匹配为1;——匹配度较好-可以抵抗轻度旋转
//images/ipad_test04.jpg images/temp2.bmp 匹配有误
void Histogram_Matching::Histogram_Matching_Template_coder()
{
	//Mat srcImg = imread("images/temp2.bmp");
	//Mat srcImg = imread("images/ipad_test04.jpg");
	Mat srcImg = imread("images/2D_srcImg/temp11.bmp");
	//Mat tempImg = imread("images/wxTemp1.png");
	Mat tempImg = imread("images/qqTemp1.png");

	int width = srcImg.cols - tempImg.cols + 1;
	int height = srcImg.rows - tempImg.rows + 1;
	//resize_srcImg(srcImg, srcImg);
	//cout << srcImg.rows << "," << srcImg.cols << endl;

	int src_width = srcImg.cols;//图像宽度  
	int src_height = srcImg.rows;//图像高度
	if (src_width > 1920 || src_height > 1080)
	{
		float factor = min((float)1920 / src_width, (float)1080 / src_height);
		resize(srcImg, srcImg, Size(factor * src_width, factor * src_height));
		src_width *= factor;
		src_height *= factor;
	}


	Mat resultImg(Size(srcImg.cols, srcImg.rows), CV_32FC1);

	//2.模版匹配
	matchTemplate(srcImg, tempImg, resultImg, TM_CCOEFF_NORMED);

	//3.正则化(归一化到0-1)
	normalize(resultImg, resultImg, 0, 1, NORM_MINMAX, -1);
	imshow("result", resultImg);

	//4.找出resultImg中的最大值及其位置
	double minValue = 0;
	double maxValue = 0;
	Point minPosition;
	Point maxPosition;
	minMaxLoc(resultImg, &minValue, &maxValue, &minPosition, &maxPosition);

	RNG rng(12345);
	//4.1遍历resultImg
	int tempX = 0;
	int tempY = 0;
	char prob[10] = { 0 };
	for (int i = 0; i < resultImg.rows; i++)
	{
		for (int j = 0; j < resultImg.cols; j++)
		{
			//4.2获得resultImg中(i,j)位置的匹配值matchValue
			double matchValue = resultImg.at<float>(i, j);
			sprintf_s(prob, "%.4f", matchValue);
			//4.3给定筛选条件
			//条件1:概率值大于0.9
			//条件2:任何选中的点在x方向和y方向上都要比上一个点大30——放置重复检测同一个目标
			if (matchValue > 0.7 && abs(i - tempX) > 30 && abs(j - tempY) > 30)
			{
				//5.给筛选出的点画出边框和文字
				rectangle(srcImg, Point(j, i), Point(j + tempImg.cols, i + tempImg.rows), Scalar(0, 255, 255), 1, 8);
				putText(srcImg,prob,Point(j,i+100),FONT_HERSHEY_COMPLEX,1, Scalar(0), 2);
				tempX = i;
				tempY = j;
			}
		}
	}

	//5.画
	rectangle(srcImg, maxPosition, Point(maxPosition.x + tempImg.cols, maxPosition.y + tempImg.rows), Scalar(0, 0, 255), 2, 8);
	cout << "目标中心位置:" << maxPosition.x + tempImg.cols / 2 << "," << maxPosition.y + tempImg.rows / 2 << endl;

	imshow("srcImg", srcImg);

	waitKey(0);
}


int main()
{
	Histogram_Matching hist_match;
	hist_match.Histogram_Matching_Template_coder();
	//hist_match.Histogram_Matching_Demo();
	//hist_match.ImgMatch2();//不要
	return 0;

}

问题:如果模板图和原图比列发生变化,会匹配错误

#include<iostream>
#include<string>
#include<vector>
#include<opencv2\opencv.hpp>
//#include"Tracker.h"

using namespace cv;
using namespace std;

namespace global {
	bool paused = true;  //单击鼠标右键,暂停标志
	Mat displayImg;    //绘制选择目标时鼠标的拖动痕迹
	bool selectObject = false;  //selectObject的初始值为false,
	bool isRoiReady = false;  //ROI区域是否已经选择好
	Point origin;   //ROI区域的左上角起始位置
	Rect selectedRoi; //最终通过鼠标选择的ROI区域

	static void onMouse(int event, int x, int y, int, void*) {
		if (selectObject)  //鼠标左键被按下后,该段语句开始执行
		{
			selectedRoi.x = MIN(x, origin.x);
			selectedRoi.y = MIN(y, origin.y);
			selectedRoi.width = std::abs(x - origin.x);
			selectedRoi.height = std::abs(y - origin.y);
			selectedRoi &= Rect(0, 0, displayImg.cols, displayImg.rows);  //不能越界

			rectangle(displayImg, selectedRoi, Scalar(0, 0, 255), 1);  //画出鼠标选择框
		}

		switch (event)
		{
			//当在第一帧按下鼠标左键后,selectObject被置位1,拖动鼠标,开始选择目标的矩形区域
		case EVENT_LBUTTONDOWN:
			origin = Point(x, y);
			selectedRoi = Rect(x, y, 0, 0);
			selectObject = true;
			isRoiReady = false;
			break;
			//直到鼠标左键抬起,标志着鼠标区域选择完毕。selectObject被置为false
		case EVENT_LBUTTONUP:
			selectObject = false;
			if (selectedRoi.width > 0 && selectedRoi.height > 0) {
				isRoiReady = true;
			}
			cout << "目标区域已经选择完毕" << endl;
			cout << "选中的矩形区域为: " << selectedRoi << endl;
			break;
			//单击右键,暂停/开始
		case EVENT_RBUTTONDOWN:
			paused = !paused;
			break;
		}
	}
}

//**********下面用于自己定义的模板匹配方法做匹配*******//
float MatchTemplate(const Mat& src, const Mat& temp1, Point2i& match_location, int match_method)
{
	CV_Assert((src.type() == CV_8UC1) && (temp1.type() == CV_8UC1)); //申明只能处理单通道的图像

	//原图像和模板的尺寸
	int src_width = src.cols;
	int src_height = src.rows;
	int temp1_cols = temp1.cols;
	int temp1_rows = temp1.rows;
	int y_end = src_height - temp1_rows + 1;
	int x_end = src_width - temp1_cols + 1;

	//在匹配过程中,记录最匹配的位置和匹配度
	float match_degree = FLT_MAX;    //给匹配度赋一个最大匹配度初始值
	int y_match = -1, x_match = -1;

	//从上到下扫描原图像
	for (int y = 0; y < y_end; y++)
	{
		//从左到右扫描原图像
		for (int x = 0; x < x_end; x++)
		{
			//src(y,x)位置上与模板的匹配度
			float match_yx = 0.0f;
			//将模板左上角temp1(0,0)对齐到src(y,x)位置,在模板内累加每个采样像素点上的差异
			for (int r = 0; r < temp1_rows; r++) {
				for (int c = 0; c < temp1_cols; c++) {
					uchar src_val = src.ptr<uchar>(y + r)[x + c];
					uchar temp1_val = temp1.ptr<uchar>(r)[c];
					if (match_method == 0)  //SQDIFF=0
						match_yx += float(std::abs(src_val - temp1_val) * std::abs(src_val - temp1_val));
					if (match_method == 1)  //SADIFF=1
						match_yx += float(std::abs(src_val - temp1_val));
				}
			}
			//与历史最好的差异度进行比较,找出差异最小的点
			if (match_degree > match_yx) {
				match_degree = match_yx;
				y_match = y;
				x_match = x;
			}
		}
	}
	match_location = Point2i(x_match, y_match);
	return match_degree;
}
//**********以上用自己定义的模板匹配方法做匹配*********//


int main06(int argc, char* argv[])
{
	//******下面用于自己定义的模板匹配方法做匹配*******//
	//const string image_file = "images/temp1.bmp";
	const string image_file = "images/ipad_test01.jpg";
	Mat srcImg = imread(image_file, IMREAD_GRAYSCALE);
	//用来显示结果
	Mat displayImg;
	srcImg.copyTo(displayImg);

	//设置全局变量
	global::isRoiReady = false;
	global::selectObject = false;
	global::displayImg = displayImg;

	const string winname = "Result Image";

	namedWindow(winname, WINDOW_AUTOSIZE);
	setMouseCallback(winname, global::onMouse, 0);

	//循环显示图像,等待鼠标选择ROI区域
	for (;;)
	{
		imshow(winname, displayImg);
		//一旦选择好ROI区域,就进入处理
		if (global::isRoiReady) {
			//设置为false,处理完此次就接着等待鼠标选择
			global::displayImg = false;
			//提取鼠标选中的图像块
			Rect roiRect = global::selectedRoi;
			Mat roiImg = srcImg(roiRect).clone();
			imshow("ROI Image", roiImg);//显示ROI图像块

			//为原始图像增加高斯噪声
			Mat noiseImg(srcImg.size(), srcImg.type());
			cv::randn(noiseImg, Scalar(0), Scalar(30));
			Mat workImg = noiseImg + srcImg;
			//显示噪声污染的图像和选择的ROI区域
			workImg.copyTo(displayImg);
			rectangle(displayImg, global::selectedRoi, Scalar::all(0), 4);
			imshow(winname, displayImg);
			waitKey(15);

			//选中的模板在噪声污染的图像上匹配
			Point2i match_location;
			int match_method = 0;
			MatchTemplate(workImg, roiImg, match_location, match_method);
			Rect matchedRoi(match_location.x, match_location.y, roiImg.cols, roiImg.rows);
			//显示匹配结果
			rectangle(displayImg, matchedRoi, Scalar::all(255), 2);
			imshow(winname, displayImg);
			waitKey(15);
		}
		waitKey(15);
	}
}

自己求阈值

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

using namespace std;
using namespace cv;

//全局变量
Mat srcImage, templateImage, dstImage;
const int trackbar_method_maxValue = 5;
int trackbar_method;

std::vector<cv::Point> aim_pos(2);

void getRGBvector(const Mat& src, vector<unsigned int>& count)//得到64维向量
{
	int nRows = src.rows, nCols = src.cols * src.channels();
	const uchar* p;
	for (int i = 0; i < nRows; ++i)
	{
		p = src.ptr<uchar>(i);
		for (int j = 0; j < nCols; j += 3)
		{
			int r = int(p[j]) / 64;
			int g = int(p[j + 1]) / 64;
			int b = int(p[j + 2]) / 64;
			count[r * 16 + g * 4 + b]++;
		}
	}
}
double getVectorLength(vector<unsigned int>& vec)
{
	long long res = 0;
	for (int i = 0; i < vec.size(); i++)
		res += vec[i] * vec[i];
	return sqrt(res);
}
double getcos(vector<unsigned int>& count1, vector<unsigned int>& count2)
{
	double len1 = getVectorLength(count1);
	double len2 = getVectorLength(count2);
	assert(len1 != 0 && len2 != 0);
	long long sum = 0;
	for (int i = 0; i < count1.size(); i++)
		sum += count1[i] * count2[i];
	return (double)sum / len1 / len2 > 0 ? (double)sum / len1 / len2 : 0;
}
double getsimilarity(const Mat& src1, const Mat& src2)
{
	vector<unsigned int> count1(64), count2(64);
	getRGBvector(src1, count1);
	getRGBvector(src2, count2);
	double res = getcos(count1, count2);
	return res;
}

//定义回调函数
void method(int, void*)
{
	Mat display;
	srcImage.copyTo(display);
	//创建输出矩阵
	int dstImage_rows = srcImage.rows - templateImage.rows + 1;
	int dstImage_cols = srcImage.cols - templateImage.cols + 1;

	/**
	 * @brief 创建一个新的图像矩阵
	 * @param type 新矩阵类型.
	 *
	 */
	dstImage.create(dstImage_rows, dstImage_cols, srcImage.type());

	/*
		void cv::matchTemplate(
		cv::InputArray image, // 用于搜索的输入图像, 8U 或 32F, 大小 W-H
		cv::InputArray templ, // 用于匹配的模板,和image类型相同, 大小 w-h
		cv::OutputArray result, // 匹配结果图像, 类型 32F, 大小 (W-w+1)-(H-h+1)
		int method // 用于比较的方法
	);
	*/
	matchTemplate(srcImage, templateImage, dstImage, trackbar_method);   //模板匹配

	normalize(dstImage, dstImage, 0, 1, NORM_MINMAX);       //归一化处理

	//通过minMaxLoc定位最佳匹配位置
	double minValue, maxValue;
	Point minLocation, maxLocation;
	Point matchLocation;
	/*
	* minMaxLoc 函数的作用是在数组中找到全局最小和最大值。
	  src ,输入的数组,若是图像,需为单通道图像。
	  minVal,返回最小值的指针。若无需返回,此值设为 NULL。
	  maxVal,返回最大值的指针。若无需返回,此值设为 NULL。
	  minLoc,返回最小值位置的指针(二维情况下)。若无需返回,此值设为 NULL。
	  maxVal,返回最大值位置的指针(二维情况下)。若无需返回,此值设为 NULL。
	  mask,可选的掩膜操作,非零掩码元素用于标记待统计元素,需要与输入图像集有相同尺寸。
	*/
	minMaxLoc(dstImage, &minValue, &maxValue, &minLocation, &maxLocation, Mat());

	//对于方法SQDIFF和SQDIFF_NORMED两种方法来讲,越小的值就有着更高的匹配结果  
	// 平方差匹配和标准平方差匹配
	//而其余的方法则是数值越大匹配效果越好
	if (trackbar_method == TM_SQDIFF || trackbar_method == TM_SQDIFF_NORMED)
	{
		matchLocation = minLocation;
	}
	else
	{
		matchLocation = maxLocation;
	}
	imshow("匹配图像", display);
	double res = getsimilarity(srcImage, templateImage);
	

		//这里是对角线画矩形
		//参数:图片, 左上角, 右下角, 颜色, 线条粗细, 线条类型,点类型
		rectangle(display, Point(matchLocation.x, matchLocation.y), Point(matchLocation.x + templateImage.cols, matchLocation.y + templateImage.rows), Scalar(255, 0, 0), 3);
		cout << "目标位置:" << matchLocation.x + templateImage.cols / 2 << " " << matchLocation.y + templateImage.rows / 2 << std::endl;
		//resize(display,display, Size(), 0.25, 0.25);//缩小4倍
		//imshow("匹配图像", display);	
		cout << "res:" << 1.0 / (res + 1) << endl;

}

/**
 * namedWindow():新建一个显示窗口
 * 
 * \return 
 */
int main()
{
	srcImage = imread("images/ipad_test02.jpg");
	//templateImage = imread("images/icon64_wx_logo.png");
	 templateImage = imread("images/wxTemp.png");

	//判断文件是否加载成功
	if (srcImage.empty() || templateImage.empty())
	{
		cout << "图像加载失败!" << endl;
		return -1;
	}
	else
		cout << "图像加载成功..." << endl << endl;
	/**
	 * @brief 新建一个显示窗口
	 * @param 窗口名字
	 * @param 窗口标识  默认为WINDOW_AUTOSIZE 自动适应图片大小,并且不可手动更改
	 *						  WINDOW_NORMAL 用户可以改变这个窗口大小.
	 * 
	 * \return 
	 */
	namedWindow("原图像", WINDOW_AUTOSIZE);
	namedWindow("模板图像", WINDOW_AUTOSIZE);
	resize(srcImage, srcImage, Size(), 0.25, 0.25);//缩小4倍
	imshow("原图像", srcImage);
	imshow("模板图像", templateImage);

	//定义轨迹条参数
	trackbar_method = 1;
	//char mathodName[50];
	std::string methodName = "method";
	namedWindow("匹配图像", WINDOW_AUTOSIZE);
	//std::cout  << "匹配方式:\n 0:SQDIFF\n 1:SQDIFF_NORMED\n 2:TM_CCORR\n 3:TM_CCORR_NORMEND\n 4:TM_COEFF\n 5:TM_COEFF_NORMED" << trackbar_method_maxValue << std::endl;
	//sprintf(methodName, "匹配方式%d\n 0:SQDIFF\n 1:SQDIFF_NORMED\n 2:TM_CCORR\n 3:TM_CCORR_NORMEND\n 4:TM_COEFF\n 5:TM_COEFF_NORMED", trackbar_method_maxValue);
	
	/**
	 * @brief 创建滚动条
	 * @param trackbarname:用来给这个滚动条取一个名字
	 * @param winname:用来指定你要把这个滚动条用到那个窗口上
	 * @param value:用来设置滑块初始值位置,同时记录滑块以后的位置
	 * @param count:用来指定滚动条可以滚动的最大值
	 * @param onChange:用来接收回调函数函数名的,默认值为0;
	 * 
	 * \return 
	 */
	createTrackbar(methodName, "匹配图像", &trackbar_method, trackbar_method_maxValue, method);

	//double res = getsimilarity(srcImage, templateImage);
	//cout << "res:" << 1.0 / (res + 1) << endl;
	method(trackbar_method, 0);
	waitKey(0);

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值