C#比较2位图和容差?

时间:2018-02-06 23:35:38

标签: c# image bitmap compare

我想比较两个位图,但是要容忍。我的当前代码仅在两个图像完全相同的情况下才会显示“ciCompareOk”。

两者的尺寸和形状相同,有时颜色较深或较浅 怎么看起来容忍?

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

1 个答案:

答案 0 :(得分:0)

对于“不同”图像的可能性,有一些可能的测试用例,而你需要采取的“匹配”它们的方法变得越来越难。

  • 简单的情况是您希望图像具有相同的大小并包含相同的功能,除了像您声明的像素稍微更浅或更暗。例如,如果要将位图图像保存为24位,则再次保存为8位(不抖动)。这两个图像在同一个地方具有相同的功能,但每个像素的颜色略有不同。
  • 另一种可能性是拍摄位图图像,然后裁剪左边的1行像素以创建第一张图像,然后从右边裁剪第二张图像的线条。
  • 第三种可能性是保存位图图像,然后在两个方向上将图像尺寸加倍以创建第二个(因此源中的一个像素在输出中变为四个像素)。我接受你已经有大小检查代码来检测这种情况。
  • 第四种可能性(更多的测试用例)是只有白色的大图像和只有黑色的大图像。我们希望这会返回ciPixelMismatch,但不会抛出异常。

如果我们只考虑第一种情况,那么你真正想要的是比较两个Color并返回一个值的函数。比较两种颜色的简单方法是计算红色,绿色和蓝色成分之间的毕达哥拉斯距离,例如

static int CompareColours(Color x, Color y)
{
    return (int)(Math.Pow((int)x.R - y.R, 2) + Math.Pow((int)x.B - y.B, 2) + Math.Pow((int)x.G - y.G, 2));
}

这将返回0(当Color s相同时)和198608(黑白之间,Math.Pow(256, 2) * 3)之间的数字。

这样,您可以将函数应用于每对像素(每个图像一个)并累积错误。在像素数上平均此误差,以确定整个图像的平均像素误差,然后将其与阈值进行比较,以确定它们是否“相同”:

const decimal errorThreshold = 0.0001D
decimal totalError = 0;
for (int x = 0; x < bmp1.Width; x++)
{
    for (int y = 0; y < bmp1.Height; y++)
    {
        totalError += CompareColours(bmp1.GetPixel(x, y), bmp2.GetPixel(x, y)) / 198608D;
    }
}
decimal averageError = totalError / (bmp1.Width * bmp1.Height);
if ( averageError > errorThreshold ) cr = CompareResult.ciPixelMismatch;

(我除以198608D以避免在添加时出现整数溢出的可能性。averageError然后是0D对于相同的值和1D对于完全不同的值。 )

我还建议您在StackOverflow上查看其他一些问题。虽然这种像素颜色匹配适用于最简单的情况,但它不适用于其他情况。如果你需要更复杂的东西,那么在回答其他问题时给出的方法会很有用:

希望这有帮助