Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
196 views
in Technique[技术] by (71.8m points)

c# - Can we programmatically compare different images of same resolutions?

Is there a good and reliable way to compare images of same format and same resolution and get difference between them?

In the best-case scenario I am looking for some numerical representation of image that can be then compared because I have to compare many images.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can use ImageMagick's compare command to do this.

(If you are successful with the command line, you could then move on to use one of ImageMagick's APIs: these are, amongst others, available for C ('MagickWand'), C++ ('Magick++'), Java ('JMagick'), LISP ('L-Magick'), .NET ('Magick.NET'), Perl ('PerlMagick'), PHP ('IMagick'), Python ('PythonMagick') and Ruby ('RMagick'). -- Then implement the respective functions into an application of your own.)

The only requirement is: the images need to have identical dimensions in width and height, measured in the number of pixels. So you do not even need the same format as you assumed.

The difference can be returned in different ways:

  • Generate a visual representation of the differences, where the pixel with deltas are somehow highlighted in a delta image.

  • Generate a textual and/or statistical representation of the differences, where the output is one or several numbers, or just the count of pixels which are different, or some other metric.


Example

Here are four example images which can compared. They each are similarly looking, have a size of 322x429 pixels -- but there are some finer differences in colorization and format: the top right one is a JPEG, the other three are PNGs:

image image

image image

Visual comparisons

Here is the most simple command to compare the top two images and produce a visual 'delta':

compare                              
  http://i.stack.imgur.com/GBax7.png 
  http://i.stack.imgur.com/D9IAV.jpg 
  delta1.pdf

This compares a PNG with the JPEG and produces a PDF as output. For a visual impression of this output see image below on the left (since PDFs cannot be displayed here, I did resort to produce a PNG and use this for display instead).

What did this simplest of all ImageMagick compare commands exactly do?

  1. It used the first image as a pale background.
  2. It overlayed red, fully opaque pixels on each location where the color of the respective pixel in the second image deviates from the first one.

(I could have added -highlight-color blue and -lowlight-color yellow or any other color definitions if I wouldn't want the default red highlighting)

What if I didn't want such an over-exact comparison of pixel colors? What if I'd like a red pixel only when there is a more considerable color distance between the respective pixels?

Easy: add a 'fuzz' factor to the command line!

compare                              
  http://i.stack.imgur.com/GBax7.png 
  http://i.stack.imgur.com/D9IAV.jpg 
 -fuzz 2.5%                          
  delta2.png

image image

When running without additional arguments the first (most simple) compare command, ImageMagick silently added a specification of its default comparison method, which is called -compose src-over.

Of course we can override this and use a different composition mode. How to learn about the available composition modes? The command convert -list compose will enumerate them for us! Here is the complete list -- it contains 67 different ones on my system:

Atop Blend Blur Bumpmap ChangeMask Clear ColorBurn ColorDodge Colorize CopyBlack CopyBlue CopyCyan CopyGreen Copy CopyMagenta CopyOpacity CopyRed CopyYellow Darken DarkenIntensity DivideDst DivideSrc Dst Difference Displace Dissolve Distort DstAtop DstIn DstOut DstOver Exclusion HardLight HardMix Hue In Lighten LightenIntensity LinearBurn LinearDodge LinearLight Luminize Mathematics MinusDst MinusSrc Modulate ModulusAdd ModulusSubtract Multiply None Out Overlay Over PegtopLight PinLight Plus Replace Saturate Screen SoftLight Src SrcAtop SrcIn SrcOut SrcOver VividLight Xor

Let's try each and every one:

for i in $(convert -list compose|tr "
" " "); do 
  compare                                         
     http://i.stack.imgur.com/GBax7.png           
     http://i.stack.imgur.com/D9IAV.jpg           
    -compose ${i}                                 
     delta-${i}.png ;                             
done

Of course it would be too much to now show each and every resulting delta image. The most interesting ones are below:

  • top left is -compose Difference
  • top right is -compose DivideSrc
  • center left is -compose CopyBlue
  • center right is -compose MinusDst
  • bottom left is -compose Hue
  • bottom right is -compose LightenIntensity

Note: if you swap the order of the two compared images, the two resulting deltas could be significantly different two!

image image

image image

image image

Now you can already start your own experiments with visually comparing two similar images.

Metrical results

To generate metrics about the differences of two images, you can run a command like this:

compare                               
  -metric rmse                        
   http://i.stack.imgur.com/GBax7.png 
   http://i.stack.imgur.com/D9IAV.jpg 
   null:

rmse is the acronym for root mean squared error. The result of the above example images gives:

 1339.53 (0.02044)

How many different metric methods are supported?

The following command enumerates all available comparison metrics methods on a given system, for the current version of ImageMagick:

compare -list metric 

On my notebook, these are:

AE Fuzz MAE MEPP MSE NCC PAE PHASH PSNR RMSE

The meanings of these abbreviations are:

AE     absolute error count, number of different pixels (`-fuzz` effected)
FUZZ   mean color distance
MAE    mean absolute error (normalized), average channel error distance
MEPP   mean error per pixel (normalized mean error, normalized peak error)
MSE    mean error squared, average of the channel error squared
NCC    normalized cross correlation
PAE    peak absolute (normalized peak absolute)
PHASH  perceptual hash
PSNR   peak signal to noise ratio
RMSE   root mean squared (normalized root mean squared)

An interesting (and relatively recent) metric is phash ('perceptual hash'). It is the only one that does not require identical dimensions for the two compared images. It really is the best 'metric' to narrow down similarly looking images (or at least to reliably exclude these image pairs which look very different) without really "looking at them", on the command line and programatically.

One good experiment to run is when you compare an image to itself. It shows how the respective metric translates 'identity' into its own environment:

for i in $(compare -list metric); do     
    compare                              
     -metric $i                          
      http://i.stack.imgur.com/GBax7.png 
      http://i.stack.imgur.com/GBax7.png 
      null:                              
done

This is the result:

AE    :   0
Fuzz  :   0 (0)
MAE   :   0 (0)
MEPP  :   0 (0, 0)
MSE   :   0 (0)
NCC   :   1.00001
PAE   :   0 (0)
PHASH :   0
PSNR  :   inf
RMSE :    0 (0)

As you can see, every single metric method returns 0, apart from two: PSNR returns infinity and NCC returns 1.00001.

Run this same command and compare a pure white patch of 100x100 pixels to a pure black one:

for i in $(compare -list metric); do 
  compare                            
     -metric $i                      
     -size 100x100                   
      xc:white                       
      xc:black                       
      null:                          
done

This returns the following result:

AE    :   10000
Fuzz  :   65535 (1)
MAE   :   65535 (1)
MEPP  :   1.96605e+09 (1.00003, 1)
MSE   :   65535 (1)
NCC   :   0
PAE   :   65535 (1)
PHASH :   417.941
PSNR  :   0
RMSE  :   65535 (1)

The AE metric is as expected: 10000 pixels (from -size 100x100) are different. Most other results are also easy to understand once you read up and grokked what the respective metric definitions mean....

Finally, let's look at the output of each available metric when comparing the top two images above (PNG and JPEG):

for i in $(compare -list metric); do     
    compare -metric $i                   
      http://i.stack.imgur.com/GBax7.png 
      http://i.stack.imgur.com/D9IAV.jpg 
      null:                              
done

AE    :   74200
Fuzz  :   1339.53 (0.02044)
MAE   :   499.997 (0.00762946)
MEPP  :   2.07206e+08 (0.000417654, 0.435294)
MSE   :   27.3801 (0.000417793)
NCC   :   0.99709
PAE   :   28527 (0.435294)
PHASH :   0.745389
PSNR  :   33.7904
RMSE  :   1339.53 (0.02044)

Now pick your metric! :-)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...