C# 获得最相似的图像
我有一个位图A和一个位图数组,在数组中有一个看起来与位图A相同的位图。我正在使用下面的代码,但它有时不起作用,它迭代整个数组而没有找到它,似乎有一些细微的差异,如果函数90%相似,是否有方法将其更改为返回true,或者选择数组中最相似的图像?该阵列只有6个图像C# 获得最相似的图像,c#,bitmap,image-comparison,C#,Bitmap,Image Comparison,我有一个位图A和一个位图数组,在数组中有一个看起来与位图A相同的位图。我正在使用下面的代码,但它有时不起作用,它迭代整个数组而没有找到它,似乎有一些细微的差异,如果函数90%相似,是否有方法将其更改为返回true,或者选择数组中最相似的图像?该阵列只有6个图像 for(int i = 0; i < list.Count;i++) { if(ImageCompareString(image,list[i]) { answerI
for(int i = 0; i < list.Count;i++)
{
if(ImageCompareString(image,list[i])
{
answerIndex = i;
break;
}
}
private static bool ImageCompareString(Bitmap firstImage, Bitmap secondImage)
{
MemoryStream ms = new MemoryStream();
firstImage.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
String firstBitmap = Convert.ToBase64String(ms.ToArray());
ms.Position = 0;
secondImage.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
String secondBitmap = Convert.ToBase64String(ms.ToArray());
if (firstBitmap.Equals(secondBitmap))
{
return true;
}
else
{
return false;
}
}
for(int i=0;i
当然有这样的方法……但你必须自己编码
首先您不应该比较base64数据……由于UTF16,您将失去直接的像素值访问,并将要比较的数据的大小在C#中增加150%以上(最初是200%,但由于PeterDuniho的评论而更正)。Second我假设所有图片都具有相同的固定大小。在比较之前,请将图像大小减小到非常小的大小,但保持宽度/高度。这将加快比较速度并消除噪音。
Third迭代两张图片并比较它们的灰度像素值。我假设您已将图片大小调整为16x16。因为我们正在比较它们的灰度值,所以一个像素的值介于0和255之间。因此两张图片之间的最大距离将为
16*16*256=65536
。如果两张图片都是黑色,图片之间的距离为零(100%相似性)。如果一张图片为黑色,另一张图片为白色,则距离为65535(0%相似性)
要比较图像,请迭代图片像素,并从点x,y
处的grayscale-pixel-value-of-picture-a
减去grayscale-pixel-value-of-picture-b
,然后将绝对差值添加到计数器中。此计数器将是两张图片之间的总距离。
假设此计数器的值为1000,在比较循环后,两张图片之间的相似性百分比相差1000/65535
~1.5%(或98.5%)
伪比较码
long counter = 0;
long total = image.Width * image.Height * (Color.White - Color.Black);
for(int x = 0; x < image.Width; x++)
{
for(int y = 0; y < image.Height; y++)
{
var p1 = image.GetPixel(x, y);
var p2 = otherImage.GetPixel(x, y);
var g1 = ((p1.R + p1.G + p1.B) / 3);
var g2 = ((p2.R + p2.G + p2.B) / 3);
var distance = Math.Abs(g1 - g2);
counter += distance;
}
}
var similarity = 100 - ((counter / total) * 100);
长计数器=0;
长总计=image.Width*image.Height*(Color.White-Color.Black);
对于(int x=0;x
这或多或少是一种简单的方法,但您必须在场景/图像中对此进行测试。您不必比较灰度值,还可以比较rgb值。查找距离定义,如欧几里德距离……开始并继续阅读:)
编辑这只是一个非常基本的方法,应该解释如何开始比较图像。它不考虑可能存在不同的图像格式(jpeg、png、gif)、颜色格式(索引、16位、24位、32位)或具有不同分辨率的图像。转换为base64不会“松动[sic]”像素值。他们只是得到了不同的代表。首先是转换为PNG会阻止有效的比较。base64的数据大小“仅”增加了33%。即使考虑到二进制中的6位被转换为16位(因为C#字符串是UTF16),这“只是”大小增加了167%,而不是“超过[sic]200%”。虽然缩小图像大小可以提高速度,但它确实会丢失像素信息,转换为灰度也是如此。请考虑,例如,将纯色图像与其他纯色图像进行比较。@ PtEddUnIO你是对的,像素值的表示方式不同,但是这使得在X点、Y和I点上访问像素值变得更加困难(个人)只看到Base64转换中的缺点。通过向下和灰度缩放丢失的像素信息是正确的(并且可能是需要的),在大多数情况下16x16肯定很小,但更容易解释如何开始比较图像和获得第一个结果的步骤。有了这第一个结果,他可以开始调整参数,如大小或rgb/灰度或使用的距离。。。