圖片識別——差異哈希算法

    差異哈希算法(Different Hash Algorithms,dHash),像aHash和pHash一樣,dHash易於實現,相比於它的簡單,其實它的識別更爲準確。作爲一種感知算法的實現,dHash比aHash相近,但比aHash效果更好。aHash關注於平均值,pHash關注頻率模式,dHash則基於漸變。下面介紹下dHash算法的工作原理。

算法步驟

  1. 縮小尺寸。最快速去掉高頻和細節的辦法就是縮小民族教育。在這裏,收縮到9*8的大小,以便它有72的像素點(之後會解釋爲什麼這樣)。通過忽略尺寸和縱橫比,不管圖片如何伸縮,該hash都能匹配相似的圖片。
  2. 簡化色彩。轉化爲灰度圖。把縮放後的圖片轉化爲256階的灰度圖。將72個像素轉變爲72個顏色(爲達到最佳效果,可以在縮放尺寸前簡化色彩,或者縮放和簡化色彩同時進行)
  3. 計算差異值。dHash算法工作在相鄰像素之間,這標識了相對的漸變方向。這樣每行9個像素之間產生了8個不同的差異,一共8行,則產生了64個差異值。
  4. 獲取指紋。如果左邊的像素比右邊的更亮,則記錄爲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;
    }

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