1. Advertising
    y u no do it?

    Advertising (learn more)

    Advertise virtually anything here, with CPM banner ads, CPM email ads and CPC contextual links. You can target relevant areas of the site and show ads based on geographical location of the user if you wish.

    Starts at just $1 per CPM or $0.10 per CPC.

Picture Comparison Code Not Working Properly

Discussion in 'Programming' started by Rabee Taha, Jul 23, 2021.

  1. #1
    I am still very much a beginner in programming and am facing a problem with a Java code. I would be very thankful for suggestions and comments. The problem is as following:

    I found a Java code online that is designed to compare two pictures and highlight the differences between them. However, the way the code works is by using a loop that compares the RGB value of each pixel of the two pictures and highlights it in a certain color if the value is equal. This however results in a problem that even the slightest shift in camera angle or lighting conditions between the two pictures leads to a different RGB value of the pixels making the code highlight them as a difference even though the pictures are mostly identical. The code is written below and i have added the link to photos showing examples of the outcome of the code. What would you suggest i change in the code? Thank you for your help in advance.

    The code:

    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;

    import javax.imageio.ImageIO;
    public class PictureOverlayTest {
    /*
    * Four variables, three for the wanted BufferedImages, one String for the
    * Path of the third Image, which does not already exist.
    */

    private BufferedImage image1;
    private BufferedImage image2;
    private BufferedImage image3;

    private String pathImage3;

    public PictureOverlayTest(String filePathAndName1, String filePathAndName2,
    String filePathAndName3) throws IOException {
    /*
    * Constructor in order to keep this method reusable and clean. Needs
    * three Strings. The paths and Filenames of all three images. Image 1
    * and 2 should exist already, Image 3 will be created if all
    * requirements are met. Constructor creates the first two buffered
    * images, sets all needed variables and starts the checkAndCompare()
    * method
    */

    File file = new File(filePathAndName1);
    this.image1 = ImageIO.read(file);

    file = new File(filePathAndName2);
    this.image2 = ImageIO.read(file);

    this.pathImage3 = filePathAndName3;
    checkAndCompare();
    }

    private void checkAndCompare() throws IOException {
    /*
    * This function creates the Color blue, compares the sizes of both
    * pictures and if they are the same, creates a third image. Then it
    * loops through the two images and compares each pixel. If the pixels
    * are the same, the third image gets a blue pixel at that point
    */

    Color blue = Color.blue;
    Color yellow = Color.yellow;

    if (image1.getHeight() == image2.getHeight()
    && image1.getWidth() == image2.getWidth()) {

    image3 = new BufferedImage(image1.getWidth(), image1.getHeight(),
    image1.getType());
    for (int y = 0; y < image1.getHeight(); y++) {
    for (int x = 0; x < image1.getWidth(); x++) {

    int colorImage1 = image1.getRGB(x, y);
    int colorImage2 = image2.getRGB(x, y);

    if (colorImage1 == colorImage2) {

    image3.setRGB(x, y, blue.getRGB());

    } else {
    image3.setRGB(x, y, yellow.getRGB());
    // Whatever Color you want. By default it is black.

    }

    }
    }
    savePicture3();
    System.out.println("Message: Image comparison is done");

    } else {

    System.out.println("Error: Image dimensions do not match");

    }

    }

    private void savePicture3() throws IOException {
    /*
    * This method saves the created Image into a file onto your computer.
    * The if() statement is used to check if the file was successfully
    * created, in order to avoid unwanted errors. Keep in mind, that you
    * have to change the "bmp" in ImageIO.write() to whatever format you
    * actually want
    */

    File file = new File(pathImage3);
    if (file.createNewFile()) {
    ImageIO.write(image3, "bmp", file);
    }
    }

    }

    import java.io.IOException;

    public class Main {

    public static void main(String[] args) {
    // TODO Auto-generated method stub

    try {
    PictureOverlayTest test = new PictureOverlayTest(
    "C:\\Users\\Rabee Taha\\Desktop\\Java Test Pics\\test1.png",
    "C:\\Users\\Rabee Taha\\Desktop\\Java Test Pics\\test2.png",
    "C:\\Users\\Rabee Taha\\Desktop\\Java Test Pics\\test3.png");
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }

    }



    Here is the link to example images of the outcome ( https://postimg.cc/gallery/rkXfPr7 )
     
    Rabee Taha, Jul 23, 2021 IP
  2. c1lonewolf

    c1lonewolf Member

    Messages:
    57
    Likes Received:
    21
    Best Answers:
    1
    Trophy Points:
    33
    #2
    "code is designed to compare two pictures and highlight the differences between them...the code works is by using a loop that compares the RGB value of each pixel of the two pictures and highlights it in a certain color if the value is equal. This however results in a problem that even the slightest shift in camera angle or lighting conditions between the two pictures leads to a different RGB value of the pixels making the code highlight them as a different even though the pictures are mostly identical."

    The code is doing exactly what it's supposed to. Slight change in camera angle or lighting from one image to another shows the images are different. It seems that the script is meant to keep you from uploading multiple copies of the same image by comparing dimensions and pixel coloring.

    In order for the script to do what you're wanting would involve a lot more complex computing.
     
    c1lonewolf, Jul 23, 2021 IP
  3. sarahk

    sarahk iTamer Staff

    Messages:
    28,500
    Likes Received:
    4,460
    Best Answers:
    123
    Trophy Points:
    665
    #3
    I'd suggest using some of Google's image tools. There must be something in there that compares photos and allows for minor differences.
     
    sarahk, Jul 23, 2021 IP
  4. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #4
    Rather than making a binary output, I would suggest doing greyscale of the differences between the two... a heatmap as it were. You could then apply ... have you ever used a CB / Ham radio? They have a thing called "squelch" which is a cutoff of signal strength designed to cut out noise. Basically you could set a threshold of how much change occurs. An 8 bit greyscale or even 10 bit RG heatmap would/could be far more useful, and by losing a few bits automatically give you a lot of difference reduction being thrown in the trash.

    Java's not my bag -- been a decade and a half since I wrote anything serious in it -- but the logic would go something like this:

    final int
    	greyBitDepth = 8, // max reliable is 31 bits
    	greySHR = 31 - greyBitDepth,
    	squelch = 16, // ignore differences of 16 or less
    	width = image1.getWidth(),
    	height = image1.getHeight();
    
    for (int y = 0; y < height; y++) {
    	for (int x = 0; x < width; x++) {
    
    		int
    			pixel1_temp = image1.getRGB(x, y),
    			pixel2_temp = image2.getRGB(x, y),
    			diff = Math.max(squelch, (
    				Math.abs(
    					(pixel1_temp & 0xFF) - (pixel2_temp & 0xFF)
    				) * 489626272 +
    				Math.abs(
    					((pixel1_temp >>= 8) &0xFF) - ((pixel2_temp >>= 8) & 0xFF)
    				) * 2521145802 +
    				Math.abs(
    					((pixel1_temp >>= 8) &0xFF) - ((pixel2_temp >>= 8) & 0xFF)
    				) * 1284195221
    			) >> greySHR);
    			/*
    				The multiplies above are the Luma component of YCrCb converted to
    				0..0x7FFFFFFF, allowing us to avoid expensive floating point divides
    				and multiplies.
    			*/
    		
    		Color grey = new Color(diff, diff, diff);
    		image3.setRGB(x, y, grey.getRGB());
    		
    	}
    }
    Code (markup):
    Mind you, guessing wildly, it's been years... but that would replace your inner loop to give you the greyscale of the differences with squelch.

    A more robust version might do resolution downscaling of the source images with a bit of blur, to account for slight camera movements. Likewise more than one frame might be sampled for changes over time so things like daylight over time is ignored / squelched out. Though at that point one might have to go into working with complex AI to really get that working right.
     
    deathshadow, Jul 29, 2021 IP
    sarahk likes this.