Search code examples
linuximagecolorsdiffdifference

Image diff preserving color for overlaying


I have two almost identical images, in color. I want to generate a transparent image that could be overlayed on the first image to make it look like the 2nd. All the image diff tools I've been able to find won't preserve color the way I need. Any ideas? (preferably Linux command-line)

diff a These are the test images I'm currently working with. diff b Ideally the result would be something like this, but accurate to the difference. (this one can't add the shadow, and had to be rendered separately) suboptimal test


Solution

  • You can do that with ImageMagick at the command-line as follows. I will show you the steps I took and why so that you can diverge from my answer at any point and hopefully get the exact result you want.

    Here's my initial attempt:

    magick compare 1.jpg 2.jpg result.png
    

    enter image description here

    That's a start, but unfortunately you have used JPEG so there are ugly blocking artefacts all over the place, let's remove them with some fuzz - ideally though, you would use a lossless PNG rather than a JPG:

    magick compare -fuzz 10% 1.jpg 2.jpg result.png
    

    enter image description here

    Now we can see two new problems - ImageMagick has kindly left the original image in reduced saturation as a reference for us and the differences have been coloured in solid red. So we want to remove the original background image and change the highlight and lowlight colours to white and black to make a change mask:

    magick compare -fuzz 10% 1.jpg 2.jpg -compose Src -highlight-color white -lowlight-color black mask.png
    

    enter image description here

    If we now take that mask and introduce it to the original image as a transparency layer, everything else will become transparent:

    magick 1.jpg mask.png -compose CopyOpacity -composite result.png
    

    enter image description here


    By the way, you could make that into a one-liner obviating the need for an intermediate file on disk like this:

    magick compare -fuzz 10% 1.jpg 2.jpg -compose Src -highlight-color white -lowlight-color black png: | magick 1.jpg - -compose CopyOpacity -composite result.png
    

    The first magick generates the mask as a PNG onto its stdout. The second magick reads the mask from its stdin and puts that into 1.jpg as the alpha channel: