java 识别图片相似度及图片是否相同

摘要:
importjava.io.FileInputStream;intlen;len);returnnull;returnbigInt.toString(16);file.isDirectory()){returnnull;i<Strings=file1.getPath();Filefile=newFile(args);
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;
}
}
 

免责声明:文章转载自《java 识别图片相似度及图片是否相同》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇UOS怎么安装Filezilla(转)对Oracle导出文件错误和DMP文件结构的分析,EXP-00008: 遇到 ORACLE 错误 904 ORA-00904: "MAXSIZE": invalid identifier下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

C#:MapControl基本操作代码整理

整理了 MapConrol各基本功能的实现代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Windows.Forms; using ESRI.ArcGI...

将日期转换为指定的格式:比如转换成 年月日时分秒 这种格式:yyyy-MM-dd hh:mm:ss 或者 yyyy-MM-dd。总结下。

可以为Date原型添加如下的方法: Date.prototype.format = function(fmt) { var o = { "M+" : this.getMonth()+1, //月份 "d+" : this.getDate(),...

C++11多线程编程系列-相关库函数使用

1、C++11 新标准中引入了多个头文件来支持多线程编程,分别是<atomic>,<thread>,<mutex>,<condition_variable>和<future>。 <atomic>:该头文主要声明了两个类, std::atomic 和 std::atomic_flag,另...

Java 处理 Exception 的 9 个最佳实践!

在Java中处理异常并不是一个简单的事情。 不仅仅初学者很难理解,即使一些有经验的开发者也需要花费很多时间来思考如何处理异常,包括需要处理哪些异常,怎样处理等等。 这也是绝大多数开发团队都会制定一些规则来规范对异常的处理的原因。而团队之间的这些规范往往是截然不同的。 本文给出几个被很多团队使用的异常处理最佳实践。 1. 在Finally块中清理资源或者使用...

SpringBoot操作ES进行各种高级查询

SpringBoot整合ES 创建SpringBoot项目,导入 ES 6.2.1 的 RestClient 依赖和 ES 依赖。在项目中直接引用 es-starter 的话会报容器初始化异常错误,导致项目无法启动。如果有读者解决了这个问题,欢迎留言交流 <!-- ES 客户端 --> <dependency> <gr...

android中的内部存储与外部存储

我们先来考虑这样一个问题: 打开手机设置,选择应用管理,选择任意一个App,然后你会看到两个按钮,一个是清除缓存,另一个是清除数据,那么当我们点击清除缓存的时候清除的是哪里的数据?当我们点击清除数据的时候又是清除的哪里的数据?读完本文相信你会有答案。 在android开发中我们常常听到这样几个概念,内存,内部存储,外部存储,很多人常常将这三个东西搞混,那么...