4

Is there any equality predicate function in ImageMagick library? I want to compare two images and find whether they are the exactly same (all colors of the pixels are the same) or have any differences.

I’ve looked around, but it seems not to have a such function. Should I write the function using pixel iterators by myself?

2 Answers 2

8

ImageMagick provides the compare function to properly compare images.

Checking the md5 checksum of two images is not the correct approach, since some image formats (e.g. PNG and JPEG with EXIF for example), contain the date and time the file was created (see example 1) below, and some files can be visually identical but represented completely differently internally (see example 2), or have different bit-depths (see example 3).

Example 1

# Create two identical images (100x100 pixels, bright red) but with different file contents convert -size 100x100 xc:red r1.png convert -size 100x100 xc:red r2.png # MD5 checksum them md5 r?.png MD5 (r1.png) = 9f6d612615efd88c3fd8521d717e9811 MD5 (r2.png) = 996911bec0e0da75af46a1e78c052998 # Mmmm different # Ask IM to tell us absolute error between the two (number of differing pixels) compare -metric AE r1.png r2.png null: 0 # No difference - that's better 

Why do these two differ in MD5? Because the date is in them...

identify -verbose r[12].png | grep -i date date:create: 2015-03-03T14:57:26+00:00 date:modify: 2015-03-03T14:57:26+00:00 date:create: 2015-03-03T14:57:43+00:00 date:modify: 2015-03-03T14:57:43+00:00 

Example 2

# Create PNG and identical GIF convert -size 100x100 xc:red r.png convert -size 100x100 xc:red r.gif # Compare with MD5 sums md5 r.png r.gif MD5 (r.png) = 692ef06b62a15b799d5dc549b0dd3737 MD5 (r.gif) = 549feea78dc438924fbb3e0ef97dc0b3 # Ooops # Compare properly compare -metric AE r.gif r.png null: 0 # Identical 

Example 3

# Create 8-bit PNG and 16-bit PNG convert -size 100x100 xc:red PNG8:8.png convert -size 100x100 xc:red PNG48:48.png # MD5 sum them md5 8.png 48.png MD5 (8.png) = eb3fc9a06e1632c3b41ebb986b81a816 MD5 (48.png) = 32fdf1c30793a4fed941c91d27084e0a # Ooops # Let ImageMagick compare them compare -metric AE 8.png 48.png null: 0 

Fuzzy Comparison of Images

As Kurt alludes to, this also leads to the possibility of doing a fuzzy compare of images. We can explore that like this:

# Create a grey image, 100x100 and put some noise in it convert -size 100x100 xc:gray +noise gaussian noise.png 

enter image description here

Now multiply all pixels by 1.01 to make them an imperceptible 1% brighter:

# Make pixels 1% brighter convert noise.png -evaluate multiply 1.01 brighternoise.png # ... and compare the statistics of the two images identify -verbose *noise* | grep -E "^Image|mean" Image: brighternoise.png mean: 127.235 (0.498959) <--- The brighter image is, well, brighter Image: noise.png mean: 126.175 (0.494805) 

And now compare them, a few different ways:

# Pixels may differ by up to 2% before being considered different compare -fuzz 2% -metric AE noise.png brighternoise.png null: 0 # All pixel values within 2% between the 2 images # Pixels may only differ by 0.5% before being considered different compare -fuzz 0.5% -metric AE noise.png brighternoise.png null: 594 # 594 of the 10,000 pixels differ by more than 0.5% # Calculate Root Mean Square Error (RMSE) to see how much pixels tend to differ compare -metric RMSE noise.png brighternoise.png null: 278.96 (0.00425666) # On average, the pixels differ by 0.4% - i.e. hardly at all 
Sign up to request clarification or add additional context in comments.

1 Comment

For anyone trying this 6 years later: compare -metric MAE 8.png 48.png. They changed parameter names in newer releases.
4

Mark's answer is spot-on. However, he forgot to mention that compare can also return a 'delta image', which will paint any pixel with differences as red, while identical pixels will be white.

# Create a PNG and a JPEG from the builtin 'wizard:' image: convert wizard: wizard.png convert wizard: wizard.jpg 

Now compare the two:

compare wizard.png wizard.jpg delta.png 

This is the 'delta.png':

delta.png

Lots of differences between PNG and JPEG! Ok, this is explained by the fact that JPEG is a lossy image format...

As you can see, the 'delta.png' has a pale background. If you do not want this background, but only red/white pixels, modify the compare command:

compare wizard.png wizard.jpg -compose src delta.png 

Also, you may want to ignore such differences which are below a certain threshold. Here the -fuzz N% parameter comes in handy.

You want blue pixels instead of red? And yellow ones instead of white? Here you go:

compare \ -highlight-color blue \ -lowlight-color yellow \ -fuzz 3% \ wizard.png \ wizard.jpg \ delta2.png 

delta2.png

You want a textual description of all pixels which are different with their respective coordinates? Here the special output format *.txt may be good.

Try this:

compare \ -fuzz 6% \ wizard.png \ wizard.jpg \ -compose src \ delta3.txt 

The 'delta3.txt' file will be quite large, because it contains one line per pixel in this format:

# ImageMagick pixel enumeration: 480,640,255,srgba 0,0: (255,255,255,0.8) #FFFFFFCC srgba(255,255,255,0.8) 1,0: (255,255,255,0.8) #FFFFFFCC srgba(255,255,255,0.8) 2,0: (255,255,255,0.8) #FFFFFFCC srgba(255,255,255,0.8) [....] 77,80: (241,0,30,0.8) #F1001ECC srgba(241,0,30,0.8) [....] 

The first column gives the (row,column) pair of the respective pixel (counting is zero-based, the topmost, leftmost pixel has the address (0,0).

The next three columns return the respective pixel color, in 3 different common notation formats.

BTW, ImageMagick can convert the delta3.txt file back to a real image without any problem:

convert delta3.txt delta3.png 

So to get all the pixels which are different (red) into a text file, you could do this:

compare \ -fuzz 6% \ wizard.png \ wizard.jpg \ -compose src \ txt:- \ | grep -v '#FFFFFFCC' 

To count the number of different pixels:

compare \ -fuzz 6% \ wizard.png \ wizard.jpg \ -compose src \ txt:- \ | grep -v '#FFFFFFCC' \ | wc -l 

With -fuzz 6% I have 2269 different pixels. With -fuzz 0% I get 122474 different pixels. (Total number of pixels in these images was 307200.)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.