图像类似度測量与模板匹配总结

摘要

本文主要总结了进行目标跟踪、检測中常常使用到的图像相似度測量和模板匹配方法,并给出了详细的基于OpenCV的代码实现。

引言

模板匹配是一种在源图像中寻找与图像patch最相似的技术,经常常使用来进行目标的识别、跟踪与检測。当中最相似肯定是基于某种相似度准则来讲的。也就是须要进行相似度的測量。另外,寻找就须要在图像上进行逐行、逐列的patch窗体扫描,当然也不一定须要逐行逐列的扫描。当几个像素的误差比计算速度来的不重要时就能够设置扫描的行列步进值,以加快扫描和计算的时间消耗。以下就对相似度測量和模板匹配进行介绍(全部的图像都假定是灰度图)。

正文

图像相似度測量

直方图方法

方法描写叙述:有两幅图像patch(当然也但是整幅图像),分别计算两幅图像的直方图,并将直方图进行归一化,然后依照某种距离度量的标准进行相似度的測量。

方法的思想:基于简单的向量相似度来对图像相似度进行度量。

长处:直方图可以非常好的归一化,比方256个bin条。那么即使是不同分辨率的图像都可以直接通过其直方图来计算相似度。计算量适中。比較适合描写叙述难以自己主动切割的图像。

缺点:直方图反应的是图像灰度值得概率分布。并没有图像的空间位置信息在里面,因此。经常出现误判。从信息论来讲。通过直方图转换。信息丢失量较大。因此单一的通过直方图进行匹配显得有点力不从心。

基于opencv的实现,我把它封装为函数(输入输出都是灰度图像,且设定的灰度级为8,及0-255),有须要的能够直接拿去使用

<span style="font-size:18px;"><span style="font-size:18px;">double getHistSimilarity(const Mat& I1, const Mat& I2)
{
	int histSize = 256;
	float range[] = {0,256};
	const float* histRange = {range};
	bool uniform = true;
	bool accumulate = false;

	Mat hist1,hist2;

	calcHist(&I1,1,0,Mat(),hist1,1,&histSize,&histRange,uniform,accumulate);
	normalize(hist1,hist1,0,1,NORM_MINMAX,-1,Mat());

	calcHist(&I2,1,0,Mat(),hist2,1,&histSize,&histRange,uniform,accumulate);
	normalize(hist2,hist2,0,1,NORM_MINMAX,-1,Mat());

	return compareHist(hist1, hist2, CV_COMP_CORREL);

}</span></span>
当中直方图比較的方法在opencv中的实现的有:

/* Histogram comparison methods */
enum
{
    CV_COMP_CORREL        =0,
    CV_COMP_CHISQR        =1,
    CV_COMP_INTERSECT     =2,
    CV_COMP_BHATTACHARYYA =3,
    CV_COMP_HELLINGER     =CV_COMP_BHATTACHARYYA
};
各自是:相关度。卡方,相交系数和巴氏距离。其计算公式例如以下图所看到的:


直方图方法的一些改进的出发点大致是为了改善直方图无法利用空间位置信息的弱点,比方FragTrack算法,将图像再进行切割成横纵的patch,然后对于每个patch搜索与之匹配的直方图,来计算两幅图像的相似度,从而融入了直方图相应的位置信息,但计算效率肯定不高。


矩阵分解的方法

方法描写叙述:将图像patch做矩阵分解,比方SVD神秘值分解和NMF非负矩阵分解等,然后再做相似度的计算。

方法思想:由于图像本身来讲就是一个矩阵,能够依靠矩阵分解获取一些更加鲁棒的特征来对图像进行相似度的计算。

基于SVD分解的方法长处:神秘值的稳定性,比例不变性。旋转不变性和压缩性。

即神秘值分解是基于总体的表示。不但具有正交变换、旋转、位移、镜像映射等代数和几何上的不变性,并且具有良好的稳定性和抗噪性,广泛应用于模式识别与图像分析中。对图像进行神秘值分解的目的是得到唯一、稳定的特征描写叙述。减少特征空间的维度,提高抗干扰能力。

基于SVD分解的方法缺点是:神秘值分解得到的神秘矢量中有负数存在,不能非常好的解释其物理意义。


