【46】【OpenCv】模板匹配问题

导读:本篇文章讲解 【46】【OpenCv】模板匹配问题,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

OpenCv提供cv::matchTemplate()进行模板匹配,该函数不基于直方图,而是使用一个图像块在输入图像上进行“滑动”,并使用设置的匹配方法进行比较。

函数声明:

void cv::matchTemplate(
	cv::InputArray image,  // input image to be searched,8U or 32F, size W-by-H
	cv::InputArray temp1,  // template to use,same type as 'image',size w-by-h
	cv::OutputArray result,  // result image, type32F,size (W-w+0)-by-(H-h+1)
	int method  // comparsion method to use
);

参数image是输入的要匹配的图片,类型是8为或浮点型灰度或彩色图。

参数temp1是匹配的模板,包含给定的物体。

参数result是结果图像,是单通道,大小为(image.width – temp1.width+1, image.height – temp1.height+1)的以整数字节或浮点存储的图片。

参数method可以设置为如下的方法,每种方法都有一个归一化的版本。归一化的版本可以降低模板和图片之间由于光照不同引起的效果。

如下公式中I表示输入图像,T表示模板,R表示输出的结果图像

1. 方差匹配方法 cv::TM_SQDIFF g归一化版本cv::TM_SQDIFF_NORMED

以方差为依据进行匹配,完全匹配结果为0,不匹配会得到一个很大的值。

R_{sq-diff} = \sum_{x^{'},y^{'}}^{}[T(x^{'},y^{'}) - I(x + x^{'},y+y^{'})]^{2}

R_{sq-diff-normed} = \frac{\sum_{x^{'},y^{'}}^{}[T(x^{'},y^{'}) - I(x+x^{'},y+y^{'})]^{2}}{\sqrt{\sum_{x^{'},y^{'}}^{}T(x^{'},y^{'})^{2} \cdot \sum_{x^{'},y^{'}}^{} I(x+x^{'},y+y^{'})^{2}}}

2. 相关性匹配方法 cv::TM_CCORR/cv::TM_CCORR_NORMED

相关性匹配方式以相乘的方式进行模板匹配,完全匹配得到一个很大的值,不匹配得到一个很小的值或0。

R_{ccorr} = \sum_{x^{'},y^{'}}^{}T(x^{'},y^{'})\cdot I(x+x^{'},y+y^{'})

R_{ccorr-normed} = \frac{\sum_{x^{'},y^{'}}^{}[T(x^{'},y^{'}) \cdot I(x+x^{'},y+y^{'})]^{2}}{\sqrt{\sum_{x^{'},y^{'}}^{}T(x^{'},y^{'})^{2} \cdot \sum_{x^{'},y^{'}}^{} I(x+x^{'},y+y^{'})^{2}}}

3. 相关系数匹配方法 cv::TM_CCOEFF/cv::TM_CCOEFF_NORMED

相关系数匹配方法对模板相对于其平均值的变化和图片相对于其平均值的变化进行匹配。完全匹配得到1,完全无匹配得到-1。如果用随机图片匹配得到0,表示两张图片毫无关联。

R_{ccoeff} = \sum_{x^{'},y^{'}}^{}T^{'}(x^{'},y^{'})\cdot I^{'}(x+x^{'},y+y^{'})

R_{ccoeff-normed} = \frac{\sum_{x^{'},y^{'}}^{}T^{'}(x^{'},y^{'})\cdot I^{'}(x+x^{'},y+y^{'})}{\sqrt{\sum_{x^{'},y^{'}}^{}T'(x^{'},y^{'})^{2} \cdot \sum_{x^{'},y^{'}}^{} I'(x+x^{'},y+y^{'})^{2}}}

T^{'}(x',y') = T(x',y') - \frac{\sum_{x^{n},y^{n}} T(x^{n},y^{n})}{(w-h)}

I^{'}(x+x',y+y') = I(x+x',y+y') - \frac{\sum_{x^{n},y^{n}} I(x^{n},y^{n})}{(w-h)}

通常情况下,从一个相对简单的度量方法(方差)换程一个更复杂的度量方法(相关系数)时,会得到更精确的结果(以更长的计算时间为代价)。

cv::matchTemplate()获得result后,可以使用cv::minMaxLoc()或着cv::minMaxIdx()找到最优匹配出现的位置。

为了避免随机性引起的该位置恰好匹配的很好,期望在找到最优匹配的邻域内也有不错的匹配结果。好的匹配点附近也应该有很好的匹配值。可以在寻找最优匹配值之前,先对结果进行轻微的平滑。

如下代码读入模板图片和要匹配的图片,分别使用6种方法进行匹配,匹配结果标示在原图中。

#include <opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main(int argc,char *argv[])
{

	cv::Mat src,temp1,ftemp[6];

	// 读取匹配模板
	temp1 = cv::imread(argv[1],cv::IMREAD_COLOR);
	if(temp1.empty())
	{
		cout << "Load image faile," << argv[1] << endl;
		return -1;
	}

	// 读取图像
	src = cv::imread(argv[2],cv::IMREAD_COLOR);
	if(src.empty())
	{
		cout << "Load image faile," << argv[2] << endl;
		return -1;
	}
	

	double maxval,minval;
	cv::Point ptmin,ptmax;
	cv::Point pt;
	cv::imshow("template",temp1);
	const char *szMethod[] = {
		"SQDIFF",
		"SQDIFF_NORMED",
		"CCORR",
		"CCORR_NORMED",
		"CCOEFF",
		"CCOEFF_NORMED"
	};
	cv::Mat srctmp,tmpblur;
	for(int i=0;i<6;i++)
	{
		srctmp = src.clone();
		cv::matchTemplate(src,temp1,ftemp[i],i);
		cv::normalize(ftemp[i],ftemp[i],1,0,cv::NORM_MINMAX);

		// 平滑处理
		cv::blur(ftemp[i],tmpblur,cv::Size(3,3));
		cv::minMaxLoc(tmpblur,&minval,&maxval,&ptmin,&ptmax);
		pt=ptmin;
		if(i > 1)
			pt=ptmax;
		cv::rectangle(srctmp,cv::Rect(pt.x,pt.y,temp1.cols,temp1.rows),cv::Scalar(0,0,255),2,8);
		cv::imshow("image",srctmp);
		cv::imshow(szMethod[i],ftemp[i]);

		cv::waitKey(0);
	}

	cv::waitKey(0);

	return 0;

}

模板图片:

【46】【OpenCv】模板匹配问题

要匹配的图片:

【46】【OpenCv】模板匹配问题

匹配结果:

【46】【OpenCv】模板匹配问题

 【46】【OpenCv】模板匹配问题

 【46】【OpenCv】模板匹配问题

 【46】【OpenCv】模板匹配问题

 【46】【OpenCv】模板匹配问题

 【46】【OpenCv】模板匹配问题

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/46132.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!