1. 程式人生 > >感知雜湊演算法對比圖片相似度

感知雜湊演算法對比圖片相似度

package com.willson.common.utils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
/**
 * 比較兩張圖片的相似度
 * 感知雜湊演算法
 *
*/ public class ImageContrastUtil { // 對比方法 public static Double imageComparison(InputStream sampleInputStream,InputStream contrastInputStream ) throws IOException { //獲取灰度畫素的比較陣列 int[] photoArrayTwo = getPhotoArray(contrastInputStream); int[] photoArrayOne = getPhotoArray(sampleInputStream);
// 獲取兩個圖的漢明距離 int hammingDistance = getHammingDistance(photoArrayOne, photoArrayTwo); // 通過漢明距離計算相似度,取值範圍 [0.0, 1.0] double similarity = calSimilarity(hammingDistance); //返回相似精度 return similarity; } // 將任意Image型別影象轉換為BufferedImage型別,方便後續操作 public static BufferedImage convertToBufferedFrom(Image srcImage) { BufferedImage bufferedImage = new
BufferedImage(srcImage.getWidth(null), srcImage.getHeight(null), BufferedImage.TYPE_INT_ARGB); Graphics2D g = bufferedImage.createGraphics(); g.drawImage(srcImage, null, null); g.dispose(); return bufferedImage; } // 轉換至灰度圖 public static BufferedImage toGrayscale(Image image) { BufferedImage sourceBuffered = convertToBufferedFrom(image); ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY); ColorConvertOp op = new ColorConvertOp(cs, null); BufferedImage grayBuffered = op.filter(sourceBuffered, null); return grayBuffered; } // 縮放至32x32畫素縮圖 public static Image scale(Image image) { image = image.getScaledInstance(32, 32, Image.SCALE_SMOOTH); return image; } // 獲取畫素陣列 public static int[] getPixels(Image image) { int width = image.getWidth(null); int height = image.getHeight(null); int[] pixels = convertToBufferedFrom(image).getRGB(0, 0, width, height, null, 0, width); return pixels; } // 獲取灰度圖的平均畫素顏色值 public static int getAverageOfPixelArray(int[] pixels) { Color color; long sumRed = 0; for (int i = 0; i < pixels.length; i++) { color = new Color(pixels[i], true); sumRed += color.getRed(); } int averageRed = (int) (sumRed / pixels.length); return averageRed; } // 獲取灰度圖的畫素比較陣列(平均值的離差) public static int[] getPixelDeviateWeightsArray(int[] pixels, final int averageColor) { Color color; int[] dest = new int[pixels.length]; for (int i = 0; i < pixels.length; i++) { color = new Color(pixels[i], true); dest[i] = color.getRed() - averageColor > 0 ? 1 : 0; } return dest; } // 獲取兩個縮圖的平均畫素比較陣列的漢明距離(距離越大差異越大) public static int getHammingDistance(int[] a, int[] b) { int sum = 0; for (int i = 0; i < a.length; i++) { sum += a[i] == b[i] ? 0 : 1; } return sum; } //獲取灰度畫素的比較陣列 public static int[] getPhotoArray(InputStream inputStream) throws IOException { Image image = ImageIO.read(inputStream); // Image image = ImageIO.read(imageFile); // 轉換至灰度 image = toGrayscale(image); // 縮小成32x32的縮圖 image = scale(image); // 獲取灰度畫素陣列 int[] pixels = getPixels(image); // 獲取平均灰度顏色 int averageColor = getAverageOfPixelArray(pixels); // 獲取灰度畫素的比較陣列(即影象指紋序列) pixels = getPixelDeviateWeightsArray(pixels, averageColor); return pixels; } // 通過漢明距離計算相似度 public static double calSimilarity(int hammingDistance) { int length = 32 * 32; double similarity = (length - hammingDistance) / (double) length; // 使用指數曲線調整相似度結果 similarity = java.lang.Math.pow(similarity, 2); return similarity; } }