相似图片搜索原理三(颜色直方图—c++实现)
圖像的顏色直方圖可以用于圖像檢索,適應(yīng)有相同色彩,并且可以有平移、縮放、旋轉(zhuǎn)不變性的圖像檢索,當(dāng)然了這三大特點(diǎn)不如sift或者surf穩(wěn)定性強(qiáng),此外最大的局限就是如果形狀內(nèi)容一樣,但色彩不一,結(jié)果是搜不到的。不過(guò)它在某些情況下達(dá)到較好的結(jié)果。
顏色直方圖兩種計(jì)算方式:
彩色圖像的顏色直方圖,這里可以有兩種處理方式,得到的效果應(yīng)該差不多。
首先第一種就是對(duì)像素的每個(gè)通道都進(jìn)行劃分,每個(gè)通道的最大像素值為255,可以等分8、16或者64等分,這樣每個(gè)通道的范圍就是0~15(以16等分為例,當(dāng)然等分越小,像素值取的范圍越大,越精確,但圖像維數(shù)就越大,消耗時(shí)間復(fù)雜度大)。這樣三通道得到圖像維數(shù)就是16*16*16=4096維(從[0,0,0]一直到[15,15,15])。代碼中我們使用了得到其下標(biāo)操作為i+(j<<4)+(k<<8)就等于i+j*16+k*16*16。比如一個(gè)像素為[4,1,20],那么就會(huì)有hist[4+1*16+20*16*16]++;
第二種方法是單獨(dú)計(jì)算每個(gè)通道像素值的個(gè)數(shù),比如一個(gè)像素點(diǎn)值為[4,1,20],那么就有bhist[4] ++;ghist[1]++; rhist[20]++;這樣就得到3個(gè)256維的一維向量,然后可以做疊加操作。
距離的度量
距離的度量通常有歐式距離、皮爾遜相關(guān)系數(shù)及余弦距離。但是這里百度百科上說(shuō)在做直方圖相似性度量時(shí),巴氏距離效果最佳。我這里做了簡(jiǎn)單測(cè)試,發(fā)現(xiàn)歐式距離的確效果很差,這可能的原因比如當(dāng)[5,5]與[1,1]應(yīng)該相似的,但是歐式距離發(fā)現(xiàn)它們距離會(huì)很大。此外,這里余弦距離,測(cè)試效果也行,也是可以用的。
巴氏距離:又叫巴氏系數(shù)。用于測(cè)量?jī)呻x散概率分布。它常在分類(lèi)中測(cè)量類(lèi)之間的可分離性。計(jì)算公式如下:
其中P, P’分別代表源與候選的圖像直方圖數(shù)據(jù),對(duì)每個(gè)相同i的數(shù)據(jù)點(diǎn)乘積開(kāi)平方以后相加得出的結(jié)果即為圖像相似度值(巴氏系數(shù)因子值),范圍為0到1之間。為什么是到1之間,這是數(shù)學(xué)的問(wèn)題,就不追究了。當(dāng)p(i)==p’(i) for all i時(shí),結(jié)果就會(huì)為1。 p(i)與p’(i)都在0~1之間。p(i)表示為該像素值出現(xiàn)的次數(shù)和除以總的像素個(gè)數(shù),就是一個(gè)概率,代碼中可以看出。
代碼:
計(jì)算方式一:
(1)得到顏色直方圖:
?
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | // 三維直方圖 方式一 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類(lèi)型 ????int size[3] = {16, 16, 16}; ????int channels[] ={0, 1, 2};?? //代表 r g通道 2代表b通道 ????// 計(jì)算圖像的直方圖 ????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類(lèi)型??? cv中用cvQueryHistValue_1D ????????????????int realValue = saturate_cast<int>(value); ????????????????int index = i + (j<<4) + (k<<8); ????????????????histValue[index] = realValue; ????????????} ????????} ????} }</int></float> |
?
(2)三種距離度量的代碼
?
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | // 歐式距離 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); } // 巴氏距離,? 需要除以總元素個(gè)個(gè)數(shù)? // 注意:在顏色直方圖的相似度比較中,巴氏距離效果最好 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; } |
?
測(cè)試圖片:
余弦結(jié)果:
巴氏距離結(jié)果:
其中【i-j】, i代表personi, j代表personi與person的漢明距離。并由結(jié)果可見(jiàn)phash對(duì)于圖片的旋轉(zhuǎn)肯定是無(wú)能為力的。
由結(jié)果可見(jiàn),針對(duì)person6,很相似,但余弦結(jié)果不好,而巴氏距離很好,此外巴氏距離對(duì)于原圖不是1,是因?yàn)橛?jì)算過(guò)程中的精度丟失造成的。
?
計(jì)算方式二:
(1)得到顏色直方圖
?
?| 1 2 3 4 5 6 7 8 9 10 11 | // 三維直方圖 方式二 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]] ++; ????????} ????} ????? }</vec3b></vec3b></vec3b> |
?
(2)三種距離度量的代碼
?
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | // 歐式距離 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); } // 巴氏距離,? 需要除以總元素個(gè)個(gè)數(shù)? // 注意:在顏色直方圖的相似度比較中,巴氏距離效果最好 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;??? // 因?yàn)檫@里有三個(gè) } |
?
余弦結(jié)果:
巴氏距離結(jié)果:
其中【i-j】, i代表personi, j代表personi與person的漢明距離。并由結(jié)果可見(jiàn)phash對(duì)于圖片的旋轉(zhuǎn)肯定是無(wú)能為力的。
?
總結(jié)
以上是生活随笔為你收集整理的相似图片搜索原理三(颜色直方图—c++实现)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: android中蓝牙的使用方法,Andr
- 下一篇: 计算机等级2级考试题库软件,XYZ计算机