圖片哈希概述(image hash)

一切的起源都來自這篇文章:《相似圖片搜索的原理》,阮一峯大佬 11 年的這篇博客講述了 Google 以圖搜圖的原理,其中的獲取圖片 hash 值的方法就是 AHash。

每張圖片都可以通過某種算法得到一個 hash 值,稱爲圖片指紋,兩張指紋相近的圖片可以認爲是相似圖片。

以圖搜圖的原理就是獲取你上傳的圖片的指紋,和圖庫的圖片指紋對比,查找出最相似的若干張圖片展示。

除了以圖搜圖,圖片哈希還可以做什麼呢?例如圖片檢索,重複圖片剔除,圖片相似度比較等等。

這種哈希算法大概有 4 種:

  • 差值哈希:DHash(Difference Hash)
  • 均值哈希:AHash(Average Hash)
  • 感知哈希:PHash(Perceptual Hash)
  • 小波哈希:WHash(Wavelet Hash)

常用的是前面三種,DHash、AHash、PHash。其中 PHash 是增強版的 AHash。

圖片基本概念

圖片是由像素點矩陣組成的,信息可保存在數組中,如下圖 4*4 的圖片,可保存在二維數組中:
在這裏插入圖片描述
左上角爲起始點

row 表示行,對應圖片的高 height,y 方向

col 表示列,對應圖片的寬 width,x 方向

四種 Hash 算法的步驟

差值哈希

梯度散列

  1. 縮小尺寸,建議 9*8(col = row + 1)
  2. 灰度化
  3. 計算灰度差值(做差變爲 8*8 的矩陣)
  4. 計算哈希值

均值哈希

平均散列

  1. 縮小尺寸,建議 8*8
  2. 灰度化
  3. 計算平均值
  4. 比較像素的灰度
  5. 計算哈希值

感知哈希

核心:離散餘弦變換(DCT)

  1. 縮小尺寸,建議 32*32
  2. 灰度化
  3. 進行離散餘弦變換(DCT)
  4. 取左上角的 8*8 的大小
  5. 計算平均值
  6. 比較像素的灰度
  7. 計算哈希值

小波哈希

核心:離散小波變換(DWT),和感知哈希步驟相同,只是將步驟 DCT 換爲 DWT

  1. 縮小尺寸,建議 32*32
  2. 灰度化
  3. 進行離散小波變換(DWT)
  4. 取左上角的 8*8 的大小
  5. 計算平均值
  6. 比較像素的灰度
  7. 計算哈希值

步驟講解

縮小尺寸

比較兩張完全相同的圖片是否相同的做好方法是什麼?

記這張圖片的像素點個數爲 m,逐個像素點比較,不同像素點記爲 n = 0,每有一個不同則+1,最後(n/m)*100則爲兩張圖片的相似度。

如果兩張圖片是 1000 * 1000 的呢?

那將對比一百萬次。太耗時了。因此要減少對比次數,那麼就要減少像素點個數。基於抽樣檢測的原理,壓縮圖片就是首要要做的工作了。將 1000 * 1000 的圖片壓縮到 8 * 8 的大小,那麼只需對比 64 次即可。

灰度化

如果對比的兩張圖片,第二種是經過第一張圖片轉換過來的,比如由 png 轉爲了 jpg 造成了色值失真,或傳輸過程中其他原因造成了色值失真,怎麼辦呢?

答案是進行灰度化。一個像素點是有 ARGB 組成的:A透明度、R紅色、G綠色、B藍色。每個色度分爲 0~255 一共 256 個色階,一般情況下除以 4,將色階縮小到 64 位,通過這一步處理後,彩色圖片基本上會變成黑白灰三種顏色,所以叫灰度化。

灰度化可以縮小色值失真帶來的影響。比如紅色是 200,失真後是 160,差值爲 40;灰度後變爲 50 - 40 = 10,差值變小了,計算 hash 時相似度會提升。

中間步驟

每種哈希算法的差異就在中間的通過何種策略獲取 64 位二進制數據,之後的文章我們再詳細講解。

計算哈希值

這一步沒有太多技術含量,經過不同算法前面的幾步運算,會得到一個 64 位的二進制數組,將數組轉爲 16 進制就是計算哈希值。

ps:很多博客中講到圖片相似都提到"漢明距離",5以內表示圖片相似,大於10則表示兩張圖片不同。但有的比較的是 64 位的二進制串,有的比較的是 16 位的十六進制串,度量方式不同結果可能大相徑庭。

比如:

0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
1111 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000

上面兩個字符串的漢明距離是 12,兩張圖肯定不相似。

但如果轉爲十六進制:

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
f f f 0 0 0 0 0 0 0 0 0 0 0 0 0

上面兩個字符串的漢明距離是 3,表示兩個圖片相似。

經過測試:應該比較 64 位的二進制字符串,纔是準確的。

本文原創發佈於公衆號 習習立 ,關注公衆號回覆 hash 獲取源碼。

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