圖片搜索之感知哈希算法

 
 TinEye是如何工作的呢?這裏面也許有十分複雜的原理。不過從結果看來,它使用了一種叫做“感知哈希算法(以下簡稱PHA)”的東西。
     PHA是一類比較哈希方法的統稱。圖片所包含的特徵被用來生成一組指紋(不過它不是唯一的),而這些指紋是可以進行比較的。
     PHA與加密哈希方法(以下簡稱CHA),如MD5、SHA1等,是不同的概念。CHA的哈希值是隨機的。用來生成哈希的數據的行爲就像隨機種子,所以相同的數據產生相同的結果,反之亦然。讀者可以如下做ruby測試:
     require 'digest/sha2'
     ......
     #生成加密後的散列值
     def self.encrypt(string)
       return Digest::SHA256.hexdigest(string)
     end
     我對這方面未做深層研究,如有錯誤,不吝賜教。此文的重點不是CHA,恕草草帶過。
    
     如果想要深入理解下文內容的話,不妨讀讀我在ftp裏的fourier相關文檔,會有所收穫。當然,不讀也不會造成大的影響。(ftp具體在文末有提及)

    對於圖片來說,高頻得到細節,低頻得到輪廓。所以小圖缺少細節,是低頻的。我先敘述一個阮一峯先生提及的最簡單PHA,在此表示感謝。大家可一睹爲快。

    感知哈希算法淺析

    

   第一步,縮小尺寸。

   最快速的去除高頻和細節,只保留結構明暗的方法就是縮小尺寸。

   將圖片縮小到8x8的尺寸,總共64個像素。摒棄不同尺寸、比例帶來的圖片差異。

    感知哈希算法淺析 

   第二步,簡化色彩。

   將縮小後的圖片,轉爲64級灰度。也就是說,所有像素點總共只有64種顏色。

   第三步,計算平均值。

   計算所有64個像素的灰度平均值。

   第四步,比較像素的灰度。

   算法的精髓,簡單、有趣,又充滿深意。

   將每個像素的灰度,與平均值進行比較。大於或等於平均值,記爲1;小於平均值,記爲0。

   第五步,計算哈希值。

   將上一步的比較結果,組合在一起,就構成了一個64位的整數,這就是這張圖片的指紋。組合的次序並不重要,只要保證所有圖片都採用同樣次序就行了(例如,自左到右、自頂向下、big-endian)。

    感知哈希算法淺析 = 8f373714acfcf4d0

   得到指紋以後,就可以對比不同的圖片,看看64位中有多少位是不一樣的。在理論上,這等同於計算Hammingdistance)。如果不相同的數據位不超過5,就說明兩張圖片很相似;如果大於10,就說明這是兩張不同的圖片。

    這個算法非常好,無論你改變圖片的高寬、亮度甚至顏色,都不會改變哈希值。最關鍵的是速度極快!cool!

    我在ftp裏放了這個算法的python版本(使用了PIL庫),如果讀者會ruby的話,不妨使用RMagick庫,同樣強大(文檔:http://www.imagemagick.org/RMagick/doc/項目:http://rubyforge.org/projects/rmagick/)

    有沒有更好的方法來判斷相似度呢?有,pHash。這種方法稍複雜寫,運用了DCT來降低頻度,比起平均值方法更精確了。DCT參見http://en.wikipedia.org/wiki/Discrete_cosine_transform
    下面來看它的過程。
    第一步,縮小尺寸。
               與平均值方法類似,不過要比8X8大些,32X32是個好尺寸,這樣做是爲了簡化DCT的計算,而不是降頻。

    第二步,簡化色彩。
               改成灰度圖,也是爲了減少DCT計算量。

    第三步,計算DCT。
               DCT將圖片分成了頻度和純量的集合。當JPEG使用8X8的DCT時,算法就使用32X32的DCT。

    第四步,降低DCT。
               當DCT是32X32時,只保留頂左的8X8,這部分代表了圖片的最低頻。這是神奇的一步。
    
    第五步,計算平均值。
               只用8X8的DCT低頻值,因爲DC係數和其他值相差很大,會破壞平均值。
 
    第六步,進一步縮小DCT
               將每個像素的灰度(64比特),與平均值進行比較。大於或等於平均值,記爲1;小於平均值,記爲0。圖片結構不變,結果就不會變。這完成了關鍵的一步。

    第七步,構造哈希。
  
發佈了21 篇原創文章 · 獲贊 3 · 訪問量 27萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章