215

How can I get the difference between two images? I have the original image. Someone has written on an exact duplicate of the original image. Now, I need to compare the original to the written on image and extract just the writing in image format.

Example: I have a picture of a house. Someone took a copy and wrote “Hello!” on the copy. I want to somehow compare the two pictures, remove the house, and be left with an image of the words “Hello!”.

Is this possible with ImageMagick? I know there are ways to get the statistical difference between images, but that is not what I am looking for.

MvG
  • 57,380
  • 22
  • 148
  • 276
Justin Noel
  • 5,945
  • 10
  • 44
  • 59
  • 8
    Try [this section](http://www.imagemagick.org/Usage/compare/) of the ImageMagick usage guide! – Benoit Feb 27 '11 at 10:48
  • 1
    I know this question is about ImageMagick, but I just had to include a link to [Resemble.js](http://huddle.github.io/Resemble.js/) for the "causual" searcher who may be after an agnostic solution. – brichins Jul 30 '15 at 21:40
  • Does anyone know of a tool that will compare 2 images by subtracting the pixels of the second image, from the first? I'd prefer not writing my own. – MarcusJ Dec 10 '15 at 16:43
  • Imagemagick 7 has perceptual hash, a technique using invariant image moments. it's nice in the sense that it hashes the same even after rotation, barrel distortion, resize, gamma change, noise introduction, watermarking... – v.oddou Jan 17 '18 at 08:37
  • related: https://askubuntu.com/questions/209517/does-diff-exist-for-images – Ciro Santilli OurBigBook.com Nov 30 '18 at 15:09
  • @v.oddou, I tried IM7 perceptual hash on two images, one image is simple translation of another (size, orientation, colorspace, and shape remained the same). The command is `/compare -metric phash Image1.png Image2.png null:`. PHash was different. I compared with a different image and PHash different in similar amount. I didn't test with rotation, distortion, resize, and other transformations, because it did not produce what you claimed with a simpler transformation. Am I doing something wrong? – BReddy May 15 '20 at 15:08
  • @BReddy I have no idea, I never used it. I just repeated the claims of the research papers and imagemagick documents. I'm not surprised that it doesn't work in practice, it's a classic to pretend something incredible and then it flops. – v.oddou May 19 '20 at 02:16
  • 1
    @v.oddou, Thanks. I read docs and did few more tests. It appears to perform badly with line drawings which are very sparsely populated and extremely low pixel density. Looks like pixel density is the key in PHASH identifying similarity. – BReddy May 20 '20 at 15:32

3 Answers3

372

My own favorites are these two:

 compare image1 image2 -compose src diff.png
 compare image1 image2 -compose src diff.pdf

The only difference between the 2 commands above: the first one shows the visual difference between the two images as a PNG file, the second one as a PDF.

The resulting diff file displays all pixels which are different in red color. The ones which are unchanged appear white.

Short and sweet.

Note, your images need not be the same type. You can even mix JPEG, TIFF, PNG -- under one condition: the images should be of the same size (image dimension in pixels). The output format is determined by the output filename's extension.

Should you, for some reason, need a higher resolution than the default one (72 dpi) -- then just add an appropriate -density parameter:

 compare -density 300 image1 image2 -compose src diff.jpeg

Illustrated examples

Here are a few illustrations of results for variations of the above command. Note: the two files compared were even PDF files, so it works with these too (as long as they are 1-pagers)!


Left: Image with text       Center: Original image      Right: Differences (=text) in red pixels. Red difference pixels only; identical pixels are white

compare \
        porsche-with-scratch.pdf  porsche-original.pdf \
       -compose src \
        diff-compose-default.pdf

This is the same command I suggested earlier above.


Left: Image with text      Center: Original image      Right: Differences in 'seagreen' pixels. Seagreen difference pixels only; identical pixels are white

compare \
        porsche-with-scratch.pdf  porsche-original.pdf \
       -compose src \
       -highlight-color seagreen \
        diff-compose-default.pdf

This command adds a parameter to make the difference pixels 'seagreen' instead of the default red.


Left: Image with text       Center: Original image       Right: Blue diffs (but w. some context background) Blue difference pixels only; first of the compared images as a lightened-up backgroundl

compare \
        porsche-with-scratch.pdf  porsche-original.pdf \
       -highlight-color blue \
        diff-compose-default.pdf

This command removes the -compose src part -- the result is the default behavior of compare which keeps as a lightened background the first one of the 2 diffed images. (This time with added parameter to make the diff pixels appear in blue.)

Kurt Pfeifle
  • 86,724
  • 23
  • 248
  • 345
  • I am not able to understand where this compare cli came from? Is it part of imagebrick? available on windows? – Krishnom May 23 '19 at 11:17
  • 3
    @Krishnom: There's no such thing as 'imagebrick'. Do you mean ImageMagick? – Kurt Pfeifle May 23 '19 at 13:17
  • 5
    @Krishnom: The question explicitely asked about an ImageMagick solution. Part of ImageMagick's v6.x software suite had a separate CLI tool called *`'compare'`*. For v7.x of ImageMagick you should run *`'magick compare'`* instead. – Kurt Pfeifle May 23 '19 at 13:19
  • My bad. Thanks for correcting that (imagebrick -> imageMagick). I will give it a try. I am also looking tool to compare bulk images. Thanks for the help again – Krishnom May 24 '19 at 06:59
  • @Krishnom: I do not know what a "bulk image" is. But I still bet that the ImageMagick suite of tools can do what you want. – Kurt Pfeifle May 24 '19 at 07:47
  • I had no idea this existed. This is great! I was doing some visual regression testing with puppeteer and was perplexed why I was never getting the same results for a certain page. This allowed me to easily find the diff! Thanks! – matchew Mar 04 '20 at 14:18
79

While compare does a good job for many applications, I found that sometimes I prefer a different approach, particularly when comparing images which are mostly grayscale:

convert '(' file1.png -flatten -grayscale Rec709Luminance ')' \
        '(' file2.png -flatten -grayscale Rec709Luminance ')' \
        '(' -clone 0-1 -compose darken -composite ')' \
        -channel RGB -combine diff.png

The idea is follows: convert both file1.png and file2.png to grayscale. Then trat the first as the red channel of the resulting image, the second as the green channel. The blue channel is formed from these two using the darken compose operator, which essentially means taking the minimum.

So things which are white in both images stay white. Things which are black in both images stay black. Things which are white in the first image but black in the second turn red, and things which are white in the second but black in the first turn green.

The result gives you a nicely color-coded image where you can easily associate green with the first input and red with the second. Here is an example where I'm using this to compare the output from LaTeX against that from KaTeX (before I fixed some bug to make this better):

enter image description here

You can combine the approaches, using compare to see where something changed and then using the above to see in more detail how it changed.

Brecht Machiels
  • 3,181
  • 3
  • 25
  • 38
MvG
  • 57,380
  • 22
  • 148
  • 276
  • 2
    Nice! I needed some interaction so I replicated your method in Gimp. For reference: 1) load images as layers, 2) Color -> Desaturate both layers, 3) remove alpha channels from both layers in the Layers tab, 4) select the G + B channels on one layer, select all and clear the channels with black color, the same with the R + B channels on the second layer, 4) set Screen mode for the upper layer in the Layers tab. – Matěj Šmíd Feb 23 '16 at 12:25
  • 1
    @Palmstrom: Thanks! I originally did these image comparisons using Gimp myself, but I did so using [the “grain extract” layer mode](http://docs.gimp.org/en/gimp-concepts-layer-modes.html#idp14580272) directly on the input images, so common areas would end up gray, while the diff would be black in one direction and white in the other. Harder to read, but quicker to generate, and it can contain color information. I guess you would match my command even more closely if you were using “darken only” instead of “screen”, and color unused channels white instead of black. – MvG Feb 23 '16 at 12:58
  • 1
    *Some* PDF inputs result in an inverted image after grayscale conversion for some reason. Using `-colorspace gray` instead of `-grayscale Rec709Luminance` fixes that, but this messes up the composition. Add `-respect-parentheses` as the first option to `convert` to take care of that. – Brecht Machiels Mar 16 '16 at 13:05
  • 1
    Here's a script to visually diff two PDFs page-by-page using this method: https://gist.github.com/brechtm/891de9f72516c1b2cbc1. It outputs one JPG for each page of the PDFs in a `pdfdiff` directory and additionally prints the numbers of the pages which differ between the two PDFs. – Brecht Machiels Mar 31 '16 at 13:31
  • 1
    In ImageMagick v6.7.7-10 it seems `-grayscale` is not supported, I had to use `-colorspace gray` as @BrechtMachiels suggested – austinmarton May 03 '18 at 22:50
  • Very nice! For me (ImageMagick 7.1.0-29) `-flatten` did weird not useful things (it seemed to revert to an uncropped version of my source image, which doesn't make sense), but it worked perfectly fine without it. Possibly only useful if you have a transparency layer in your png? I also swapped the order of the input files so red means "removed in file2" and green means "added in file2", which is more intuitive in my mind. – Heath Raftery Apr 15 '22 at 14:34
3

From ImageMagick 6.3.4, you can use -compose ChangeMask (see also "Removing a Known Background" and following sections). For example, using IM7 and these images stone.png, diamond_ore.png, and netherrack.png:
stone.png diamond_ore.png netherrack.png

magick diamond_ore.png stone.png -fuzz 15% -compose ChangeMask -composite diamond_ore_overlay.png gives:
diamond_ore_overlay.png

Then magick netherrack.png diamond_ore_overlay.png -composite nether_diamond_ore.png gives:
nether_diamond_ore.png
(In one command: magick netherrack.png \( diamond_ore.png stone.png -fuzz 15% -compose ChangeMask -composite +compose \) -composite nether_diamond_ore.png)

James Groom
  • 235
  • 2
  • 6