Shell test for “images are different”?

2019-09-05 13:34发布

问题:

In a shell script, I would like to check whether two PNG images are different in the sense that either the images have different sizes or at least one pixel of one image has a different RGBA than the corresponding pixel of the other image.

Hashing the two image files will not work because the images could be compressed differently or have a different comment or perhaps two pixels are fully transparent but the RGB components differ, etc.

I know how to check whether the file sizes are different using ImageMagick's convert utility. As far as comparing the pixel values, I thought of using ImageMagick's compare utility, but the exit code is always 0 if the command was successfully processed: http://www.imagemagick.org/discourse-server/viewtopic.php?f=3&t=22451

What command line test can be used to compare the pixels of two PNG images for equality? Or perhaps there is a way to use compare after all?

回答1:

Find an image format which allows uncompressed RGBA, convert both files, and compare the output. Maybe something like this:

$ convert a.png a.rgba
$ convert b.png b.rgba
$ cmp {a,b}.rgba
a.rgba b.rgba differ: byte 1, line 1


回答2:

You should not use the exit code from ImageMagick compare. All that says is the compare function exited successfully with no error. You want to report the AE metric from compare, which will tell you how many pixels are different. Or use some other metric such MAE or RMSE.

compare -metric AE image1 image2 null:


That will return a value to the terminal, which is the count.

For example:

compare -metric AE lena.png lena.jpg null:
65100


65100 pixels are different

You can return that to a variable as:

var=`compare -metric AE lena.png lena.jpg null: 2>&1`
echo $var
65100


ImageMagick writes its output to stderr, so that is why I added 2>&1

See

https://imagemagick.org/script/compare.php https://imagemagick.org/Usage/compare/



回答3:

another way using ImageMagick and grep

compare -compose src -highlight-color "#FF0000FF" -lowlight-color "#00000000" a.png b.png delta.png

convert delta.png -define histograme:unique-colors=true -format %c histogram:info:- > histogram.info

if grep --quiet "#FF0000 red" histogram.info : then
   echo "different"
else
   echo "same"
fi

while this methodology relies on ImageMagick being installed, and is heavier than cmp it may be easier to expand to allow for tolerance etc...

TIPS
display -version is a quick way to test if ImageMagick is already installed.

These commands could also be piped together if you want to avoid writing to disk.



回答4:

2 foundamental steps:

  1. Recognize image format (gif, png, jpeg, ...). This can be done by file extension, if image files are "trustable" or in some other kind of way.

  2. Find image properties, that are specific image format informations, stored into processed file. You can find infos about file and generic data formats from Wotsit.org.