Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if an image is a scaled version of another image

Tags:

c#

.net

image

I am looking for an EASY way to check if an image is a scaled version of another image. It does not have to be very fast, it just should be "fairly" accurate. And written in .NET. And for free.

I know, wishful thinking :-)

I am pretty sure, even without having tried it, that converting the bigger image to the smaller scale and comparing checksums is not working (especially if the smaller version was done with another software then .NET).

The next approach would be to scale down and compare pixels. But first of all, it seems like a really bad idea running a loop over all pixels with a bool comparison results, I am sure there will be some pixels off by a bit or so...

Any library coming to mind? Way back in the university we had some MPEG7 classes, so I am thinking about using a combination of "statistics" like tone distribution, brightness, etc..

Any ideas or links for that topic?

Thanks, Chris

like image 782
Christian Ruppert Avatar asked Aug 06 '10 08:08

Christian Ruppert


People also ask

What is scaled image version?

A scaled image is essentially one that has been sized to fit the exact dimensions you're using it for. On one hand, an image that's too small and scaled up will be blurry. On the other hand, while a browser will shrink an image that is too large, it adds to the page's file size unnecessarily.

What will happen to an image that is scaled?

When scaling, the resolution is not adjusted to best suit the new size, rather the pixels are stretched and can appear pixelated. The most common side effect of scaling an image larger than its original dimensions is that the image may appear to be very fuzzy or pixelated.

How do you proportionally scale an image?

If the Shift key is held down whilst moving the handle, then the proportions of the object will be preserved. For example, if I hold Shift and drag the bottom edge upwards to reduce the size by half, then the right edge will automatically move to the left to reduce the width of the object by the same amount.

How is a photo scaled?

Image scaling refers to the resizing of a digital image. The Image scaler embedded in our graphic maker enlarges or reduces the physical size of an image by changing the number of pixels it contains. It changes the size of the contents of the image and resizes the canvas accordingly.


2 Answers

I think this is going to be your best solution. First check the aspect ratio. Then scale the images to the smaller of the 2 if they're not the same size. Finally, do a hash comparison of the 2 images. This is a lot faster than doing a pixel compare. I found the hash compare method in a post from someone else and just adapted the answer here to fit. I was trying to think of the best way to do this myself for a project where I'm going to have to compare over 5200 images. After I read a few of the posts here I realized I already had everything I needed for it and figured I'd share.

public class CompareImages2
    {
        public enum CompareResult
        {
            ciCompareOk,
            ciPixelMismatch,
            ciAspectMismatch
        };

        public static CompareResult Compare(Bitmap bmp1, Bitmap bmp2)
        {
            CompareResult cr = CompareResult.ciCompareOk;

            //Test to see if we have the same size of image
            if (bmp1.Size.Height / bmp1.Size.Width == bmp2.Size.Height / bmp2.Size.Width)
            {
                if (bmp1.Size != bmp2.Size)
                {
                    if (bmp1.Size.Height > bmp2.Size.Height)
                    {
                        bmp1 = (new Bitmap(bmp1, bmp2.Size));
                    }
                    else if (bmp1.Size.Height < bmp2.Size.Height)
                    {
                        bmp2 = (new Bitmap(bmp2, bmp1.Size));
                    }
                }

                //Convert each image to a byte array
                System.Drawing.ImageConverter ic = new System.Drawing.ImageConverter();
                byte[] btImage1 = new byte[1];
                btImage1 = (byte[])ic.ConvertTo(bmp1, btImage1.GetType());
                byte[] btImage2 = new byte[1];
                btImage2 = (byte[])ic.ConvertTo(bmp2, btImage2.GetType());

                //Compute a hash for each image
                SHA256Managed shaM = new SHA256Managed();
                byte[] hash1 = shaM.ComputeHash(btImage1);
                byte[] hash2 = shaM.ComputeHash(btImage2);

                //Compare the hash values
                for (int i = 0; i < hash1.Length && i < hash2.Length && cr == CompareResult.ciCompareOk; i++)
                {
                    if (hash1[i] != hash2[i])
                        cr = CompareResult.ciPixelMismatch;

                }
            }
            else cr = CompareResult.ciAspectMismatch;
            return cr;
        }
    }
like image 65
Veritoanimus Avatar answered Oct 05 '22 00:10

Veritoanimus


One idea to achieve this:

If the image is 10x10, and your original is 40x40

Loop each pixel in the 10x10, then retrieve the 4 pixels representative of that looped pixel.

So for each pixel in the smaller image, find the corresponding scaled amount of pixels in the larger image.

You can then take the average colour of the 4 pixels, and compare with the pixel in the smaller image. You can specify error bounds, IE -10% or +10% bounds are considered a match, others are considered a failure.

Build up a count of matches and failures and use the bounds to determine if it is considered a match or not.

I think this might perform better than scaling the image to the same size and doing a 1pixel:1pixel comparison as I'm not sure how resizing algorithms necesserially work and you might lose some detail which will give less accurate results. Or if there might be different ways and methods of resizing images. But, again I don't know how the resize might work depends on how you go about doing it.

like image 42
Tom Gullen Avatar answered Oct 05 '22 00:10

Tom Gullen