圖片識別——三種哈希算法性能與準確度比較

    前面幾篇文章對圖片的三種哈希算法做了簡單的介紹:均值哈希算法感知哈希算法差異哈希算法。本篇將對上面算法做一個總結。並對在性能方面做些對比。

性能和準確度

   目前有個超過150,000張圖片的實驗,有幾張已知出現次數的待查找測試圖片。比如一張圖片(針)在150,000張圖片(草堆)中出現一次,另外一張出現兩次,第三張測試圖片出現了32次。

    分別使用aHash、pHash、dHash三種算法在這一“草堆”查找一隻“針”。爲了作比較,沒有預先緩存圖片庫中的任何哈希值。比較值(漢明距離)10以內的就認爲是匹配。下面就是實現結果:

  1. 不計算哈希。這是一個比較的基線。程序把每張圖片加載到內存中,之後一張張的卸載。這將告訴我們僅僅是文件訪問和加載要花費多長時間(所有的圖片在NFS模式的文件系統中加載--當然還有網絡請求)。總時間是16分鐘。沒有任何圖片比較,僅僅是加載完這些圖片,要耗去16分鐘。
  2. 不計算哈希,但縮小尺寸。上面討論的所有算法都是從縮小圖片尺寸開始的。小圖縮放非常快,但是大圖會花費10秒甚至更長時間。僅僅是加載和縮小這150,000張圖,耗了3.75小時(真的有必要研究一種方法來優化圖片縮放算法)。
  3. aHash算法。該算法花費了3.75小時來執行。換句話說,加載和縮放圖片比算法本身要花費更多時間。但不幸的是,aHash算法出現了大量的誤報。它去匹配所有期望的圖片,但出現了幾十位的誤報。比如說,測試圖片應該匹配32次,實現上卻匹配了400張圖片。更壞的是,這些圖片中,有些差別位數竟然不到2位。總之,aHash算法是一種快速,但不準確的算法。
  4. pHash算法。該算法在準確性表現最好的。沒有誤報,沒有漏報,每次匹配的距離值都在2以內。我確信更大的數據集(或修改測試圖片)可能會產生誤判斷。但是漏報錯誤數量會大大小於aHash。
    毫無疑問,pHash的問題就是性能方面。它花費了7小時才完成。這是因爲DCT比較有大量的操作,包括餘弦變換。如果預先計算好DCT的數值,將會至少減少1-2小時的比較時間。總之,pHash算法準確,但不夠快。
  5. dHash算法。絕對令人驚歎!非常小的誤報。比如,已知有兩個匹配的圖片,最後得出結果是6個匹配(4個誤報)。數值爲10,0,8,10,0和10,兩個0的是正確的匹配,所有誤報匹配都是高的數值。而速度方面,dHash和aHash差不多。從技術層面來講,它的速度快是因爲不需要計算顏色均值。dHash算法有着aHash算法的速度,和非常小的誤報率。

算法變種

    我已經試驗了幾種dHash算法的變種。比如,最初設想的是用一個8*8的圖片幷包含最後一個比較(比較p[0]與p[7]之間的不同),這確實比現在9*8的變體要差一些,不過差一點點。

    你可以使用結合dHash的性能加上pHahs的準確性。比如在用dHash比較得到匹配後,再用pHash去比較。

    最後,我意識到用dHash作爲一種快速的過濾器是不錯的選擇。但可能不需要使用64位來比較。試想可以用6*4大小的圖片來生成16位的dHash。這會產生20個不同值(每行6個像素產生5個不同值,共4行)。忽略四個角落產生16位hash。忽略的好處是像Instagram類似的光暈的影響。如果有1百萬圖片,那麼每個16位的dHash會包含15個圖片(因爲有hash碰撞)。然後用pHash去比較15個圖片依然非常快的。如果有十億張圖片,會有15,258張圖片的碰撞,但依然還是非常小的數量級。

    我甚至可以讓16位dHash變得稀疏,允許任何一位的變化都算匹配。任何可能的16位dHash計算將產生17個可能的dHash值匹配,百萬圖片將產生260個碰撞。10億圖片會生產260000碰撞,10億的圖片,同時存儲16位dHash、64位dHash和64位pHash值是值得的。

應用比較

    從感知哈希算法中我們要考慮兩個事情:速度和準確性。把dHash與pHash結合起來,我們將兩者兼得。但是即使沒有pHash,dHash相對於aHash依然是非常大的提升,並且沒有任何性能損失。

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章