相似圖片搜索原理三(顏色直方圖—c++實現)

       圖像的顏色直方圖可以用於圖像檢索,適應有相同色彩,並且可以有平移、縮放、旋轉不變性的圖像檢索,當然了這三大特點不如sift或者surf穩定性強,此外最大的侷限就是如果形狀內容一樣,但色彩不一,結果是搜不到的。不過它在某些情況下達到較好的結果。

顏色直方圖兩種計算方式:

彩色圖像的顏色直方圖,這裏可以有兩種處理方式,得到的效果應該差不多。

       首先第一種就是對像素的每個通道都進行劃分,每個通道的最大像素值爲255,可以等分816或者64等分,這樣每個通道的範圍就是0~15(16等分爲例,當然等分越小,像素值取的範圍越大,越精確,但圖像維數就越大,消耗時間複雜度大)。這樣三通道得到圖像維數就是16*16*16=4096([0,0,0]一直到[15,15,15])。代碼中我們使用了得到其下標操作爲i+(j<<4)+(k<<8)就等於i+j*16+k*16*16。比如一個像素爲[4,1,20],那麼就會有hist[4+1*16+20*16*16]++;

       第二種方法是單獨計算每個通道像素值的個數,比如一個像素點值爲[4,1,20],那麼就有bhist[4] ++;ghist[1]++; rhist[20]++;這樣就得到3256維的一維向量,然後可以做疊加操作。

距離的度量

距離的度量通常有歐式距離、皮爾遜相關係數及餘弦距離。但是這裏百度百科上說在做直方圖相似性度量時,巴氏距離效果最佳。我這裏做了簡單測試,發現歐式距離的確效果很差,這可能的原因比如當[5,5][1,1]應該相似的,但是歐式距離發現它們距離會很大。此外,這裏餘弦距離,測試效果也行,也是可以用的。

巴氏距離:又叫巴氏係數。用於測量兩離散概率分佈。它常在分類中測量類之間的可分離性。計算公式如下:

                                         

其中P, P’分別代表源與候選的圖像直方圖數據,對每個相同i的數據點乘積開平方以後相加得出的結果即爲圖像相似度值(巴氏係數因子值),範圍爲01之間。爲什麼是到1之間,這是數學的問題,就不追究了。當p(i)==p’(i) for all i時,結果就會爲1 p(i)p’(i)都在0~1之間。p(i)表示爲該像素值出現的次數和除以總的像素個數,就是一個概率,代碼中可以看出。

代碼:

計算方式一:

(1)得到顏色直方圖:

// 三維直方圖 方式一
void getHistogram(Mat &image, int *histValue){
	MatND hist;       // 在cv中用CvHistogram *hist = cvCreateHist
	int dims = 3;

	float r_hranges[] = {0, 255};
	float g_hranges[] = {0, 255};
	float b_hranges[] = {0, 255};
	const float *ranges[] = {r_hranges, g_hranges, b_hranges};   // 這裏需要爲const類型
	int size[3] = {16, 16, 16};
	int channels[] ={0, 1, 2};   //代表 r g通道 2代表b通道
	// 計算圖像的直方圖
	calcHist(&image, 1, channels, Mat(), hist, dims, size, ranges);    // cv 中是cvCalcHist
	

	for(int i = 0; i < 16; i++)
	{
		for(int j = 0; j < 16; j++)
		{
			for(int k = 0; k < 16; k++)
			{
				float value = hist.at<float>(i,j,k);           //   注意直方圖的值是float類型    cv中用cvQueryHistValue_1D
				int realValue = saturate_cast<int>(value);
				int index = i + (j<<4) + (k<<8);
				histValue[index] = realValue;

			}
		}
	}

}


(2)三種距離度量的代碼

// 歐式距離
float getDistance(int *sur, int *dst){
	float sum = 0;
	for(int i = 0; i < MaxHistValue; i++){
		sum += pow(sur[i]-dst[i]+0.0,2);
	}
	return sqrt(sum);
}

// 餘弦距離
float getCosDistance(int *sur, int *dst){
	float surSum = 0, dstSum = 0, sum = 0;
	for(int i = 0; i < MaxHistValue; i++){
		surSum += pow(sur[i]+0.0,2);
		dstSum += pow(dst[i]+0.0,2);
		sum += sur[i]*dst[i];
	}
	surSum = sqrt(surSum);
	dstSum = sqrt(dstSum);
	return sum/(surSum*dstSum);
}

// 巴氏距離,  需要除以總元素個個數  
// 注意:在顏色直方圖的相似度比較中,巴氏距離效果最好

float getPSDistance(int *sur, int*dst, const float sTotal, const float dTotal){
	float sum = 0;
	for(int i = 0; i < MaxHistValue; i++){
		sum += sqrt((sur[i]/sTotal)*(dst[i]/dTotal));
	}
	return sum;
}

測試圖片:


餘弦結果:


巴氏距離結果:


其中【i-j】, i代表personi j代表personiperson的漢明距離。並由結果可見phash對於圖片的旋轉肯定是無能爲力的。

由結果可見,針對person6,很相似,但餘弦結果不好,而巴氏距離很好,此外巴氏距離對於原圖不是1,是因爲計算過程中的精度丟失造成的。

 

計算方式二:

(1)得到顏色直方圖

// 三維直方圖 方式二
void getHistogram2(Mat &image, int **HistValue){
	for(int i = 0; i < image.rows; i++){
		for(int j = 0; j < image.cols; j++){
			HistValue[0][image.at<Vec3b>(i,j)[0]] ++;
			HistValue[1][image.at<Vec3b>(i,j)[1]] ++;
			HistValue[2][image.at<Vec3b>(i,j)[2]] ++;
		}
	}
	
}

(2)三種距離度量的代碼

// 歐式距離
float getDistance(int **sur, int **dst){
	float sum = 0;
	for(int i = 0; i < 3; i++){
		for(int j = 0; j < 256; j++){
			sum += pow(sur[i][j]-dst[i][j]+0.0,2);
		}
		
	}
	return sqrt(sum);
}

// 餘弦距離
float getCosDistance(int **sur, int **dst){
	float surSum = 0, dstSum = 0, sum = 0;
	for(int i = 0; i < 3; i++){
		for(int j = 0; j < 256; j++){
			surSum += pow(sur[i][j]+0.0,2);
			dstSum += pow(dst[i][j]+0.0,2);
			sum += sur[i][j]*dst[i][j];
		}
		
	}
	surSum = sqrt(surSum);
	dstSum = sqrt(dstSum);
	return sum/(surSum*dstSum);
}

// 巴氏距離,  需要除以總元素個個數  
// 注意:在顏色直方圖的相似度比較中,巴氏距離效果最好

float getPSDistance(int **sur, int**dst, const float sTotal, const float dTotal){
	float sum = 0;
	for(int i = 0; i < 3; i++){
		for(int j = 0; j < 256; j++){
			sum += sqrt((sur[i][j]/sTotal)*(dst[i][j]/dTotal));
		}
	}
	return sum/3;    // 因爲這裏有三個
}

餘弦結果:


巴氏距離結果:


其中【i-j】, i代表personi j代表personiperson的漢明距離。並由結果可見phash對於圖片的旋轉肯定是無能爲力的。

完整源碼(均勻hash、感知hash、顏色直方圖)下載地址:

http://download.csdn.net/detail/lu597203933/8710535 

參考文獻:

1http://blog.csdn.net/jia20003/article/details/7771651

2http://blog.csdn.net/luoweifu/article/details/8690835

3http://baike.baidu.com/view/10343198.htm巴氏距離

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章