计算2字节数组java的欧氏距离

时间:2015-03-16 13:45:38

标签: java bytearray euclidean-distance

我有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 基本上问题是,即使图像大小相同,生成的字节数组也不一样。

1 个答案:

答案 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;