基于NMF分解的方法:将非负矩阵分解为能够体现图像主要信息的基矩阵与系数矩阵。而且能够对基矩阵赋予非常好的解释,比方对人脸的切割,得到的基向量就是人的“眼睛”、“鼻子”等主要概念特征,源图像表示为基矩阵的加权组合,所以。NMF在人脸识别场合发挥着巨大的作用。

基于矩阵特征值计算的方法还有非常多,比方Trace变换,不变矩计算等。

基于特征点方法

方法描写叙述:统计两个图像patch中匹配的特征点数。假设相似的特征点数比例最大,则觉得最相似,最匹配
方法思想:图像能够中特征点来描写叙述,比方sift特征点。LK光流法中的角点等等。

这样相似度的測量就转变为特征点的匹配了。

曾经做过一些实验。关于特征点匹配的。对一幅图像进行仿射变换,然后匹配两者之间的特征点。选取的特征点有sift和高速的sift变形版本号surf等。
方法长处:能被选作特征点的大致要满足不变性,尺度不变性,旋转不变等。这样图像的相似度计算也就具备了这些不变性。

方法缺点:特征点的匹配计算速度比較慢。同一时候特征点也有可能出现错误匹配的现象。


基于峰值信噪比(PSNR)的方法

当我们想检查压缩视频带来的细微差异的时候,就须要构建一个可以逐帧比較差视频差异的系统。最
经常使用的比較算法是PSNR( Peak signal-to-noise ratio)。这是个使用“局部均值误差”来推断差异的最简单的方法。如果有这两幅图像:I1和I2,它们的行列数各自是i。j。有c个通道。

每一个像素的每一个通道的值占用一个字节。值域[0,255]。

注意当两幅图像的同样的话。MSE的值会变成0。这样会导致PSNR的公式会除以0而变得没有意义。所以我们须要单独的处理这种特殊情况。此外因为像素的动态范围非常广,在处理时会使用对数变换来缩小范围。

基于OpenCV的PSNR方法实现,相同将其封装为函数,能够直接拿来调用:

<span style="font-size:18px;">double getPSNR(const Mat& I1, const Mat& I2)
{
	Mat s1;
	absdiff(I1, I2, s1);       // |I1 - I2|
	s1.convertTo(s1, CV_32F);  // cannot make a square on 8 bits
	s1 = s1.mul(s1);           // |I1 - I2|^2

	Scalar s = sum(s1);         // sum elements per channel

	double sse = s.val[0] + s.val[1] + s.val[2]; // sum channels

	if( sse <= 1e-10) // for small values return zero
		return 0;
	else
	{
		double  mse =sse /(double)(I1.channels() * I1.total());
		double psnr = 10.0*log10((255*255)/mse);
		return psnr;
	}
}</span>

考察压缩后的视频时,这个值大约在30到50之间。数字越大则表明压缩质量越好。假设图像差异非常明显,就可能会得到15甚至更低的值。PSNR算法简单,检查的速度也非常快。

可是其呈现的差异值有时候和人的主观感受不成比例。所以有第二种称作 结构相似性 的算法做出了这方面的改进。

基于结构相似性(SSIM,structural similarity (SSIM) index measurement)的方法


结构相似性理论觉得,自然图像信号是高度结构化的,即像素间有非常强的相关性。特别是空域中最接近的像素。这样的相关性蕴含着视觉场景中物体结构的重要信息;HVS的主要功能是从视野中提取结构信息,能够用对结构信息的度量作为图像感知质量的近似。

结构相似性理论是一种不同于以往模拟HVS低阶的组成结构的全新思想,与基于HVS特性的方法相比,最大的差别是自顶向下与自底向上的差别。

这一新思想的关键是从对感知误差度量到对感知结构失真度量的转变。它没有试图通过累加与心理物理学简单认知模式有关的误差来预计图像质量,而是直接预计两个复杂结构信号的结构改变。从而在某种程度上绕开了自然图像内容复杂性及多通道去相关的问题.作为结构相似性理论的实现。结构相似度指数从图像组成的角度将结构信息定义为独立于亮度、对照度的。反映场景中物体结构的属性。并将失真建模为亮度、对照度和结构三个不同因素的组合。用均值作为亮度的预计。标准差作为对照度的预计,协方差作为结构相似程度的度量。

