计算图像相似度——《Python也可以》之一(转)
聲明:本文最初發(fā)表于賴勇浩(戀花蝶)的博客http://blog.csdn.net/lanphaday,如蒙轉(zhuǎn)載,敬請(qǐng)確保全文完整,未經(jīng)同意,不得用于商業(yè)用途。
?
關(guān)于《Python也可以》系列:這是我打算把這幾年里做的一些實(shí)驗(yàn)和代碼寫(xiě)出來(lái),涉及的面比較廣,也比較雜,可能會(huì)有圖像處理、檢索等方面的內(nèi)容,也會(huì)有中文分詞、文本分類、拼音、糾錯(cuò)等內(nèi)容。毫不掩飾地說(shuō):在博客發(fā)這系列文章的原因在于宣傳?python?,所以這系列文章都會(huì)帶有源碼和相關(guān)的測(cè)試用例,這也是特色之一。但這系列文章都是“淺嘗輒止”的,不會(huì)深入到專屬領(lǐng)域,只是為了表明?python?功能很強(qiáng)大,不僅適合于web?或者game?開(kāi)發(fā),也適合于科學(xué)研究。
?
?
要計(jì)算圖像的相似度,肯定是要找出圖像的特征。這樣跟你描述一個(gè)人的面貌:國(guó)字臉,濃眉,雙眼皮,直鼻梁,大而厚的嘴唇。Ok,這些特征決定了這個(gè)人跟你的同事、朋友、家人是不是有點(diǎn)像。圖像也一樣,要計(jì)算相似度,必須抽象出一些特征比如藍(lán)天白云綠草。常用的圖像特征有顏色特征、紋理特征、形狀特征和空間關(guān)系特征等。顏色特征的算是最常用的,在其中又分為直方圖、顏色集、顏色矩、聚合向量和相關(guān)圖等。直方圖能夠描述一幅圖像中顏色的全局分布,而且容易理解和實(shí)現(xiàn),所以入門級(jí)的圖像相似度計(jì)算都是使用它的;作為一篇示例性的“淺嘗輒止”的文章,我們也不例外。
在進(jìn)行我們?cè)囼?yàn)之前,我們需要找到一批圖片來(lái)作為測(cè)試用例。我上窮碧落下黃泉,最后終于在我的前同事西門的博客(http://blog.163.com/johnal1?)找到了一系列他在公司組織的年度旅游時(shí)去西藏林芝拍的一組風(fēng)光圖片(http://blog.163.com/johnal1/blog/static/9394912200812105654784?),實(shí)在是難得之佳品,簡(jiǎn)直可以說(shuō)得到了它們我們的實(shí)驗(yàn)已經(jīng)完成了90%。哦耶!下面來(lái)看一下我們最重要的一組照片(兩張):
?
?
?
找到一組很好的測(cè)試圖片之后,我們需要再給?Python?環(huán)境安裝一個(gè)圖像庫(kù),我的選擇是PIL(Python image library)。PIL?為?Python?提供了圖像處理功能,并且支持?jǐn)?shù)十種圖像格式。(關(guān)于?PIL?的介紹,可以查看我之前的文章《用Python做圖像處理》http://blog.csdn.net/lanphaday/archive/2007/10/28/1852726.aspx?)
雖然這兩張圖片大小都是一樣的,但為了通用性,我們有必要把所有的圖片都統(tǒng)一到特別的規(guī)格,在這里我選擇是的256x256的分辨率。
??????
因?yàn)?PIL?為?RGB?模式的圖像計(jì)算的?histogram?樣點(diǎn)數(shù)為?768,計(jì)算量并不算太大,所以本文就直接使用,沒(méi)有再作降維處理了。
??6 def make_regalur_image(img, size = (256, 256)):
??7?????return img.resize(size).convert('RGB')
轉(zhuǎn)化為規(guī)則圖像之后,可以調(diào)用?img.histogram()?方法獲得直方圖數(shù)據(jù),如上文兩圖的直方圖如下:
?
?
得到規(guī)則圖像之后,圖像的相似度計(jì)算就轉(zhuǎn)化為直方圖的距離計(jì)算了,本文依照如下公式進(jìn)行直方圖相似度的定量度量:
Sim(G,S)=,其中G,S為直方圖,N?為顏色空間樣點(diǎn)數(shù)
轉(zhuǎn)換為相應(yīng)的?Python?代碼如下:
?19 def hist_similar(lh, rh):
?20?????assert len(lh) == len(rh)
?21?????return sum(1 - (0 if l == r else float(abs(l - r))/max(l, r)) for l, r in zip(lh, rh))/len(lh)
?22????
?23 def calc_similar(li, ri):
?24?????return hist_similar(li.histogram(), ri.histogram())
短短十行代碼不到就完成了圖片相似度的計(jì)算,再加上從硬盤(pán)讀取圖像的函數(shù)和測(cè)試代碼,也不過(guò)二十行上下:
?28 def calc_similar_by_path(lf, rf):
?29?????li, ri = make_regalur_image(Image.open(lf)), make_regalur_image(Image.open(rf))
?30?????return calc_similar(li, ri)
?31????
?32 if __name__ == '__main__':
?33?????path = r'test/TEST%d/%d.JPG'
?34?????for i in xrange(1, 7):
?35????????print 'test_case_%d: %.3f%%'%(i, calc_similar_by_path('test/TEST%d/%d.JPG'%(i, 1), 'test/TEST%d/%d.JPG'%(i, 2))*100)
那么這樣做的效果到底怎么樣呢?且來(lái)看看測(cè)試結(jié)果(測(cè)試用例和代碼請(qǐng)猛擊這里下載):
test_case_1: 63.322%
test_case_2: 66.950%
test_case_3: 51.990%
test_case_4: 70.401%
test_case_5: 32.755%
test_case_6: 42.203%
結(jié)合我們?nèi)庋蹖?duì)測(cè)試用例的觀察,這個(gè)程序工作得還算可以。不過(guò)?test_case_4?就暴露了直方圖的缺點(diǎn):它只是圖像中顏色的全局分布的描述,無(wú)法描述顏色的局部分布和色彩所處的位置。test_case_4?的規(guī)則圖如下:
?????
可以看到它們的色彩局部分布有相當(dāng)大的不同,但事實(shí)上它們的全局直方圖相當(dāng)相似:
?
雖然從直方圖來(lái)看兩圖是極其相似的,但上述算法計(jì)算出相似度為70.4%的結(jié)果肯定是不可接受的。那么,怎么樣才能克服直方圖的缺點(diǎn)呢?答案是把規(guī)則圖像分塊,再對(duì)相應(yīng)的小塊進(jìn)行相似度計(jì)算,最后根據(jù)各小塊的平均相似度來(lái)反映整個(gè)圖片的相似度。在實(shí)驗(yàn)中,我們把規(guī)則圖像分為?4x4?塊,每塊的分辨率為?64x64:
?
?
分割圖像的代碼為:
??9 def split_image(img, part_size = (64, 64)):
?10?????w, h = img.size
?11?????pw, ph = part_size
?12
?13?????assert w % pw == h % ph == 0
?14
?15?????return [img.crop((i, j, i+pw, j+ph)).copy() /
?16?????????????????for i in xrange(0, w, pw) /
?17?????????????????for j in xrange(0, h, ph)]
相應(yīng)地,把計(jì)算相似圖的函數(shù)calc_similar()修改為:
?23 def calc_similar(li, ri):
?24 #???return hist_similar(li.histogram(), ri.histogram())
?25?????return sum(hist_similar(l.histogram(), r.histogram()) for l, r in zip(split_image(li), split_image(ri))) / 16.0
進(jìn)行這樣的改進(jìn)后,算法已經(jīng)能夠在一定的程序上反映色彩的局倍分布和顏色所處的位置,可以比較好的彌補(bǔ)全局直方圖算法的不足。新的算法計(jì)算出來(lái)的結(jié)果如下:
test_case_1: 56.273%
test_case_2: 54.925%
test_case_3: 49.326%
test_case_4: 40.254%
test_case_5: 30.776%
test_case_6: 39.460%
可以看到,test_case_4的相似度由?70.4%?下降到?40.25%,基本上跟肉眼的判斷是切合的;另外其它圖像的相似度略有下降,這是因?yàn)榧尤肓宋恢靡蜃又挠绊憽亩梢?jiàn)基于分塊的直方圖相似算法是簡(jiǎn)單有效的。
???????圖像的相似度計(jì)算是圖像檢索、識(shí)別的基礎(chǔ),本文只是淺嘗輒止地介紹了其中最基本的計(jì)算方法,如果你要學(xué)習(xí)和研究更好的算法,也請(qǐng)記住?Python?也能幫助你哦~
?
本實(shí)驗(yàn)的所有代碼和測(cè)試用例請(qǐng)猛擊這里下載,再次感謝提供圖片支持的西門同學(xué)。
?
有問(wèn)題不明白?請(qǐng)教Google大神吧!| ? | ? | ||
| ? |
|
轉(zhuǎn)載于:https://www.cnblogs.com/qq78292959/archive/2013/03/22/2976239.html
總結(jié)
以上是生活随笔為你收集整理的计算图像相似度——《Python也可以》之一(转)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Android常用代码(类似工具类吧)
- 下一篇: 20130327 jQuery easy