0

I have 2 main images and I want to compare a set of other images to them. What I do is computing the byte array of those two images and then compare those 2 with the current image being processed. This are the 2 main images:

File upper = new File("sweater.jpg");
byte [] upperPart = Files.readAllBytes(upper.toPath());
File lower = new File("pants.jpg");
byte [] lowerPart = Files.readAllBytes(lower.toPath());

Then in the loop where I treat all the images from a directory I do the following:

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";
}

However, computing the euclidean distance with the UpperImage works perfectly, comparing to the lowerImage does not work. The following error appears:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 55881
at org.apache.commons.io.ShapeRecognition.main(ShapeRecognition.java:54)

The image sizes are all the same, so I really dont understand why it works for upper and not for lower. Any hint? Thanks!

UPDATE so basically the problem is that the Byte Arrays generated are not the same size even if the images sizes are the same.

user3540466
  • 303
  • 1
  • 2
  • 13
  • 1
    Are all the images the same size? same size byte array? – GregA100k Mar 16 '15 at 13:50
  • All the images are the same size. The byte array are not, I took for granted that if the images where the same size, the byte arrays would also be the same size. – user3540466 Mar 16 '15 at 13:56

1 Answers1

3

The images may be the same size, regarding the resolution (e.g. they may both be 800x600 pixels). But you are not comparing the images, but the files. And... comparing images this way does not make sense, whatsoever. Two JPG files of images with size 800x600 may be 10 KB in size, or 50 KB. It depends on the image contents and the compression level.

What you (most likely...) want to do is to compare the pixels of the images. Therefore, you have to read the images with ImageIO, and decode the JPG files to obtain the actual pixel data.

You can read the images with

BufferedImage upper = ImageIO.read(new File("upper.jpg"));
BufferedImage lower = ImageIO.read(new File("lower.jpg"));

Then, to compare the images, you have to compute the differences of the pixels. This is not trivial. There is no common, universally applicable "distance measure" for pixels. One simple approach could be to iterate over the pixels of both images, and compute something like

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);

to obtain the differences in the red, green, blue and alpha channel, and add these differences together to obtain the value that you later compute the square root from.


A side note: You computed

differenceUpper  += (upperPart[i] - currentImage[i])^2;

But note that ^2 does NOT compute the power, as you might expect. You could either use Math.pow(difference, 2), but preferably something like

differenceSum += difference * difference;
Marco13
  • 53,703
  • 9
  • 80
  • 159
  • thanks! however this wont work for me since my images are black background and the shape is white. I am trying to build an algorithm to recognize pattern – user3540466 Mar 16 '15 at 14:05
  • @user3540466 Well, pattern recognition can be driven arbitrarily far. With the approach that I sketched here, you can compute "a" distance measure between two images (regardless of their contents). That's what you asked for. Sensibly applying this in your context (and diving into the topics of http://en.wikipedia.org/wiki/Computer_vision ) is beyond the scope of an answer to a focussed question. – Marco13 Mar 16 '15 at 16:15