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

I am looking for an EASY way to check if an image is a scaled version of another image. It doesn't have to be very fast, it just has to be “fair” for sure. And it is written in .NET. And for free.

I know, wishful thinking :-)

I’m sure, without even trying that converting a larger image to a smaller scale and comparing checksums does not work (especially if the smaller version was performed with other software, then .NET).

The next approach would be to zoom out and compare the pixels. But first of all, it seems that a very bad idea works with a loop over all the pixels with the bool comparison results, I'm sure some pixels will be a little or so ...

Any library comes to mind? Back at the university, we had some MPEG7 classes, so I’m thinking about using a combination of “statistics” such as tone distribution, brightness, etc.

Any ideas or links for this thread?

Thank you, Chris

+4
source share
7 answers

I think this will be your best decision. Check the aspect ratio first. Then scale the images to the smaller of 2 if they are not the same size. Finally, make a hash comparison of the two images. This is much faster than pixel comparison. I found a hash comparison method in a message from someone else and just adapted the answer here to fit. I tried to think of a better way to do this myself for a project where I would have to compare more than 5200 images. After I read a few posts, I realized that I already have everything I need, and decided that I would 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; } } 
+3
source

One idea to achieve this is:

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

Scroll each pixel 10x10, then extract 4 pixels representing this looped pixel.

So, for each pixel in the smaller image, find the corresponding increased number of pixels in the enlarged image.

Then you can take the average color of 4 pixels and compare with the pixel in the smaller image. You can specify the margin of error, IE ratings of -10% or + 10% are considered a coincidence, others are considered a failure.

Create a hit and fail counter and use borders to determine if this is considered a match or not.

I think this could be better than scaling an image to the same size and comparing 1pixel: 1pixel, as I'm not sure how resizing algorithms are needed, and you may lose some details that will give less accurate results. Or there may be different ways and methods of resizing images. But, again, I don’t know how the size will change, it depends on how you do it.

+1
source

Just scale the enlarged image to a smaller size, then compare each pixel, taking the absolute value of the difference in each of the red, green, and blue components.

Then you can set a threshold value to determine how close you should count it as a match, for example. if 95% + pixels are within 5% of the color value, you have a match.

Fuzzy matching is necessary because you may have artifact / anti-aliasing scaling effects.

+1
source

At some point you will have to iterate over the pixels. Something that is easy to implement but powerful enough is to calculate the difference between the individual color components (RGB) for each pixel, find the average value and see if it crosses a certain threshold. This, of course, is not the best method, but it should do for a quick check.

0
source

The easiest way is to simply zoom in to a smaller image size and compare the color difference. Since you do not know if the scaling is cubic or linear (or something else), you should accept a slight difference.

Do not forget to take the absolute value of each difference in pixels .;)

0
source

I would say something like Tom Gullen, except that I would simply reduce the larger image to a smaller size before comparing (otherwise you would just have hard math if you compare 25x25 with 30x30 or something else).

Another thing that I can consider depending on the size of the image is to scale them to a smaller image. those. if you have 4000x4000 and the other 3000x3000, then you can scale them to 200x200 and compare them with such sizes.

As others have said, you will need to perform a threshold check (preferably on color components) and decide which tolerances work best. I would suggest that this is probably best done through trial and error.

0
source

Having absolutely no authority or experience in this area, I am going to help you.

I would start by matching the proportions with a certain tolerance if you are not comparing cropped sections of images, which will make work a little more difficult.

Then I scan the pixels for the areas of similarity, without accuracy, the tolerance level is again needed. Then, when the area is similar, run in a straight line, comparing one with the other, and find another similar colored area. Black and white will be harder.

If you get hit, you will have two areas in a row with similar images. With two points, you have a link of length between them, and now you can see what scaling can be. You can also scale images at first, but this does not take into account cropped sections where aspects do not match.

Now select a random point in the original image and get the color information. Then, using the scale factor, find the same random point in another image and see if the color is checked. Do this several times with random dots. If many of them are similar, it is rather a copy.

Then you can mark it for further, more intensive processor verification. Either a pixel-by-pixel comparison, or something else.

I know that Microsoft (Photosynth) uses filters such as the "outline" (the look of the material in Photoshop) to remove the colors of the images and leave only square lines that leave only the "components" of the image to match (they correspond to the borders and overlapping).

For speed, I would break the problem into pieces and really think about how people decide that the two photos are similar. For a non-speedy, comprehensive color comparison, you will probably get there.

In short:

If a hole punched a piece of paper at random 4 times, then put it on two photographs, just seeing that the colors passing through you can determine if they are a likely copy and need additional verification.

0
source

All Articles