Search code examples
javaimagecolorssimilarity

Compare images for similarity using java


I want to check similarity in between 2 images: enter image description here to enter image description here

Using code below, I get Difference Percentage-->8.132336061764388. First I resize images to be on the same size and then use the compare method.

I was expect to have small if not none similarity. What is not correct in the similarity check? Is there other precise method?

public static void compare(BufferedImage imgA, BufferedImage imgB) {
// Assigning dimensions to image
int width1 = imgA.getWidth();
int width2 = imgB.getWidth();
int height1 = imgA.getHeight();
int height2 = imgB.getHeight();

// Checking whether the images are of same size or
// not
if ((width1 != width2) || (height1 != height2))

  // Display message straightaway
  System.out.println("Error: Images dimensions mismatch");
else {

  long difference = 0;

  // treating images likely 2D matrix

  // Outer loop for rows(height)
  for (int y = 0; y < height1; y++) {

    // Inner loop for columns(width)
    for (int x = 0; x < width1; x++) {

      int rgbA = imgA.getRGB(x, y);
      int rgbB = imgB.getRGB(x, y);
      int redA = (rgbA >> 16) & 0xff;
      int greenA = (rgbA >> 8) & 0xff;
      int blueA = (rgbA) & 0xff;
      int redB = (rgbB >> 16) & 0xff;
      int greenB = (rgbB >> 8) & 0xff;
      int blueB = (rgbB) & 0xff;

      difference += Math.abs(redA - redB);
      difference += Math.abs(greenA - greenB);
      difference += Math.abs(blueA - blueB);
    }
  }

  double total_pixels = width1 * height1 * 3;

  double avg_different_pixels
          = difference / total_pixels;

  double percentage
          = (avg_different_pixels / 255) * 100;

  // Lastly print the difference percentage
  System.out.println("Difference Percentage-->"
          + percentage);
}

}


Solution

  • Well, first of all, we, humans do not even agree to what "similar" is: is it just the same shape? or even the same color but different markers? aesthetically identical but with different circuitry inside?

    Having said that, for computer vision, things are way more complex. Similarly, in computer vision there are plenty of ways to tell if something is similar "at a certain degree": histograms, corners, edges, features, etc...

    Have a look at Checking images for similarity with OpenCV for an introduction on the topic.

    In your case, the number you obtain for "similarity" is just purely based on the exact pixel representation, and therefore is sensible to scaling the image. Furthermore, keep in mind that scaling an image is a transformation that alters the pixel composition. In particular, you are adding/removing pixels with certain algorithms in such a way some high level features of the image are preserved at a certain extent.

    If you want to detect the similarity within two images, you have to first decide what is similar to you, then you can use a combination of multiple techniques to achieve your result. OpenCV provides a good and solid starting base.