How to compare two images?

前端 未结 3 524
误落风尘
误落风尘 2020-12-02 02:37
public void winCheck()
{
    if (button1.Image == img1)
    {
        w1 = \"P2\";
        button1.Image = new Bitmap(@\"win_cross.png\");
        button2.Image = ne         


        
相关标签:
3条回答
  • 2020-12-02 03:11

    Here is one possibility to do it, if you can have unsafe code and if you want images to be exactly the same on byte level:

    public unsafe static bool AreEqual(Bitmap b1, Bitmap b2)
    {
        if (b1.Size != b2.Size)
        {
            return false;
        }
    
        if (b1.PixelFormat != b2.PixelFormat)
        {
            return false;
        }
    
        if (b1.PixelFormat != PixelFormat.Format32bppArgb)
        {
            return false;
        }
    
        Rectangle rect = new Rectangle(0, 0, b1.Width, b1.Height);
        BitmapData data1
            = b1.LockBits(rect, ImageLockMode.ReadOnly, b1.PixelFormat);
        BitmapData data2
            = b2.LockBits(rect, ImageLockMode.ReadOnly, b1.PixelFormat);
    
        int* p1 = (int*)data1.Scan0;
        int* p2 = (int*)data2.Scan0;
        int byteCount = b1.Height * data1.Stride / 4; //only Format32bppArgb 
    
        bool result = true;
        for (int i = 0; i < byteCount; ++i)
        {
            if (*p1++ != *p2++)
            {
                result = false;
                break;
            }
        }
    
        b1.UnlockBits(data1);
        b2.UnlockBits(data2);
    
        return result;
    }
    

    This compares images "literally" - all bytes need to be exactly the same. Other possibility would be to compare colours of pixels - then PixelFormats wouldn't have to be the same (taken from here):

    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 != bmp2.Size)
        {
            cr = CompareResult.ciSizeMismatch;
        }
        else
        {
            //Sizes are the same so start comparing pixels
            for (int x = 0; x < bmp1.Width 
                 && cr == CompareResult.ciCompareOk; x++)
            {
                for (int y = 0; y < bmp1.Height 
                             && cr == CompareResult.ciCompareOk; y++)
                {
                    if (bmp1.GetPixel(x, y) != bmp2.GetPixel(x, y))
                        cr = CompareResult.ciPixelMismatch;
                }
            }
        }
        return cr;
    }
    

    This can be however very slow. The same link contains an interesting idea of comparing hash values:

    using System;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.Security.Cryptography;
    
    namespace Imagio
    {
        public class ComparingImages
        {
            public enum CompareResult
            {
                ciCompareOk,
                ciPixelMismatch,
                ciSizeMismatch
            };
    
            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 != bmp2.Size)
                {
                    cr = CompareResult.ciSizeMismatch;
                }
                else
                {
                    //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;
                    }
                }
                return cr;
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-02 03:12

    Your code doesn't work because you are comparing the variables pointing to the images (i.e. in memory address) not the image data (pixels).

    See ImageComparer.Compare method. Has overloads to specify tolerance. It is available since VS2012.

    https://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.uitesting.imagecomparer.compare.aspx

    0 讨论(0)
  • 2020-12-02 03:23

    dont use double equal (==). use equals method. (if button1.Image.equals(img1)) // you code

    0 讨论(0)
提交回复
热议问题