近日逛博客的時(shí)候偶然發(fā)現(xiàn)了一個(gè)有關(guān)圖片相似度的Python算法實(shí)現(xiàn)。想著很有意思便搬到C#上來(lái)了,給大家看看。
閑言碎語(yǔ)
才疏學(xué)淺,只把計(jì)算圖像相似度的一個(gè)基本算法的基本實(shí)現(xiàn)方式給羅列了出來(lái),以至于在最后自己測(cè)評(píng)的時(shí)候也大發(fā)感慨,這個(gè)算法有點(diǎn)不靠譜。不管怎么樣,這個(gè)算法有時(shí)候還是有用的,所以還是列出來(lái)跟大家伙一起分享分享~~powered by 25175.net
PS:圖像處理這一塊博大精深,個(gè)人偶爾發(fā)現(xiàn)了點(diǎn)東西拿來(lái)分享。說(shuō)的不好的地方,寫(xiě)得太糟的地方,諸位準(zhǔn)備扔磚頭還望淡定,淡定~~
基本知識(shí)介紹
顏色直方圖
顏色直方圖是在許多圖像檢索系統(tǒng)中被廣泛采用的顏色特征,它所描述的是不同色彩在整幅圖像中所占的比例,而并不關(guān)心每種色彩所處的空間位置,即無(wú)法描述圖像中的對(duì)象或物體。顏色直方圖特別適用于描述那些難以進(jìn)行自動(dòng)分割的圖像。
灰度直方圖
灰度直方圖是灰度級(jí)的函數(shù),它表示圖像中具有每種灰度級(jí)的像素的個(gè)數(shù),反映圖像中每種灰度出現(xiàn)的頻率;叶戎狈綀D的橫坐標(biāo)是灰度級(jí),縱坐標(biāo)是該灰度級(jí)出現(xiàn)的頻率,是圖像的最基本的統(tǒng)計(jì)特征。
本文中即是使用灰度直方圖來(lái)計(jì)算圖片相似度,關(guān)于算法那一塊也不贅言了,畢竟圖像學(xué)圖形學(xué),直方圖我是門(mén)兒都不懂,我也不準(zhǔn)備打腫臉充胖子,只想實(shí)現(xiàn)一個(gè)最基本的算法,然后從最直觀的角度看看這個(gè)算法的有效性,僅此而已。
算法實(shí)現(xiàn)
諸位看官休怪筆者囫圇吞棗,淺嘗輒止的學(xué)習(xí)態(tài)度。額畢竟是因興趣而來(lái),于此方面并無(wú)半點(diǎn)基礎(chǔ)(當(dāng)然,除了知道RGB是啥玩意兒——這還幸虧當(dāng)年計(jì)算機(jī)圖形學(xué)的老師是個(gè)Super美女,因此多上了幾節(jié)課的緣故),更談不上半點(diǎn)造詣,看官莫怪莫怪,且忍住怒氣,是走是留,小生不敢有半點(diǎn)阻攔~~
大致步驟如下:
1, 將圖像轉(zhuǎn)換成相同大小,以有利于計(jì)算出相像的直方圖來(lái)
2, 計(jì)算轉(zhuǎn)化后的灰度直方圖
3, 利用XX公式,得到直方圖相似度的定量度量
4, 輸出這些不知道有用沒(méi)用的相似度結(jié)果數(shù)據(jù)
代碼實(shí)現(xiàn)
步驟1,將圖像轉(zhuǎn)化成相同大小,我們暫且轉(zhuǎn)化成256 X 256吧。
public Bitmap Resize(string imageFile, string newImageFile)
{
img = Image.FromFile(imageFile);
Bitmap imgOutput = new Bitmap(img, 256, 256);
imgOutput.Save(newImageFile, System.Drawing.Imaging.ImageFormat.Jpeg);
imgOutput.Dispose();
return (Bitmap)Image.FromFile(newImageFile);
}
這部分代碼很好懂,imageFile為原始圖片的完整路徑,newImageFile為強(qiáng)轉(zhuǎn)大小后的256 X 256圖片的路徑,為了“賽”后可以看到我們轉(zhuǎn)化出來(lái)的圖片長(zhǎng)啥樣,所以我就把它保存到了本地了,以至于有了上面略顯丑陋的代碼。
步驟2,計(jì)算圖像的直方圖
public int[] GetHisogram(Bitmap img)
{
BitmapData data = img.LockBits( new System.Drawing.Rectangle( 0 , 0 , img.Width , img.Height ), ImageLockMode.ReadWrite , PixelFormat.Format24bppRgb );
int[ ] histogram = new int[ 256 ];
unsafe
{
byte* ptr = ( byte* )data.Scan0;
int remain = data.Stride - data.Width * 3;
for( int i = 0 ; i < histogram.Length ; i ++ )
histogram[ i ] = 0;
for( int i = 0 ; i < data.Height ; i ++ )
{
for( int j = 0 ; j < data.Width ; j ++ )
{
int mean = ptr[ 0 ] + ptr[ 1 ] + ptr[ 2 ];
mean /= 3;
histogram[ mean ] ++;
ptr += 3;
}
ptr += remain;
}
}