C#比较2个带容差的位图?

C#比较2个带容差的位图?,c#,image,bitmap,compare,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

我想比较两个位图,但有容差。我当前的代码只在两个图像完全相同时才显示“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;
}
公共静态比较结果比较(位图bmp1、位图bmp2)
{
CompareResult cr=CompareResult.ciCompareOk;
//测试看我们是否有相同大小的图像
如果(bmp1.Size!=bmp2.Size)
{
cr=比较结果;Crizemismatch;
}
其他的
{
//大小相同,所以开始比较像素
对于(int x=0;x
对于图像的“不同”程度,有一些可能的测试用例,您需要采取的“匹配”方法变得越来越困难

  • 简单的情况是,您希望图像的大小相同,并且包含相同的特征,除了像素在您陈述时稍微亮一点或暗一点之外。例如,如果要将位图图像保存一次为24位,然后再次保存为8位(无抖动)。这两幅图像在同一位置具有相同的特征,但每个像素的颜色略有不同
  • 另一种可能是,拍摄位图图像,裁剪左侧的一行像素以创建第一个图像,然后裁剪右侧的一行以创建第二个图像
  • 第三种可能是保存位图图像,然后在两个方向上将图像大小加倍以创建第二个(因此源中的一个像素变为输出中的四个像素)。我承认您已经有了尺寸检查代码来检测这个案例
  • 第四种可能性(更多的是测试用例)是有一个白色的大图像,和一个黑色的大图像。我们希望它返回
    cipixelsmismatch
    ,但不会引发异常

如果我们只考虑第一种情况,那么你真正想要的是一个函数来比较两个<代码>颜色< /代码> s,并返回一个值,看看它们有多么不同。比较两种颜色的一种简单方法是计算红色、绿色和蓝色分量之间的毕达哥拉斯距离,例如

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(当
颜色相同时)和198608(介于黑白之间,即
Math.Pow(256,2)*3
)之间的数字

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

const decimal errorThreshold=0.0001D
十进制总误差=0;
对于(int x=0;xerrorThreshold)cr=CompareResult.ciPixelMismatch;
(我除以
198608D
,以避免加法时出现整数溢出的可能性。
averageError
是一个介于相同的
0D
和完全不同的
1D
之间的值。)

我还建议您看看StackOverflow上的其他一些问题。虽然这种像素颜色匹配适用于最简单的情况,但它不适用于其他情况。如果您需要更复杂的内容,其他问题答案中给出的方法将非常有用:

希望这有帮助

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;