圖像類似度中的Hash算法

本博客中使用的代碼見本文末尾php

       度量兩張圖片的類似度有許多算法,本文講介紹工程領域中最經常使用的圖片類似度算法之一——Hash算法。Hash算法準確的說有三種,分別爲平均哈希算法(aHash)、感知哈希算法你(pHash)和差別哈哈希算法(dHash)。html

       三種Hash算法都是經過獲取圖片的hash值,再比較兩張圖片hash值的漢明距離(韓明距離的概念可見本公衆號《》一文)來度量兩張圖片是否類似。兩張圖片越類似,那麼兩張圖片的hash數的漢明距離越小。下面本文將分別介紹這三種Hash算法。git

1 平均哈希算法(aHash)

1.1 算法步驟

       平均哈希算法是三種Hash算法中最簡單的一種,它經過下面幾個步驟來得到圖片的Hash值,這幾個步驟分別是(1) 縮放圖片;(2)轉灰度圖; (3) 算像素均值;(4)根據類似均值計算指紋。具體算法以下所示:github

表1 aHash獲得圖片Hash值地算法
步驟 具體內容
縮放圖片 輸入圖片大小尺寸各異,爲了統一圖片的輸入,統一將圖片尺寸縮放爲8*8,一共獲得了64個像素點。
轉灰度圖 輸入圖片有些爲單通道灰度圖,有些RGB三通道彩色圖,有些爲RGBA四通道彩色圖。也爲了統一下一步輸入標準,將非單通道圖片都轉爲單通道灰度圖。 其中RGB三通道轉單通道算法有下面幾種:
1.浮點算法:Gray=R0.3+G0.59+B0.11
2.整數方法:Gray=(R
30+G59+B11)/100
3.移位方法:Gray =(R76+G151+B*28)>>8;
4.平均值法:Gray=(R+G+B)/3;
5.僅取綠色:Gray=G;
算像素均值 經過上一步可得一個8x8的整數矩陣G,計算這個矩陣中全部元素的平均值,假設其值爲a
據像素均值計算指紋 初始化輸入圖片的ahash = ""
從左到右一行一行地遍歷矩陣G每個像素若是第i行j列元素G(i,j) >= a,則ahash += "1"若是第i行j列元素G(i,j) <a, 則ahash += "0"

       獲得圖片的ahash值後,比較兩張圖片ahash值的漢明距離,一般認爲漢明距離小於10的一組圖片爲類似圖片。算法

1.2 具體實例

       本文圖片爲Lena圖來講明.學習


圖1 Lena(Origin)圖

圖2 轉爲8x8尺寸的Lena圖

圖3 轉爲灰度8x8尺寸的Lena圖

       其中轉爲8x8尺寸的Lena對應的數據矩陣爲:測試


       很容獲得如上矩陣全部元素的均值a= 121.328125, 將上述矩陣中大於或等於a的元素置爲1, 小於a的元素置爲0,可得:google


       因此可得Lena圖的aHash爲3d

       1011111010011110100111011010100110101011101000110000111000101100code

       將二進制形式ahash轉十六進制hash爲

       be9e9da9aba30e2c

       爲了測試aHash算法的效果,咱們用一張帶噪聲Lena(noise)圖和與Lena不同的Barbara作圖片類似度對比實驗,其中Lena(noise)和Barbara以下:


圖4 Lena(noise)圖

圖5 Barbara圖

       經過aHash算法容易得三個圖片的hash值,而後根據hanming距離計算Lena(origin).png和Lena(noise).png Barbar.png之間漢明距離,具體以下:


圖6 aHash算法圖片類似度實驗

       由上圖可見aHash能區別類似圖片和差別大的圖片。

2 感知哈希算法(pHash)

2.1 算法步驟

       感知哈希算法是三種Hash算法中較爲複雜的一種,它是基於DCT(離散餘弦變換)來獲得圖片的hash值,其算法幾個步驟分別是(1) 縮放圖片;(2)轉灰度圖; (3) 計算DCT;(4)縮小DCT; (5)算平均值;(6) 計算指紋。具體算法以下所示:

