如何将Image对象与C#.NET进行比较?

时间:2010-08-02 04:22:29

标签: c# .net testing image bitmap

我们可以用C#比较两个Image个对象吗?例如,检查它们是否相等,或者甚至更好地检查它们的像素有多相似?

如果可能,怎么样?

3 个答案:

答案 0 :(得分:12)

您可以使用一组名为TestApi的工具,这是一个开源库,可以帮助进行单元测试。其中一个API称为Visual Verification API,它完全符合您的需求 - 它可以比较两个图像并告诉您它们是否相等:

// 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);
}

答案 1 :(得分:4)

最简单的起点是尺寸。如果维度不相等,您可以将它们声明为假。

如果你需要逐个像素地浏览它们,你需要两个for循环。这些方面的东西:

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;
         }
     }
}

它是伪代码(函数存在于C#中,虽然我现在无法回想起它们)并且非常简单,但是你想要执行基本的像素到像素检查。

但是,请注意,要使该循环起作用,图像必须具有相同的尺寸。如果不是,如果您尝试对较小区域外的像素进行采样,则可能会出现例外情况。比较像素也不会非常快,因此您可能希望找到另一种方法来首先丢弃可能的重复项。

编辑:我不确定如何在Image上执行此操作,但对Bitmap来说非常简单。没有一种可见的方法可以将Image像素数据从类中取出。但是看起来Bitmaps继承自Images,所以这可能仍然有用。鉴于Images是Bitmaps和Metafiles的抽象类,它们可能没有简单的内部像素列表。

答案 2 :(得分:1)

我今天有同样的问题,我的解决方法是将image1和image2转换为256x256或128x128两者都翻译然后生成一个image3与它们之间的差异,然后扫描image3检查差异并返回差异数量,我发现LOWER差异量%对图像的影响更大,并且它们更可能相等。这样,即使图像大小不同,也可以识别图像是否相等。这是代码。

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;
    }

在这里测试了900多张图片,它就像魅力x)