我想比较两个位图,但可以与公差进行比较。我当前的代码仅在两个图像完全相同时说" 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;
}
有一些可能的测试用例,即"不同"图像的样子,而您需要采用的方法变得更加困难。
- 简单的情况是,您期望图像的大小相同并包含相同的功能,除了像素时稍微稍微浅或暗。例如,如果您要保存一个位图映像为24位,则再次为8位(无抖动(。这两个图像在同一位置将具有相同的特征,但每个像素的颜色略有不同。
- 另一种可能性是您拍摄位图图像,然后裁剪左图1行以创建第一个图像,然后将一条线从右边的右图中裁剪成第二张图像。
- 第三可能性是您保存位图图像,然后在两个方向上将图像大小加倍以创建第二个(因此,源中的一个像素成为输出中的四个像素(。我接受您的大小检查代码已经检测到这种情况。
- 第四种可能性(更多的测试用例(是只有大的白色图像,而只是黑色的大图像。我们希望这将返回
ciPixelMismatch
,但不会出现例外。
如果我们仅考虑第一种情况,那么您真正想要的是比较两个Color
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(当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上查看其他一些问题。尽管此像素颜色匹配适合最简单的情况,但它对其他情况不起作用。如果您需要更复杂的内容,则对其他问题的答案中给出的方法将很有用:
- 比较两个图像的算法
- 算法比较C# 中的两个图像
- 图像比较 - 快速算法
希望这有帮助