基于OpenCV的SSIM方法实现。相同将其封装为函数,能够直接拿来调用:

<span style="font-size:18px;">Scalar getMSSIM( const Mat& i1, const Mat& i2)
{
	const double C1 = 6.5025, C2 = 58.5225;
	/***************************** INITS **********************************/
	int d     = CV_32F;

	Mat I1, I2;
	i1.convertTo(I1, d);           // cannot calculate on one byte large values
	i2.convertTo(I2, d);

	Mat I2_2   = I2.mul(I2);        // I2^2
	Mat I1_2   = I1.mul(I1);        // I1^2
	Mat I1_I2  = I1.mul(I2);        // I1 * I2

	/*************************** END INITS **********************************/

	Mat mu1, mu2;   // PRELIMINARY COMPUTING
	GaussianBlur(I1, mu1, Size(11, 11), 1.5);
	GaussianBlur(I2, mu2, Size(11, 11), 1.5);

	Mat mu1_2   =   mu1.mul(mu1);
	Mat mu2_2   =   mu2.mul(mu2);
	Mat mu1_mu2 =   mu1.mul(mu2);

	Mat sigma1_2, sigma2_2, sigma12;

	GaussianBlur(I1_2, sigma1_2, Size(11, 11), 1.5);
	sigma1_2 -= mu1_2;

	GaussianBlur(I2_2, sigma2_2, Size(11, 11), 1.5);
	sigma2_2 -= mu2_2;

	GaussianBlur(I1_I2, sigma12, Size(11, 11), 1.5);
	sigma12 -= mu1_mu2;

	///////////////////////////////// FORMULA ////////////////////////////////
	Mat t1, t2, t3;

	t1 = 2 * mu1_mu2 + C1;
	t2 = 2 * sigma12 + C2;
	t3 = t1.mul(t2);              // t3 = ((2*mu1_mu2 + C1).*(2*sigma12 + C2))

	t1 = mu1_2 + mu2_2 + C1;
	t2 = sigma1_2 + sigma2_2 + C2;
	t1 = t1.mul(t2);               // t1 =((mu1_2 + mu2_2 + C1).*(sigma1_2 + sigma2_2 + C2))

	Mat ssim_map;
	divide(t3, t1, ssim_map);      // ssim_map =  t3./t1;

	Scalar mssim = mean( ssim_map ); // mssim = average of ssim map
	return mssim;
}
</span>

图像模板匹配

一般而言,源图像与模板图像patch尺寸一样的话,能够直接使用上面介绍的图像相似度測量的方法;假设源图像与模板图像尺寸不一样。通常须要进行滑动匹配窗体,扫面个整幅图像获得最好的匹配patch。

在OpenCV中相应的函数为:matchTemplate():函数功能是在输入图像中滑动窗体寻找各个位置与模板图像patch的相似度。相似度的评价标准(匹配方法)有:CV_TM_SQDIFF平方差匹配法(相似度越高,值越小),CV_TM_CCORR相关匹配法(採用乘法操作,相似度越高值越大),CV_TM_CCOEFF相关系数匹配法(1表示最好的匹配,-1表示最差的匹配)。

CV_TM_SQDIFF计算公式:


CV_TM_CCORR计算公式:



有一种新的用来计算相似度或者进行距离度量的方法:EMD,Earth Mover's Distances

EMD is defined as the minimal cost that must be paid to transform one histograminto the other, where there is a “ground distance” between the basic featuresthat are aggregated into the histogram。

光线变化能引起图像颜色值的漂移,虽然漂移没有改变颜色直方图的形状,但漂移引起了颜色值位置的变化,从而可能导致匹配策略失效。而EMD是一种度量准则,度量如何将一个直方图转变为还有一个直方图的形状,包含移动直方图的部分(或所有)到一个新的位置,能够在随意维度的直方图上进行这样的度量。

在OpenCV中有对应的计算方法:cvCalcEMD2()。

结合着opencv支持库。计算直方图均衡后与原图的HSV颜色空间直方图之间的EMD距离。
*******************************************************************************************************************************************************************************************************

2015-7-24

原文地址:https://www.cnblogs.com/wzjhoutai/p/7242993.html