C#图像识别性能-将图像列表与图像字典进行比较

本文关键字:图像 字典 比较 列表 性能 图像识别 | 更新日期: 2023-09-27 18:25:02

我已经设法从图像中识别出了字符。因此:

我将所有识别的斑点(图像)保存在列表中

        Bitmap bpt1 = new Bitmap(@"C:'2'torec1.png", true);
        Bitmap bpt2 = new Bitmap(@"C:'2'torec2.png", true);
        List<Bitmap> toRecognize = new List<Bitmap>();
        toRecognize.Add(bpt1);
        toRecognize.Add(bpt2);

我在字典里保存了一个已知字母库。

            Bitmap le = new Bitmap(@"C:'2'e.png", true);
            Bitmap lg = new Bitmap(@"C:'2'g.png", true);
            Bitmap ln = new Bitmap(@"C:'2'n.png", true);
            Bitmap li = new Bitmap(@"C:'2'i.png", true);
            Bitmap ls = new Bitmap(@"C:'2's.png", true);
            Bitmap lt = new Bitmap(@"C:'2't.png", true);
            var dict = new Dictionary<string, Bitmap>();
            dict.Add("e", le);
            dict.Add("g", lg);
            dict.Add("n", ln);
            dict.Add("i", li);
            dict.Add("s", ls);
            dict.Add("t", lt);

然后我用图片创建新列表-来自库:

var target = dict.ToList();

并对图像进行比较:(target[index].Key,target[inded].Value)

for (int i = 0; i < x; i++)
{
   for (int j = 0; j < y; j++)
   {
       if (CompareMemCmp(toRecognize[i], target[j].Value) == true)
       {
       textBox3.AppendText("Found!" + Environment.NewLine);
       textBox2.AppendText(target[j].Key); //Letter is found - save it!
       }
       else {textBox3.AppendText("Don't match!" + Environment.NewLine); }
   }
}

1.[已删除]

2.从性能的角度来看,我使用的方法可以容忍吗我计划同时对10-20个图像进行识别(每个图像的平均字母数为8),字母库将由英文字母表(大写26+小写26)、特殊字母(~10)和数字(10)组成。

所以我有80多个必须识别的字母和由70多个字符组成的模式库。表现会达到好的水平吗?

建设性的批评欣然接受

C#图像识别性能-将图像列表与图像字典进行比较

问题1:

[已删除]

问题2:

这取决于情况
首先,如果性能不够,您的瓶颈是什么
我怀疑是CompareMemCmp()函数。。。你能加快速度吗?

如果不是,考虑到循环的每次迭代似乎都独立于之前的迭代,您可以尝试并行运行它
要做到这一点,请查看框架4.0的任务并行库方法,特别是Parallel.For

编辑:

如果我们谈论的是图像之间的完美匹配,您可以尝试使用字典查找来加快速度。

首先,您可以为Bitmap构建一个包装类,该类可以有效地用作Dictionary<>密钥,如下所示:

class BitmapWrapper
{
    private readonly int hash;
    public Bitmap Image { get; private set; }
    public BitmapWrapper(Bitmap img)
    {
        this.Image = img;
        this.hash = this.ComputeHash();
    }
    private int ComputeHash()
    {
        // you could turn this code into something unsafe to speed-up GetPixel
        // e.g. using lockbits etc...
        unchecked // Overflow is fine, just wrap
        {
            int h = 17;
            for (int x = 0; x < this.Image.Size.Width; x++)
                for (int y = 0; y < this.Image.Size.Height; y++)
                    h = h * 23 + this.Image.GetPixel(x, y).GetHashCode();
            return h;
        }
    }
    public override int GetHashCode()
    {
        return this.hash;
    }
    public override bool Equals(object obj)
    {
        var objBitmap = obj as Bitmap;
        if (obj == null)
            return false;
        // use CompareMemCmp in case of hash collisions 
        return Utils.CompareMemCmp(this.Image, objBitmap); 
    }
}

这个类计算受这个答案启发的ComputeHash方法中的hascode(但您可以只计算ex或每个像素)。这肯定可以通过包含不安全的代码(类似于CompareMemCmp方法)来改进。

一旦你有了这个类,你就可以构建一个这样的查找字典:

Bitmap le = new Bitmap(@"C:'2'e.png", true);
Bitmap lg = new Bitmap(@"C:'2'g.png", true);
...
var lookup = new Dictionary<string, Bitmap>();
lookup.Add(new BitmapWrapper(le), "e");
lookup.Add(new BitmapWrapper(lg), "g");
...

那么搜索将是简单的:

foreach(var imgToRecognize in toRecognize)
{
   string letterFound;
   if(lookup.TryGetValue(new BitmapWrapper(imgToRecognize), out letterFound))
   {
      textBox3.AppendText("Found!" + Environment.NewLine);
      textBox2.AppendText(letterFound); //Letter is found - save it!
   }
   else
      textBox3.AppendText("Don't match!" + Environment.NewLine);
}

这种方法的性能肯定取决于哈希计算,但它们肯定可以节省大量的CompareMemCmp()调用。

C#是否适合此项工作取决于图像的大小。哈希表是一种很好的方法,但在检查是否匹配之前,您需要比较整个图像。对图像进行xor非常快,但您需要对所有图像进行XO,直到找到匹配的图像,这是非常低效的。

一个更好的方法是选择一个指纹,它的设计方式是只需要读取最少量的数据。例如,如果你的图像会为每个图像产生不同的值,你可以在中间生成一条垂直线的哈希码。如果不调整该方法,直到您找到一种算法,在该算法中,您不需要读取整个图像,而只需要读取几个字节,直到您可以将图像分配到正确的桶。只有当输入数据只包含字典中的图像时,这才有效。否则,这将只是一种概率方法。