Article : Image Comparing

ImageMagick v6 Examples --

  Image Comparing
Index
  ImageMagick Examples Preface and Index
 Methods of Comparing Images -- what is different?
•   Compare Program
•   Difference Images
•   Flicker Compare
•   Comparing Animations
  Comparison Statistics -- how different?
  Sub-Image Matching and Locating Finding smaller images in larger.
  Finding Duplicate Images -- finding two images that are the same
  Sorting Images by Type -- image classifications for comparing
  Handling Specific Image Types
  Image Metrics -- finger-printing images for comparision
  Web Cameras -- Finding what has changed in fixed cameras
The ability to compare two or more images, or finding duplicate images in a large collection, is a very tricky matter. In these examples we look at comparing images to determine how they similar they are, and where they differ.
This may involve classifying or grouping images into various types for better handling. Discovering some metric to simplify and group similar images. And clustering similar images together based on such metrics.
However such comparisons, and or studies while difficult can be rewarding, with the ability to find image duplicates, copies, and even removal of 'spam' or other text or notices from images.
________________________________________
Methods of Comparing Images
Compare Program
The "compare" program is provided to give you an easy way to compare two similar images, to determine just how 'different' the images are.
For example here I have two frames of a animated 'bag', which I then gave to "compare' to highlight the areas where it changed.

  compare bag_frame1.gif bag_frame2.gif  compare.gif
   
As you can see you get a white and red image, which has a 'shadow' of the second image in it. It clearly shows that three areas that changed between the two images.
Rather than saving the 'compare' image, you can of course view it directly, which I find more convenient, by output to the special "x:" output format, or using the "display" program. For example..

  compare bag_frame1.gif bag_frame2.gif  x:
  compare bag_frame1.gif bag_frame2.gif  miff:- | display
As of IM v6.4 you can change the color of the differences from red to some other more interesting color...

  compare bag_frame1.gif bag_frame2.gif \
  -highlight-color  SeaGreen  compare_color.gif
   
As of IM v6.4.2-8 you can specify the other color as well.

  compare bag_frame1.gif bag_frame2.gif \
  -highlight-color  SeaGreen  -lowlight-color PaleGreen \
  compare_colors.gif
   
If you don't want that 'shadow' of the second image, from IM v6.4.2-8 you can add a "-compose src" to the options to remove it.

  compare bag_frame1.gif bag_frame2.gif \
  -compose Src compare_src.gif
   
By using all three extra settings we can generate a gray-scale mask of the changed pixels...

  compare bag_frame1.gif bag_frame2.gif \
  -compose Src -highlight-color White -lowlight-color Black \
  compare_mask.gif
   
Note however that this mask is of ANY difference, even the smallest difference. For example you can see all the minor differences that saving an image to the Lossy JPEG Format produces...

  convert bag_frame1.gif  bag_frame1.jpg
  compare bag_frame1.gif bag_frame1.jpg  compare_lossy_jpeg.gif
   
As you can see even though you can't really see any difference between GIF and the JPEG versions of the image, "compare" reports a lot of differences.
By using a small Fuzz Factor you can ask IM to ignore these minor differences between the two images.

  compare -metric AE -fuzz 5% \
  bag_frame1.gif bag_frame1.jpg  compare_fuzz.gif
 
   
Which shows that most of the actual differences are only minor.
The special "-metric" setting of 'AE' (short for "Absolute Error" count), will report (to standard error), a count of the actual number of pixels that were masked, at the current fuzz factor.
Difference Images
To get a better idea of exactly how different the images are, you are probably better of getting a more exact 'difference' composition image....

  composite bag_frame1.gif bag_frame1.jpg \
  -compose difference  difference_jpeg.gif
   
