This is a started out as a set of simple extension methods for the System.Drawing.Image class which would allow you to:

Find out how different two images are as a percentage value based on a threshold of your choosing

Get a difference-image which shows where the two are different

Get the difference as raw data to use for your own purposes

With the feedback received here, the solution has been expanded to

A console version which can take the paths of two images as parameters, and return the difference as an errorlevel

A COM callable DLL (still in need of testing - anyone?)

The ability to find duplicates in a folder, or among a list of imagepaths

As a bonus, you get extension methods for resizing or grayscaling an image.

With the feedback I recieved here, the

Background

You don't need to read this chapter to use the extension methods, so if you don't care about how I created the software - just skip to the Using the code bit.

I was happily coding away one evening, making a little tool to download images from posts in an RSS feed, when I first got the idea: "If there's a link from the blog post to another post cited as the source, why not have the code go there and check for a higher resolution version of the image?" Then I thought "but the original image might not have the same name as the one I first met in the post" https://www.codeproject.com/script/Forums/Images/smiley_frown.gif

So I had to find a way of comparing the visual representation of the two images. I am not particularly good at math, so after Googling around and finding assorted algorithms using wavelets, keypoint matching, etc. (which seemed out of my mental reach https://www.codeproject.com/script/Forums/Images/smiley_wink.gif ), I found out that some people were having good results using histograms. So I first went down that path.

Histograms

A histogram is a way of representing what kinds of colors are in a picture. You can create a histogram describing the light or red, green, or blue values in an image. A basic way of creating a histogram is to look at each pixel in a bitmap and for each of them find out what the value of the property you are looking at (RGB) is. For each possible value (typically 0-255), you have a variable which you increment. This way, when you are done with all the pixels, you can iterate over the variables and see how many pixels had low values, medium values, and high values of light, R, G, or B. I fiddled around a couple of hours with this, but found out that in the end, this wasn't good enough for detecting differences in pictures, as two totally different pictures depicting almost the same (e.g., two corn fields) with the same composition of colors/light can be hard to differentiate using just a histogram. I tried comparing the two using average in colors, and variance, but to no avail.

The good thing is that as a byproduct of my work, now there are histogram extension methods for the Bitmap class: GetRgbHistogram and GetRgbHistogramBitmap.

//get a histogram as an image
Bitmap bmpHist = img1.GetRgbHistogramBitmap();
//save it
bmpHist.Save("C:\\bmphist.png");

//get a histogram object
Histogram hist = img1.GetRgbHistogram(); //basically three arrays for RGB values
//show it in the console
Console.WriteLine(hist.ToString());

Feel free to use them https://www.codeproject.com/script/Forums/Images/smiley_smile.gif Note: Based on Svansickle's comments on this article on histograms I've implemented the Bhattacharyya histogram algorithm, which is a way of comparing two images based on their normalized histograms.
You can play around with this to see whether this way of comparing two images is better for your purposes. I've added the functionality because it seemed interesting, and I'd love to hear if you've found uses for it :)

Simplifying

Histograms were a dead end to me. But after Googling around some more, I read some forum posts suggesting that if images were reduced to a much smaller size, and even gray scaled, then the differences would be both faster and simpler to find. It was worth a try.

Using the .NET Framework, I could easily resize an image. Then I found some code that would grayscale an image. Now all that was left was to iterate through the pixels on both images and compare the two and then find out how many were different.

Here are the two images I used, with an XBOX controller, a post-it with and without text and two different colored pens.

I thought I'd start out by using a gray scaled, 16x16 pixel version of each image, and see whether I needed higher resolution for practical use.

Upscaled versions of the two 16x16 pixel images

For each pixel I'd then get the difference of the brightness value compared to the other image's pixel in the same spot and save it in a double array of bytes (since R, G and B values in Bitmap can be between 0 and 255). I would then count all the values in the double array which weren't zero, divide this value by the amount of pixels in an image (256), and voilà - I would have a difference value in percentages - right? ....not quite https://www.codeproject.com/script/Forums/Images/smiley_smile.gif

It works well enough to visualize differences between two images as you can see here:

But...!

There was a slight problem though. My algorithm was also finding differences where none were visible to the naked eye. Here and there a re-encoding of a JPEG in the same resolution as the original or identical images in different resolutions suddenly had a lot of differences with a value of 1 or 2 showing up. This could easily give me fifty pixels with a difference - and fifty pixels out of 255 is about 20%, which makes the algorithm too blunt, since a human could detect no difference visually. So I introduced a threshold (a value that the difference had to exceed to be counted).

Using a threshold

Here you can see the differences between a 200 pixels wide version of an image and a 100 pixels wide version of the same image:

You can see what threshold values resulted in the above (the red text). By default, pixel difference values below 4 are now treated as no difference, and it is possible to adjust this by giving the extension method an optional parameter:

//find out how different two images are, with a threshold of 5 in the lightness of pixels
int threshold = 5;
float percentageDifference = img1.PercentageDifference(img2, threshold);

This also makes it possible for you to adjust the sensitivity of the code according to your needs. A default threshold of three works for me, but by all means - play around with it, and adjust this to your heart's desire or depending on the task you need it for.

That's it folks!

This is where my story ends. I now have the ability to detect whether two images are similar, how much they differ, and where, which was all I wanted - yay! XD.

I hope you've had fun reading my little coding-story, and I hope you can use the code somehow.

Kind regards - Jakob "XnaFan" Krarup.

Using the code

Get the DLL

All you need to do is download the DLL or the complete solution (see top of article), add a reference to XnaFan.ImageComparison.dll, and a using XnaFan.ImageComparison statement to your code file - and you should be set to go.

Use the public methods of ImageTool

//use this method to find the difference between two images (returns a float between 0 and 1)
float GetPercentageDifference(string image1Path, string image2Path, byte threshold = 3)
//use this method to find the difference in percent between the Bhattacharyya histograms
//Bhattacharyya histogram is a normalized histogram, see comments...
float GetBhattacharyyaDifference(string image1Path, string image2Path)
//Use these methods to get a list of duplicate images in a specific folder
​List<List<string>> GetDuplicateImages(string folderPath, bool checkSubfolders)
List<List<string>> GetDuplicateImages(IEnumerable<string> pathsOfPossibleDuplicateImages)

Visualizing the differences

I have included the possibility of color coding the difference bitmap either by using a palette of black to pink corresponding to values 0 to 255, or by having the palette map to whatever is the current max. This will enable you to highlight small differences or keep them dark as you wish. See the difference here:

This is the difference between using the parameter adjustColorSchemeToMaxDifferenceFound as true or false:

Sample Console and WPF application included

To get you started, I've included a sample Console application and a WPF app - to show how you can use the code. WPF also has the added benefit of giving you code to transform between System.Drawing.Image ("regular" .NET) and System.Windows.Media.Imaging.BitmapSource (WPF). I am just starting on WPF, so it was a learning-by-failing experience. Don't go looking for any best-practices there ;-D.

Console version

A reader asked for a command prompt version of the functionality, so there is also a commandline version now, which returns the difference between the images as an error level so you can use it from a batch file or other programming language.

Usage

ImageComparisonConsole.exe [image1 path] [image2 path]

Here is a sample batch file using it:

@echo off
<pre>REM saving paths to images
REM you can also use absolute paths. i.e "C:\something.png"
set image1="firefox1.png"
set image2="firefox2.png"

REM print what is about to happen
echo 'ConsoleImageComparison.exe %image1% %image2%'

Hello. Work is good. But few suggestions. 1. Use BackgroundWorker to make the comparision smooth.

2. Wpf has a good and fast imaging support. Instead of usin legacy Drawing.Bitmap method, use Wpf imaging.

3. Comparison in Spatial domain is fine but of now use practically. Especially for Jpeg images. Convert the images to gray scale, take dct, compare on dct domain. convert the resultant image to spatial domain.

1) As I mentioned in the article - I am a beginner in WPF, so this is merely a small application to show the real functionality which is in the extension methods .2) I want this code to be usable for as many people as possible, therefore I have used the System.Drawing namespace .3) I don't know what you mean by "dct domain"?

