1. 程式人生 > >影象相似度測量與模板匹配總結

影象相似度測量與模板匹配總結

摘要

本文主要總結了進行目標跟蹤、檢測中經常使用到的影象相似度測量和模板匹配方法,並給出了具體的基於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