赞
踩
搜索方法是计算出每一个图片的特征值,然后进行对比。目前的搜索速度较慢,之后可以加入线程池等使搜索速度得到极大的提升,欢迎大家指点。
~~~
~~~
~~~
递归得到文件
public static ArrayList<File> getallfile(File file, ArrayList<File> allfilelist) {
if (file.exists()) {
// 判断文件是否是文件夹,如果是,开始递归
if (file.isDirectory()) {
File f[] = file.listFiles();
for (File file2 : f) {
getallfile(file2, allfilelist);
}
} else {
allfilelist.add(file);
}
}
return allfilelist;
}
~~~
将图片路径放入队列
public Vector<String> getFileByDirectory(String filepath, String endFileName) { File file = new File(filepath); ArrayList<File> files = new ArrayList<File>(); // 拿到所有文件 ArrayList<File> allFiles = getallfile(file, files); Vector<String> imagePathArray=new Vector<String>(); for (int i = 0; i < allFiles.size(); i++) { if (allFiles.get(i).getName().endsWith(endFileName)) {// 筛选特定的文件 String icon=allFiles.get(i).getAbsolutePath(); imagePathArray.add(icon); } } return imagePathArray; }
将图片缩小到8x8的尺寸,总共64个像素。这一步的作用是去除图片的细节,只保留结构、明暗等基本信息,摒弃不同尺寸、比例带来的图片差异。
public static BufferedImage thumb(BufferedImage source, int width, int height, boolean b) { //返回此 ColorSpace 的颜色空间类型 int type = source.getType(); BufferedImage target = null; //计算缩小倍数 sx=8/原宽度 sy=8/原高度 double sx = (double) width / source.getWidth(); double sy = (double) height / source.getHeight(); // 没有识别出图像类型,因此它必定是一个自定义图像。需要做处理 if (type == BufferedImage.TYPE_CUSTOM) { ColorModel cm = source.getColorModel(); WritableRaster raster = cm.createCompatibleWritableRaster(width, height); boolean alphaPremultiplied = cm.isAlphaPremultiplied(); target = new BufferedImage(cm, raster, alphaPremultiplied, null); } else target = new BufferedImage(width, height, type); Graphics2D g = target.createGraphics(); g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); //从图像空间到用户空间的转换。 g.drawRenderedImage(source, AffineTransform.getScaleInstance(sx, sy)); g.dispose(); return target; }
/将缩小后的图片,转为64级灰度。转换以后,所有像素点总共只有64种颜色。之后比较灰度,做出色彩标记。
灰度转换
int[] pixels = new int[width * height]; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { pixels[i * height + j] = ImageHelper.rgbToGray(thumb.getRGB(i, j)); } } /** * 灰度转化 * @param pixels 原数组 * @return */ public static int rgbToGray(int pixels) { // int _alpha = (pixels >> 24) & 0xFF; int _red = (pixels >> 16) & 0xFF; int _green = (pixels >> 8) & 0xFF; int _blue = (pixels) & 0xFF; return (int) (0.3 * _red + 0.59 * _green + 0.11 * _blue); }
计算所有64个像素的灰度平均值。
// 计算所有64个像素的灰度平均值。
int avgPixel = ImageHelper.average(pixels);
public static int average(int[] pixels) {
float m = 0;
for (int i = 0; i < pixels.length; ++i) {
m += pixels[i];
}
m = m / pixels.length;
return (int) m;
}
标记颜色
将每个像素的灰度,与平均值进行比较。大于或等于平均值,记为1;小于平均值,记为0。
int[] comps = new int[width * height];
for (int i = 0; i < comps.length; i++) {
if (pixels[i] >= avgPixel) {
comps[i] = 1;
} else {
comps[i] = 0;
}
}
将上一步的比较结果,组合在一起,就构成了一个64位的整数,这就是这张图片的指纹。
StringBuffer hashCode = new StringBuffer();
for (int i = 0; i < comps.length; i+= 4) {
int result = comps[i] * (int) Math.pow(2, 3) + comps[i + 1] * (int) Math.pow(2, 2) + comps[i + 2] * (int) Math.pow(2, 1) + comps[i + 2];
hashCode.append(binaryToHex(result));
}
/** * 计算"汉明距离"(Hamming distance)。 * 如果不相同的数据位不超过5,就说明两张图片很相似;如果大于10,就说明这是两张不同的图片。(总共64位) * @param sourceHashCode 源hashCode * @param hashCode 与之比较的hashCode */ public static int hammingDistance(String sourceHashCode, String hashCode) { int difference = 0; int len = sourceHashCode.length(); for (int i = 0; i < len; i++) { if (sourceHashCode.charAt(i) != hashCode.charAt(i)) { difference ++; } } return difference; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。