开发者

How to compare Image objects with C# .NET? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.

Want to improve this question? Update the question so it focuses on one problem only by editing this post.

Closed 8 years ago.

开发者_JAVA百科 Improve this question

Can we compare two Image objects with C#? For example, check whether they are equal, or even better check how similar are their pixels?

if possible, how?


You can use a set of tools called TestApi, which is an open-source library to aid unit testing. One of such API is called Visual Verification API, and it does exactly what you need - it can compare two images and tell you if they are equal:

// 1. Capture the actual pixels from a given window
Snapshot actual = Snapshot.FromRectangle(new Rectangle(0, 0, 100, 100));

// 2. Load the reference/master data from a previously saved file
Snapshot expected = Snapshot.FromFile("Expected.png"));

// 3. Compare the actual image with the master image
//    This operation creates a difference image. Any regions which are identical in 
//    the actual and master images appear as black. Areas with significant 
//    differences are shown in other colors.
Snapshot difference = actual.CompareTo(expected);

// 4. Configure the snapshot verifier - It expects a black image with zero tolerances
SnapshotVerifier v = new SnapshotColorVerifier(Color.Black, new ColorDifference());

// 5. Evaluate the difference image
if (v.Verify(difference) == VerificationResult.Fail)
{
    // Log failure, and save the diff file for investigation
    actual.ToFile("Actual.png", ImageFormat.Png);
    difference.ToFile("Difference.png", ImageFormat.Png);
}


The simplest place to start would be dimensions. If the dimensions are not equal, you may be able to declare them false.

If you need to go through them pixel-by-pixel, you'll need two for loops. Something along these lines:

Bitmap ImageA...
Bitmap ImageB...

for ( Int64 x = 0; x < ImageA.Width; x++ )
{
     for ( Int64 y = 0; y < ImageA.Height; y++ )
     {
         if ( ImageA.GetPixel(x, y) != ImageB.GetPixel(x, y) )
         {
            return false;
         }
     }
}

It's pseudo-code (the functions exist in C#, although I can't recall them at the moment) and very simplistic, but is how you'd want to perform a basic pixel-to-pixel check.

Note, however, for that loop to work the images must be of the same dimensions. If they aren't, you're likely to get exceptions if you try to sample a pixel outside of the smaller one's area. It also won't be terribly fast to compare the pixels, so you may want to find another way of discarding possible duplicates first.

Edit: I'm not sure how to do this on an Image, but it is quite simple for Bitmaps. There isn't a visible way of getting Image pixel data out of the class. It appears the Bitmaps inherit from Images, though, so this may still work. Given that Images are an abstract class for both Bitmaps and Metafiles, they may not have a simple internal pixel list.


I had the same question this very day, my workaround was to take image1 and image2 converted to 256x256 or 128x128 both translated AND then generate an image3 with the difference between them, then scan image3 checking the differences and returning the difference amount, I found out that the LOWER difference amount in % more equal the images are and more likely for them to be equal. This way you can identify if images are equal even if they're differently sized. here is the code.

double CompareImages(Bitmap InputImage1, Bitmap InputImage2, int Tollerance)
    {
        Bitmap Image1 = new Bitmap(InputImage1, new Size(128, 128));
        Bitmap Image2 = new Bitmap(InputImage2, new Size(128, 128));
        int Image1Size = Image1.Width * Image1.Height;
        int Image2Size = Image2.Width * Image2.Height;
        Bitmap Image3;
        if (Image1Size > Image2Size)
        {
            Image1 = new Bitmap(Image1, Image2.Size);
            Image3 = new Bitmap(Image2.Width, Image2.Height);
        }
        else
        {
            Image1 = new Bitmap(Image1, Image2.Size);
            Image3 = new Bitmap(Image2.Width, Image2.Height);
        }
        for (int x = 0; x < Image1.Width; x++)
        {
            for (int y = 0; y < Image1.Height; y++)
            {
                Color Color1 = Image1.GetPixel(x, y);
                Color Color2 = Image2.GetPixel(x, y);
                int r = Color1.R > Color2.R ? Color1.R - Color2.R : Color2.R - Color1.R;
                int g = Color1.G > Color2.G ? Color1.G - Color2.G : Color2.G - Color1.G;
                int b = Color1.B > Color2.B ? Color1.B - Color2.B : Color2.B - Color1.B;
                Image3.SetPixel(x, y, Color.FromArgb(r,g,b));
            }
        }
        int Difference = 0;
        for (int x = 0; x < Image1.Width; x++)
        {
            for (int y = 0; y < Image1.Height; y++)
            {
                Color Color1 = Image3.GetPixel(x, y);
                int Media = (Color1.R + Color1.G + Color1.B) / 3;
                if (Media > Tollerance)
                    Difference++;
            }
        }
        double UsedSize = Image1Size > Image2Size ? Image2Size : Image1Size;
        double result = Difference*100/UsedSize;
        return Difference*100/UsedSize;
    }

Tested here with over 900 images and it works like a charm x)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