As you can see while "compare" showed that JPEG created a lot of differences between the images, a 'difference' composition was quite dark, indicating that all the differences were relatively minor.
If the resulting image looks too black to see the differences, you may like to Normalize the image (using the more mathematically correct "-auto-level", so as to enhance the results.

  convert difference_jpeg.gif  -auto-level  difference_norm.gif
   
This still shows that most of the differences are still very minor, with the largest difference occurring along the sharp edges of the image, which the JPEG image file format does not handle very well.
On the other hand getting a difference image between the two original frames of the animation shows a very marked differences between the two images, even without any enhancement.

  composite bag_frame1.gif bag_frame2.gif \
  -compose difference  difference_frames.gif
   
Note that as the 'difference' compose method is associative, the order of the two images in the above examples does not matter, although unlike "compare", you can compare different sized images, with the destination image determining the final size of the difference image.
The different method is even more useful when used with the "convert" program, as you can process the resulting image further before saving or displaying the results. For example you can threshold and merge each of the color channels to to generate a mask of any pixel that changed color between the two images.

  convert bag_frame1.gif bag_frame2.gif -compose difference -composite \
  -threhold 0 -separate -evaluate-sequence Add \
  difference_mask.gif
   
This is basically what the "compare" program does, but with more controls as to the color and output style.
However as you can see it tends to find even the smallest minor change between two images. If the images are from a lossy image file format, such as JPEG, or a GIF image that required color reduction and dithering (color quantization), then that would probably match everything in the image. As such it it typically not very useful.
For better results you can try to figure out just how different the pixel colors are. For example we can gray-scale the result, so as to get a better comparison image, than a colorful one.

  convert bag_frame1.gif bag_frame2.gif -compose difference -composite \
  -colorspace Gray  difference_gray.gif
   
Now unlike "compare", the difference image shows a mixture of both images combined in the final result. For example look at the weird 'talisman' seems to appear in the forehead of the cat. This was originally the handle of the bag from the first image. This merger can make it confusing as to exactly what differences you are seeing, and you see a megere of both the additions and removals from the image.
Because of this confusion of details, the "compare" is usually the better way for us humans to view, while the 'difference' image is the better method for further processing the image.
However grayscaling a difference image will simply average (actually a weighted average) the RGB distances together. As a result a single bit color difference could be lost though Quantum Rounding Effects.
If even the smallest difference between images is important, a better method is to add the separate color channels of the difference image, to ensure you capture ALL the differences, including the most minor difference.

  convert bag_frame1.gif bag_frame2.gif -compose difference -composite \
  -separate -evaluate-sequence add  difference_add.gif
   
The difference values produced in the above is known as a 'manhattan distance' metric. That is the distance between the two colors of each image when you are restricted to orthogonal (or axial) movement. Be warned however that large differences may become clipped (or burned) as it can exceed the pixel data 'Quantium Range', or integer limits, unless using a HDRI version of IM.
To take this further you can get the color vector distance, by using some squares and square roots to implement a Pythagorean or Euclidean distance.

  convert bag_frame1.gif bag_frame2.gif -compose difference -composite \
  -evaluate Pow 2 -separate -evaluate-sequence Add -evaluate Pow 0.5 \
  difference_vector.gif
   
This is in fact similar what a 'fuzz' factor actually measures as part of its thresholding (when no transparency is involved). However 'fuzz' also divides the squared values by 3, before adding, to ensure the results do not exceed the image color range limits. Doing this means you would only get a pure 'white' pixel in the result for difference between opposite primary and secondary colors, such between a blue and yellow pixel.
So lets do that scaling too...

  convert bag_frame1.gif bag_frame2.gif -compose difference -composite \
  -evaluate Pow 2 -evaluate divide 3 -separate \
  -evaluate-sequence Add -evaluate Pow 0.5 \
  difference_vector_scaled.gif
   
This is actually very similar to what you would get for a "-colorspace Gray' difference image (as above), but it is much more accuriate representation of color difference.
You could leave of the second 'Pow 0.5' modification in which case you will get a Squared difference Image.
There are other color distance metrics, which you can read about on the Color Difference, Wikipedia page. Most of these involve generating vector differences (see last) but using a different colorspace, such as LAB or LUV. This would however be more important in comparing real wo