差異哈希算法(Different Hash Algorithms,dHash),像aHash和pHash一樣,dHash易於實現,相比於它的簡單,其實它的識別更爲準確。作爲一種感知算法的實現,dHash比aHash相近,但比aHash效果更好。aHash關注於平均值,pHash關注頻率模式,dHash則基於漸變。下面介紹下dHash算法的工作原理。
算法步驟
- 縮小尺寸。最快速去掉高頻和細節的辦法就是縮小民族教育。在這裏,收縮到9*8的大小,以便它有72的像素點(之後會解釋爲什麼這樣)。通過忽略尺寸和縱橫比,不管圖片如何伸縮,該hash都能匹配相似的圖片。
- 簡化色彩。轉化爲灰度圖。把縮放後的圖片轉化爲256階的灰度圖。將72個像素轉變爲72個顏色(爲達到最佳效果,可以在縮放尺寸前簡化色彩,或者縮放和簡化色彩同時進行)
- 計算差異值。dHash算法工作在相鄰像素之間,這標識了相對的漸變方向。這樣每行9個像素之間產生了8個不同的差異,一共8行,則產生了64個差異值。
- 獲取指紋。如果左邊的像素比右邊的更亮,則記錄爲1,否則爲0(這裏用1代表p[x]<p[x+1],設置位從左及右,從上及下的大邊)
==3a6c6565498da525
與aHash算法比較,這種算法產生的hash值,將不會隨圖片的縮放和縱橫比的改變而改變,增強或減小亮度或對比度,或者修改顏色也不會對hash值產生顯著的影響。即使對伽馬校正和顏色配置做複雜的調整,也不會影響結果。最好的一點是:速度快!!!嚴格來說——最慢的地方是縮小尺寸那一步。
該hash值代表了亮度的梯度變化。比較兩個hash值,只要看看不相同的位數個數即可(即漢明距離)。如果比較結果爲0表明是一個非常相似的圖片。大於10表明是不同的圖片,如果介於1到10之間則暗示有一定的修改。
java實現
/** * 差異哈希算法/Difference hash algorithm/HA * <p> * 最適用於縮略圖,放大圖搜索 * <p> * 相比pHash,dHash的速度要快的多<br> * 相比aHash,dHash在效率幾乎相同的情況下的效果要更好,它是<b>基於漸變</b>實現的。 * <p> * * @author xuyanhua * @data Jan 10, 2017 1:09:46 AM */ public class DHash { /** * 圖片指紋 * * @param imagePath * @return * @throws IOException */ public static long fingerprint(String imagePath) throws IOException { File file = new File(imagePath); BufferedImage srcImage = ImageIO.read(file); srcImage = ImageUtil.trim(srcImage); ImageIO.write(srcImage, "jpg", new File("c:/imagetest/trim/2/"+file.getName())); /* * 1.縮小尺寸. 收縮到9*8的大小,一遍它有72的像素點 */ BufferedImage image9x8 = ImageUtil.resize(srcImage, 9, 8); /* * 2.簡化色彩,轉化爲灰度圖. 把縮放後的圖片轉化爲256階的灰度圖 */ int width = image9x8.getWidth(); int height = image9x8.getHeight(); int[] grayPix = new int[width * height]; int i = 0; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int rgb = image9x8.getRGB(x, y); int r = rgb >> 16 & 0xff; int g = rgb >> 8 & 0xff; int b = rgb >> 0 & 0xff; int gray = (r * 30 + g * 59 + b * 11) / 100; grayPix[i++] = gray; } } /* * 4.計算差異值:dHash算法工作在相鄰像素之間,這樣每行9個像素之間產生了8個不同的差異,一共8行,則產生了64個差異值. * 5.獲取指紋.如果左邊的像素比右邊的更亮,則記錄爲1,否則爲0. */ long figure = 0; for (i = 0; i < 63; i++) { long b = grayPix[i] > grayPix[i + 1] ? 1 : 0; figure |= b << i; } return figure; } }