图片识别——差异哈希算法 - 高飞网
2341 人阅读

图片识别——差异哈希算法

2017-07-28 02:09:46

    差异哈希算法(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;
    }

}


还没有评论!