我有2个主要图像,我想将一组其他图像与它们进行比较。 我所做的是计算这两个图像的字节数组,然后将这些图像与正在处理的当前图像进行比较。这是两个主要图像:
File upper = new File("sweater.jpg");
byte [] upperPart = Files.readAllBytes(upper.toPath());
File lower = new File("pants.jpg");
byte [] lowerPart = Files.readAllBytes(lower.toPath());
然后在我处理目录中所有图像的循环中,我执行以下操作:
byte [] currentImage = Files.readAllBytes(f.toPath());
float differenceUpper = 0;
float differenceLower = 0;
for (int i=0;i< currentImage.length;i++) {
differenceUpper += (upperPart[i] - currentImage[i])^2;
differenceLower += (lowerPart[i] - currentImage[i])^2;
}
float euclideanDistanceUpper = (float) Math.sqrt(differenceUpper);
float euclideanDistanceLower = (float) Math.sqrt(differenceLower);
if (euclideanDistanceUpper < euclideanDistanceLower){
filename = filename + "Upper";
} else {
filename = filename + "Lower";
}
然而,使用UpperImage计算欧氏距离非常有效,与lowerImage相比无法正常工作。出现以下错误:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 55881
at org.apache.commons.io.ShapeRecognition.main(ShapeRecognition.java:54)
图像尺寸都是一样的,所以我真的不明白为什么它适用于鞋面而不是较低的。任何提示?谢谢!
UPDATE 基本上问题是,即使图像大小相同,生成的字节数组也不一样。
答案 0 :(得分:3)
关于分辨率,图像的大小可能相同(例如,它们可能都是800x600像素)。但您不是在比较图像,而是文件。并且......以这种方式比较图像无论如何都没有意义。尺寸为800x600的两个JPG文件大小可能是10 KB,或50 KB。这取决于图像内容和压缩级别。
您(最有可能......)想要做的是比较图像的像素。因此,您必须使用ImageIO
读取图像,并使用解码 JPG文件来获取实际的像素数据。
您可以使用
阅读图像BufferedImage upper = ImageIO.read(new File("upper.jpg"));
BufferedImage lower = ImageIO.read(new File("lower.jpg"));
然后,要比较图像,您必须计算像素的差异。这不是微不足道的。像素没有通用的,普遍适用的“距离测量”。一种简单的方法可能是迭代两个图像的像素,并计算像
这样的东西int argb0 = image0.getRGB(x, y);
int argb1 = image1.getRGB(x, y);
int a0 = (argb0 >> 24) & 0xFF;
int r0 = (argb0 >> 16) & 0xFF;
int g0 = (argb0 >> 8) & 0xFF;
int b0 = (argb0 ) & 0xFF;
int a1 = (argb1 >> 24) & 0xFF;
int r1 = (argb1 >> 16) & 0xFF;
int g1 = (argb1 >> 8) & 0xFF;
int b1 = (argb1 ) & 0xFF;
int aDiff = Math.abs(a1 - a0);
int rDiff = Math.abs(r1 - r0);
int gDiff = Math.abs(g1 - g0);
int bDiff = Math.abs(b1 - b0);
获取红色,绿色,蓝色和Alpha通道的差异,并将这些差异加在一起以获得稍后计算平方根的值。
附注:你计算了
differenceUpper += (upperPart[i] - currentImage[i])^2;
但请注意^2
NOT 计算功率,正如您所料。您可以使用Math.pow(difference, 2)
,但最好使用
differenceSum += difference * difference;