Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 获得最相似的图像_C#_Bitmap_Image Comparison - Fatal编程技术网

C# 获得最相似的图像

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

我有一个位图A和一个位图数组,在数组中有一个看起来与位图A相同的位图。我正在使用下面的代码,但它有时不起作用,它迭代整个数组而没有找到它,似乎有一些细微的差异,如果函数90%相似,是否有方法将其更改为返回true,或者选择数组中最相似的图像?该阵列只有6个图像

 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/灰度或使用的距离。。。