表2 pHash獲得圖片Hash值地算法
步驟 具體內容
縮放圖片 統一將圖片尺寸縮放爲32*32,一共獲得了1024個像素點。
轉灰度圖 統一下一步輸入標準,將非單通道圖片都轉爲單通道灰度圖。
計算DCT 計算32x32數據矩陣的離散餘弦變換後對應的32x32數據矩陣
縮小DCT 取上一步獲得32x32數據矩陣左上角8x8子區域
算平均值 經過上一步可得一個8x8的整數矩陣G, 計算這個矩陣中全部元素的平均值,假設其值爲a
計算指紋 初始化輸入圖片的phash = ""
從左到右一行一行地遍歷矩陣G每個像素
若是第i行j列元素G(i,j) >= a,則phash += "1"
若是第i行j列元素G(i,j) <a, 則phash += "0"

       獲得圖片的phash值後,比較兩張圖片phash值的漢明距離,一般認爲漢明距離小於10的一組圖片爲類似圖片。

2.2 具體實例

       仍用Lena圖來講明.


圖7 轉爲灰度32x32尺寸的Lena圖

圖8 灰度32x32尺寸Lena圖對應的DCT矩陣

       經過計算可得灰度32x32Lenna圖對應的DCT矩陣左上角8x8區域子矩陣爲:


       很容獲得如上矩陣全部元素的均值a= 77.35, 將上述矩陣中大於或等於a的元素置爲1, 小於a的元素置爲0,可得:


       因此可得Lena圖的pHash爲

       1001100111000100010101000010010101100000001000111000001010000000

       將二進制形式phash轉十六進制hash爲

       99c4542560238280

       爲了測試pHash算法的效果,一樣用一張帶噪聲Lena(noise)圖和與Lena不同的Barbara作圖片類似度對比實驗。經過pHash算法容易得三個圖片的hash值,而後根據hanming距離計算Lena(origin).png和Lena(noise).png Barbar.png之間漢明距離,具體以下:


圖9 pHash算法圖片類似度實驗

       由上圖可見pHash能區別類似圖片和差別大的圖片。

3 差別哈希算法(dHash)

3.1 算法步驟

       相比pHash,dHash的速度要快的多,相比aHash,dHash在效率幾乎相同的狀況下的效果要更好,它是基於漸變實現的。其算法幾個步驟分別是(1) 縮放圖片;(2)轉灰度圖; (3) 計算DCT;
(4)縮小DCT; (5)算平均值;(6) 計算指紋。具體算法以下所示:

表3 dHash獲得圖片Hash值地算法
步驟 具體內容
小圖片 統一將圖片尺寸縮放爲9x8,一共獲得了72個像素點
轉灰度圖 統一下一步輸入標準,將非單通道圖片都轉爲單通道灰度圖。
算差別值 當前行像素值-前一行像素值, 從第二到第九行共8行,又由於矩陣有8列,因此獲得一個8x8差分矩陣G
算平均值 經過上一步可得一個8x8的整數矩陣G, 計算這個矩陣中全部元素的平均值,假設其值爲a
計算指紋 初始化輸入圖片的dhash = ""
從左到右一行一行地遍歷矩陣G每個像素
若是第i行j列元素G(i,j) >= a,則dhash += "1"
若是第i行j列元素G(i,j) <a, 則dhash += "0"

       獲得圖片的phash值後,比較兩張圖片phash值的漢明距離,一般認爲漢明距離小於10的一組圖片爲類似圖片。

3.2 具體實例

       仍用Lena圖來講明.


圖7 轉爲灰度9x8尺寸的Lena圖

       經過計算可得灰度9x8Lenna圖數據矩陣爲:


       從第二行開始進行減去前一行操做,可得以下查分矩陣


       將上述矩陣中大於或等於0元素置爲1, 小於a的元素置爲0,可得:


       因此可得Lena圖的dHash爲

       0101100000110111111010000101001001101011101011110001010001010000

       將二進制形式dhash轉十六進制hash爲

       99c4542560238280

       爲了測試dHash算法的效果,一樣用一張帶噪聲Lena(noise)圖和與Lena不同的Barbara作圖片類似度對比實驗。經過pHash算法容易得三個圖片的hash值,而後根據hanming距離計算Lena(origin).png和Lena(noise).png Barbar.png之間漢明距離,具體以下:


圖9 dHash算法圖片類似度實驗

       由上圖可見dHash能區別類似圖片和差別大的圖片。

總結

       關於圖像類似度算法除了Hash算法,在傳統算法領域中還有基於SIFT的匹配算法,基於Gist特徵的匹配算法;在深度學習領域中有基於ResNet全鏈接的匹配算法。感興趣的讀者能夠經過google來了解這些算法。

參考資料

432-Looks-Like-It
529-Kind-of-Like-That

本文代碼

Github代碼

相關文章
相關標籤/搜索