Opencv3.4.4 利用matchTemplate方法实现多目标匹配

       matchTemplate实现单目标匹配的方法很多在此不赘述,本文主要提供多目标匹配的方法。

       首先matchTemplate( InputArray image, InputArray templ, OutputArray result, int method, InputArray mask = noArray() );三个参数Result,反应的是样本与待测目标的相似程度的一个矩阵;

       minMaxLoc函数是找出矩阵中最大最小值的大小和位置。

1、 使用matchTemplate得到Result,利用minMaxLoc确定最佳匹配位置,接着利用CoverTarget函数(见下文代码)覆盖掉目标区域得到新的Result重复上述步骤;

2、设置阈值使Result中符合阈值范围的点全部画出来,缺点同个目标被多词框出,解决方法在符合阈值点的领域范围内寻找最佳值。(未实现)。

核心代码:

方法1:

int main()
{
	Mat src = imread("1.jpg");
	Mat tem = imread("temp.jpg", 0);
	Mat gray = Mat::zeros(src.size(), CV_8UC1);
	cvtColor(src, gray, COLOR_BGR2GRAY);

	Mat resultImage;

	int resultImage_cols = gray.cols - tem.cols + 1;
	int resultImage_rows = gray.rows - tem.rows + 1;
	resultImage.create(resultImage_cols, resultImage_rows, CV_32FC1);
	

	matchTemplate(gray, tem, resultImage, 1);

	double minValue, maxValue;
	Point minLoc, maxLoc;
	minMaxLoc(resultImage, &minValue, &maxValue, &minLoc, &maxLoc,  Mat());
	rectangle(src, minLoc, Point(minLoc.x + tem.cols, minLoc.y + tem.rows), Scalar(0, 0, 255), 1, 8, 0);

	// 计算第二个最小值  
	
	CoverTarget(resultImage, minLoc, maxValue, tem.cols, tem.rows);
	minMaxLoc(resultImage, &minValue, &maxValue, &minLoc, &maxLoc, Mat());
	rectangle(src, minLoc, Point(minLoc.x + tem.cols, minLoc.y + tem.rows), Scalar(0, 0, 255), 1, 8, 0);



	// 计算三个最小值  
	CoverTarget(resultImage, minLoc, maxValue, tem.cols, tem.rows);
	minMaxLoc(resultImage, &minValue, &maxValue, &minLoc, &maxLoc, Mat());
	rectangle(src, minLoc, Point(minLoc.x + tem.cols, minLoc.y + tem.rows), Scalar(0, 0, 255), 1, 8, 0);


	imshow("2", src);

	waitKey(0);
	return 0;
}


void CoverTarget(Mat &result, Point minLoc, int maxVaule, int cols, int rows)
{

	// 先将第一个最小值点附近两倍模板宽度和高度的都设置为最大值防止产生干扰  
	int startX = minLoc.x - cols;
	int startY = minLoc.y - rows;
	int endX = minLoc.x + cols;
	int endY = minLoc.y + rows;
	if (startX < 0)
	{
		startX = 0;
	}
	if (startY < 0)
	{
		startY = 0;
	}
	if (endX > result.cols - 1)
	{
		endX = result.cols - 1;
	}
	if (endY > result.rows - 1)
	{
		endY = result.rows - 1;
	}

	int y, x;
	for (y = startY; y < endY; y++)
	{
		for (x = startX; x < endX; x++)
		{
			result.at<float>(y, x) = maxVaule;		//覆盖
		}
	}
}

结果:

完整代码链接:https://download.csdn.net/download/qq_34902877/11042461

方法2:  法1和法2效果图贴反,抱歉

int main()
{
	Mat src = imread("1.jpg");
	Mat tem = imread("temp.jpg",0);
	Mat gray = Mat::zeros(src.size(), CV_8UC1);
	cvtColor(src, gray, COLOR_BGR2GRAY);

	Mat resultImage;

	int resultImage_cols = gray.cols - tem.cols + 1;
	int resultImage_rows = gray.rows - tem.rows + 1;
//	int resultImage_cols = gray.cols;
//	int resultImage_rows = gray.rows;
	resultImage.create(resultImage_cols, resultImage_rows, CV_32FC1);

	//进行匹配和标准化
	/*
	参数四:SQDIFF和SQDIFF_NORMED越小数值匹配效果更好,其他方法则反之。
	TM_SQDIFF	TM_SQDIFF_NORMED	TM_CCORR
	TM_CCORR_NORMED	TM_CCOEFF	TM_CCOEFF_NORMED
	*/
	int matchMethod = 5;//1 3 5
	
	matchTemplate(gray, tem, resultImage, matchMethod);
	imshow("效果图片1", resultImage);
//	cout << resultImage;
	float threshold;
	for (int i = 0; i < resultImage.rows; i++)
	{
		for (int j = 0; j < resultImage.cols; j++)
		{
			if (matchMethod == 1)
			{
				threshold = 0.4;
				if (resultImage.at<float>(i, j) < threshold)
				{
					rectangle(src, Point(j, i), Point(j + tem.cols, i + tem.rows), Scalar(0, 0, 255), 1, 8, 0);
				}
			}
			else if(matchMethod == 3)
			{
				threshold = 0.8;
				if (resultImage.at<float>(i, j) > threshold && resultImage.at<float>(i, j) < 1)
				{
					rectangle(src, Point(j, i), Point(j + tem.cols, i + tem.rows), Scalar(0, 0, 255), 1, 8, 0);
				}
			}
			else if (matchMethod == 5)
			{
				threshold = 0.6;
				if (resultImage.at<float>(i, j) > threshold && resultImage.at<float>(i, j) < 1)
				{
					rectangle(src, Point(j, i), Point(j + tem.cols, i + tem.rows), Scalar(0, 0, 255), 1, 8, 0);
				}
			}
		}
	}
	imshow("原始图片", src);


	cvWaitKey(0);
	return 0;
}

结果:

完整代码链接:https://download.csdn.net/download/qq_34902877/11042459

  • 5
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值