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多个字符组成的模式库。表现会达到好的水平吗?
建设性的批评欣然接受
问题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,直到找到匹配的图像,这是非常低效的。
一个更好的方法是选择一个指纹,它的设计方式是只需要读取最少量的数据。例如,如果你的图像会为每个图像产生不同的值,你可以在中间生成一条垂直线的哈希码。如果不调整该方法,直到您找到一种算法,在该算法中,您不需要读取整个图像,而只需要读取几个字节,直到您可以将图像分配到正确的桶。只有当输入数据只包含字典中的图像时,这才有效。否则,这将只是一种概率方法。