zoukankan      html  css  js  c++  java
  • java 识别图片相似度及图片是否相同

    1.比较MD5值 判断图片是否相同
    package com.zerdoor.util;

    import java.io.File;
    import java.io.FileInputStream;
    import java.math.BigInteger;
    import java.security.MessageDigest;
    import java.util.HashMap;
    import java.util.Map;
    public class FileDigest {
    /**
    * 获取单个文件的MD5值!
    * @param file
    * @return
    */
    public static String getFileMD5(File file) {
    if (!file.isFile()){
    return null;
    }
    MessageDigest digest = null;
    FileInputStream in=null;
    byte buffer[] = new byte[1024];
    int len;
    try {
    digest = MessageDigest.getInstance("MD5");
    in = new FileInputStream(file);
    while ((len = in.read(buffer, 0, 1024)) != -1) {
    digest.update(buffer, 0, len);
    }
    in.close();
    } catch (Exception e) {
    e.printStackTrace();
    return null;
    }
    BigInteger bigInt = new BigInteger(1, digest.digest());
    return bigInt.toString(16);
    }
     
    /**
    * 获取文件夹中文件的MD5值
    * @param file
    * @param listChild ;true递归子目录中的文件
    * @return
    */
    public static Map<String, String> getDirMD5(File file,boolean listChild) {
    if(!file.isDirectory()){
    return null;
    }
    //<filepath,md5>
    Map<String, String> map=new HashMap<String, String>();
    String md5;
    File files[]=file.listFiles();
    for(int i=0;i<files.length;i++){
    File f=files[i];
    if(f.isDirectory()&&listChild){
    map.putAll(getDirMD5(f, listChild));
    } else {
    md5=getFileMD5(f);
    if(md5!=null){
    map.put(f.getPath(), md5);
    }
    }
    }
    return map;
    }
     
     
    public static void main(String[] args) {
     
    File file1 = new File("F:\workspace_acg\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\acgweb\uploads\task\1495872495006.jpg");
    String s = file1.getPath();
    File file2 = new File("F:\workspace_acg\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\acgweb\uploads\task\1\20170527\1495872475363.jpg");
    System.out.println(getFileMD5(file1).equals(getFileMD5(file2)));
    System.out.println(s);
    }
    }
    2.比较每一个的图片的像素相似度(效率较低)
    package com.zerdoor.util;

    import javax.imageio.ImageIO;
    import java.awt.image.BufferedImage;

    import java.io.File;

    public class CompareImg {
    // 改变成二进制码
    public static String[][] getPX(String args) {
    int[] rgb = new int[3];
    File file = new File(args);
    BufferedImage bi = null;
    try {
    bi = ImageIO.read(file);
    } catch (Exception e) {
    e.printStackTrace();
    }
    int width = bi.getWidth();
    int height = bi.getHeight();
    int minx = bi.getMinX();
    int miny = bi.getMinY();
    String[][] list = new String[width][height];
    for (int i = minx; i < width; i++) {
    for (int j = miny; j < height; j++) {
    int pixel = bi.getRGB(i, j);
    rgb[0] = (pixel & 0xff0000) >> 16;
    rgb[1] = (pixel & 0xff00) >> 8;
    rgb[2] = (pixel & 0xff);
    list[i][j] = rgb[0] + "," + rgb[1] + "," + rgb[2];
    }
    }
    return list;
    }

    public static int compareImage(String imgPath1, String imgPath2) {
    String[] images = { imgPath1, imgPath2 };
    if (images.length == 0) {
    System.out.println("Usage >java BMPLoader ImageFile.bmp");
    System.exit(0);
    }
    // 分析图片相似度 begin
    String[][] list1 = getPX(images[0]);
    String[][] list2 = getPX(images[1]);
    int xiangsi = 0;
    int busi = 0;
    int i = 0, j = 0;
    for (String[] strings : list1) {
    if ((i + 1) == list1.length) {
    continue;
    }
    for (int m = 0; m < strings.length; m++) {
    try {
    String[] value1 = list1[i][j].toString().split(",");
    String[] value2 = list2[i][j].toString().split(",");
    int k = 0;
    for (int n = 0; n < value2.length; n++) {
    if (Math.abs(Integer.parseInt(value1[k]) - Integer.parseInt(value2[k])) < 5) {
    xiangsi++;
    } else {
    busi++;
    }
    }
    } catch (RuntimeException e) {
    continue;
    }
    j++;
    }
    i++;
    }
    list1 = getPX(images[1]);
    list2 = getPX(images[0]);
    i = 0;
    j = 0;
    for (String[] strings : list1) {
    if ((i + 1) == list1.length) {
    continue;
    }
    for (int m = 0; m < strings.length; m++) {
    try {
    String[] value1 = list1[i][j].toString().split(",");
    String[] value2 = list2[i][j].toString().split(",");
    int k = 0;
    for (int n = 0; n < value2.length; n++) {
    if (Math.abs(Integer.parseInt(value1[k]) - Integer.parseInt(value2[k])) < 5) {
    xiangsi++;
    } else {
    busi++;
    }
    }
    } catch (RuntimeException e) {
    continue;
    }
    j++;
    }
    i++;
    }
    String baifen = "";
    try {
    baifen = ((Double.parseDouble(xiangsi + "") / Double.parseDouble((busi + xiangsi) + "")) + "");
    baifen = baifen.substring(baifen.indexOf(".") + 1, baifen.indexOf(".") + 3);
    } catch (Exception e) {
    baifen = "0";
    }
    if (baifen.length() <= 0) {
    baifen = "0";
    }
    if (busi == 0) {
    baifen = "100";
    }
    System.out.println("相似像素数量:" + xiangsi + " 不相似像素数量:" + busi + " 相似率:" + Integer.parseInt(baifen) + "%");
    return Integer.parseInt(baifen);
    }

    public static void main(String[] args) {
    String file1 = "F:\workspace_acg\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\acgweb\uploads\task\1\20170526\1495780364826.png";
    String file2 = "F:\workspace_acg\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\acgweb\uploads\task\1495610591334.png";
    int compareImage = CompareImg.compareImage(file1, file2);
    System.out.println(compareImage);
    }

    }
    3.通过汉明距离计算相似度,取值范围 [0.0, 1.0]
    package com.zerdoor.util;

    import java.awt.Color;
    import java.awt.Graphics2D;
    import java.awt.Image;
    import java.awt.color.ColorSpace;
    import java.awt.image.BufferedImage;
    import java.awt.image.ColorConvertOp;
    import java.io.File;
    import java.io.IOException;

    import javax.imageio.ImageIO;

    public class ImgSimilarity{
    // 全流程
    public static void main(String[] args) throws IOException {
    // 获取图像
    File imageFile1 = new File("F:\workspace_acg\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\acgweb\uploads\task\1496212755337.jpg");
    File file2 = new File("F:\workspace_acg\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\acgweb\uploads\task\1496212755337.jpg");
    getSimilarity(imageFile1, file2);
    }

    public static double getSimilarity(File imageFile1, File file2) throws IOException {
    int[] pixels1 = getImgFinger(imageFile1);
    int[] pixels2 = getImgFinger(file2);
    // 获取两个图的汉明距离(假设另一个图也已经按上面步骤得到灰度比较数组)
    int hammingDistance = getHammingDistance(pixels1, pixels2);
    // 通过汉明距离计算相似度,取值范围 [0.0, 1.0]
    double similarity = calSimilarity(hammingDistance)*100;
    System.out.println("相似度:"+similarity+"%");
    return similarity;
    }

    private static int[] getImgFinger(File imageFile) throws IOException {
    Image image = ImageIO.read(imageFile);
    // 转换至灰度
    image = toGrayscale(image);
    // 缩小成32x32的缩略图
    image = scale(image);
    // 获取灰度像素数组
    int[] pixels1 = getPixels(image);
    // 获取平均灰度颜色
    int averageColor = getAverageOfPixelArray(pixels1);
    // 获取灰度像素的比较数组(即图像指纹序列)
    pixels1 = getPixelDeviateWeightsArray(pixels1, averageColor);
    return pixels1;
    }

    // 将任意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 double calSimilarity(int hammingDistance){
    int length = 32*32;
    double similarity = (length - hammingDistance) / (double) length;

    // 使用指数曲线调整相似度结果
    similarity = java.lang.Math.pow(similarity, 2);
    return similarity;
    }
    }
     
  • 相关阅读:
    css3 边框、背景、文本效果
    Java JDBC连接MYSQL数据库教程
    waf平台常用方法总结
    java比较两个日期大小
    js控制的弹出层
    js时间大小判断写法demo
    PL/SQL Developer技巧
    杀Oracle死锁进程方法
    查看oracle数据库的连接数以及用户
    Oracle分散问题记录
  • 原文地址:https://www.cnblogs.com/wwwcnblogscom/p/8341250.html
Copyright © 2011-2022 走看看