這篇文章主要介紹了python實現圖像檢索的三種(直方圖/OpenCV/哈希法),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨着小編來一起學習學習吧
簡介:
本文介紹了圖像檢索的三種實現方式,均用python完成,其中前兩種基於直方圖比較,哈希法基於像素分佈。
檢索方式是:提前導入圖片庫作爲檢索範圍,給出待檢索的圖片,將其與圖片庫中的圖片進行比較,得出所有相似度後進行排序,從而檢索結果爲相似度由高到低的圖片。由於工程中還包含Qt界面類、觸發函數等其他部分,在該文檔中只給出關鍵函數的代碼。
開發系統:MacOS
實現方式:Qt + Python
方法一:自定義的直方圖比較算法
a) 基本思路
遍歷圖片像素點,提取R\G\B值並進行對應的計數,得到原始直方圖,但由於0-255的範圍太大,因此每一個像素值的統計量均偏小,因此分別將R\G\B的256個像素值映射到0-31共32個像素值上,將像素值範圍由256*3縮小到32*3。記錄像素值採用的數據結構爲一維數組,第1到32個值爲R的像素直方圖,第33到第64個值爲G的像素統計,第65到96個值爲B的像素統計。得到直方圖後,計算待檢索圖的直方圖和圖片庫中圖像的直方圖之間的相似性。
b) 具體實現
用到的函數:
- split_Img()
- calc_Hist(img)
- calc_Similar(h1,h2)
- calc_Similar_Split(h1,h2)
遍歷圖片的像素點以計算直方圖:calc_Hist(img)
嘗試了兩種方式,第一種是對圖像遍歷時逐個調用getpixel()來獲取R,G,B的值,但發現這種方式的速度太慢。第二種採用的是內存讀取,利用load()函數一次性讀取圖像的像素值,然後對像素值進行遍歷,該方法的速度比逐個提取更快。
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 41 42 43 44 45 46 47 48 49 50 |
|
直方圖比較 calc_Similar(h1,h2)
採用的公式是:
其中N爲顏色級數,Sim越靠近1則兩幅圖像的相似度越高。
c) 問題和改進
簡單實現直方圖比較後,檢索的結果並不好,和預期相比誤差較大。分析原因,直方圖比較主要依靠整幅圖像的色彩統計來進行比較,而對像素的位置並沒有很好的記錄,因此會造成誤判。
同時增加calc_Similar_Split(h1,h2)函數,加入分塊比較的部分,計算方法是:對每個小塊調用calc_Similar(h1,h2),累加計算結果,最後除以16取平均值。
測試發現效果顯著提升,基於顏色相似的同時保留了形狀信息。
函數如下:
1 2 3 4 5 6 7 8 9 10 |
|
#該函數用於統一圖片大小爲256*256,並且分割爲16個塊,返回值是16個局部圖像句柄的數組 def split_Img(img, size = (64,64)): img = img.resize((256,256)).convert('RGB') w,h = img.size sw,sh = size return [img.crop((i,j,i+sw,j+sh)).copy() for i in xrange(0,w,sw) for j in xrange(0,h,sh)] #計算兩個直方圖之間的相似度,h1和h2爲直方圖,zip表示同步遍歷 def calc_Similar(h1,h2): return sum(1 - (0 if g==s else float(abs(g-s))/max(g,s)) for g,s in zip(h1,h2)) / len(h1)
方法二:openCV庫的直方圖比較算法實現
openCV開源庫已經集成了直方圖提取、直方圖均衡化以及直方圖比較的功能,調用方便。爲了進一步瞭解直方圖比較的各類實現方法,利用openCV重新進行了實驗。
a) 基本思路
對圖片庫中每個圖片提取直方圖並均衡化,然後調用cv庫函數進行直方圖比較,結果進行排序,並顯示。
b) 具體實現
首先調用cv2.imread()讀取圖像,然後調用cv2.calcHist()計算直方圖,cv2.normalize()均衡化後進入比較階段,調用cv2.compareHist(),比較待檢索圖和圖片庫圖像之間的直方圖差異,然後調用DisplayTotalPics()進行顯示。
關鍵代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
c) 問題與解決
openCV中的compareHist函數中提供了4中比較方法:
1.相關係數標準(method=CV_COMP_CORREL) 值越大,相關度越高,最大值1,最小值0
2.卡方係數標準(method=CV_COMP_CHISQR) 值越小,相關度越高,無上限,最小值0
3.相交係數標準(method=CV_COMP_INTERSECT)值大,相關度越高,最大9.455319,最小0
4.巴氏係數的標準(method=CV_COMP_BHATTACHARYYA) 值小,相關度越高,最大值1,最小值0
測試後選擇的是method = cv2.cv.CV_COMP_INTERSECT
另外,該方法的速度很快,完全基於圖像的色彩分佈,但在一些情況下精度並不高。
方法三:平均哈希值比較算法實現
用到的函數:getKey(),getCode(),cmpCode()
a) 基本思路
平均哈希值的比較算法是基於像素分佈的,比較對象是灰度圖的圖像指紋。圖像指紋的計算通過比較每個圖的像素值和平均像素值來計算,然後計算圖像指紋之間的漢明距離,排序後得到相似圖像。
b) 具體實現
具體方法是:計算進行灰度處理後圖片的所有像素點的平均值,然後遍歷灰度圖片每一個像素,如果大於平均值記錄爲1,否則爲0,這一步通過定義函數getCode(img)完成。接着計算編碼之間的漢明距離,即一組二進制數據變爲另一組數據所需的步驟數,漢明距離越小,說明圖像指紋的相似度越高。計算漢明距離可以通過簡單的遍歷和計數來完成,函數爲compCode(code1,code2),其中code1和code2爲getCode得到的圖像指紋。
關鍵函數代碼如下:
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 |
|
c) 問題與優化
我們發現在數據量大時,該方法的檢索速度較慢,因此我們將圖像指紋也作爲圖像的屬性存在self.hashCode中,在importFolder時計算好,避免後續操作中的冗餘重複計算。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。