日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

相似图片搜索原理三(颜色直方图—c++实现)

發布時間:2023/12/29 c/c++ 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 相似图片搜索原理三(颜色直方图—c++实现) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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

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

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

首先第一種就是對像素的每個通道都進行劃分,每個通道的最大像素值為255,可以等分8、16或者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]++;這樣就得到3個256維的一維向量,然后可以做疊加操作。

距離的度量

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

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

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

代碼:

計算方式一:

(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類型 ????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; ????????????} ????????} ????} }</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); } // 巴氏距離,? 需要除以總元素個個數? // 注意:在顏色直方圖的相似度比較中,巴氏距離效果最好 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代表personi與person的漢明距離。并由結果可見phash對于圖片的旋轉肯定是無能為力的。

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

?

計算方式二:

(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); } // 巴氏距離,? 需要除以總元素個個數? // 注意:在顏色直方圖的相似度比較中,巴氏距離效果最好 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代表personi與person的漢明距離。并由結果可見phash對于圖片的旋轉肯定是無能為力的。

?

總結

以上是生活随笔為你收集整理的相似图片搜索原理三(颜色直方图—c++实现)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。