hi,MATLAB(Matrix Laboratory) is Software which do calculation in the form of matrices.It is useful for processing images, plotting graphs,and calculations related signals & Matrices.It also has feature to develop GUIs using its controls.I am trying to develop automated software that will take i mages from webcam and stores it on hard disk. Next time when it takes images it will compare image with previous ones and shows result on dialogue box how much percent does it matches.

Main thing is that the brightness will be different for different images of same object so i have to check how much does it matches?

we cant bring .net code in matlab I am also learning .net simultaneously so and now thinking to apply your algorithm in MATLAB.

I've changed the code a bit and added a console version, so you can call the imagecomparison function from other programs (including MatLab I hope ). I will update the article and the source code download over the weekend.

Could be faster if you'd use unsafe code instead of GetPixel/SetPixel (at least).

Another thing is that in image processing, _nothing_ is this simple. This algorithm can fail in varying lighting conditions, or because of different autofocus settings, or because of a movement of your camera or a whole lot of other stuff, but is okay for a start though.

Thanks for your input - you're right about both things.- I considered the unsafe code practice, but since I know a lot of developers are nervous about using "unsafe" code, I opted for the other version - I know the algorithm is far from perfect, thanks for pointing out some of the scenarios to be aware of. I think the only thing that speaks for this algorithm is its simplicity. The benefit is that I could cover 80 % of the usecases with 10 % of the effort - and it is relatively easy for others to understand and change the code

Firstly, fantastic job with the image comparison, i'm using it effectively over here and you have saved me some real time !!!!!!!!

I have this working in VS 2010. I have another machine with 2012 and I'm using the exact same cs file however i have encountered this error - doesn't seem to like the DLL

System.BadImageFormatException : Could not load file or assembly 'XnaFan.ImageComparison, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. An attempt was made to load a program with an incorrect format.

i want to compare two images like image1.png and image2.png.both the images look pretty same with some difference. so i want to get the difference and want to apply the difference on first image image1.png. i searched lot to get similar kind of code but found none.

after lots of search i got bit similar kind of things which i am looking for but that is in java code. here is the url http://mindmeat.blogspot.in/2008/07/java-image-comparison.html

please go to the url and there you can see the code generate 3rd image with difference but my requirement is bit different. i do not want to generate 3rd image rather i want to apply the difference on the 1st image image1.png. so just tell me how can i use your code to achieve my object. it will be great help if you can guide how to your routine. which method i need to call to get the difference between two image and another important thing how can i apply the difference on first image image1.png.

another most important things is i want to proceed in such way as a result all the comparison and apply diff on 1st image should be very faster just take few ms. so please guide me with your opinion and code snippet. thanks

Hi.
Palette of black to pink corresponding tovalues0to255 represents change inimagein your article. How this comparison can be done in percentage likeif both images are same it show 100% andif there is dissimilarity it will show 50% orany other value.