1. 程式人生 > >圖片相似度判斷-差異值雜湊演算法JAVA版

圖片相似度判斷-差異值雜湊演算法JAVA版

差異值雜湊演算法(dHash)

  1. 圖片縮放為9*8大小
  2. 將圖片灰度化
  3. 差異值計算(每行相鄰畫素的差值,這樣會生成8*8的差值,前一個畫素大於後一個畫素則為1,否則為0)
  4. 生成雜湊值
package com.example.demo.hello;
 
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
 
/**
 * 差異雜湊演算法
 */
public class DHashUtil {
    /**
     * 計算dHash方法
     *
     * @param file 檔案
     * @return hash
     */
    private static String getDHash(File file) {
        //讀取檔案
        BufferedImage srcImage;
        try {
            srcImage = ImageIO.read(file);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
 
        //檔案轉成9*8畫素,為演算法比較通用的長寬
        BufferedImage buffImg = new BufferedImage(9, 8, BufferedImage.TYPE_INT_RGB);
        buffImg.getGraphics().drawImage(srcImage.getScaledInstance(9, 8, Image.SCALE_SMOOTH), 0, 0, null);
 
        int width = buffImg.getWidth();
        int height = buffImg.getHeight();
        int[][] grayPix = new int[width][height];
        StringBuffer figure = new StringBuffer();
 
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                //圖片灰度化
                int rgb = buffImg.getRGB(x, y);
                int r = rgb >> 16 & 0xff;
                int g = rgb >> 8 & 0xff;
                int b = rgb & 0xff;
                int gray = (r * 30 + g * 59 + b * 11) / 100;
                grayPix[x][y] = gray;
 
                //開始計算dHash 總共有9*8畫素 每行相對有8個差異值 總共有 8*8=64 個
                if(x != 0) {
                    long bit = grayPix[x-1][y] > grayPix[x][y] ? 1 : 0;
                    figure.append(bit);
                }
            }
        }
 
        return figure.toString();
    }
 
    /**
     * 計算海明距離
     * <p>
     * 原本用於編碼的檢錯和糾錯的一個演算法
     * 現在拿來計算相似度,如果差異值小於一定閾值則相似,一般經驗值小於5為同一張圖片
     *
     * @param str1
     * @param str2
     * @return 距離
     */
    private static long getHammingDistance(String str1, String str2) {
        int distance;
        if (str1 == null || str2 == null || str1.length() != str2.length()) {
            distance = -1;
        } else {
            distance = 0;
            for (int i = 0; i < str1.length(); i++) {
                if (str1.charAt(i) != str2.charAt(i)) {
                    distance++;
                }
            }
        }
        return distance;
    }
 
    //DHashUtil 引數值為待處理資料夾
    public static void main(String[] args) {
        File file1 = new File("xxx//1.jpg");
        File file2 = new File("xxx//2.jpg");
 
        System.out.println("圖片1hash值:"+getDHash(file1));
        System.out.println("圖片2hash值:"+getDHash(file2));
        System.out.println("海明距離為:"+getHammingDistance(getDHash(file1),getDHash(file2)));
 
    }
}