2012-02-19 10 views
1

画像から文字を認識することができました。この理由のために:C#画像認識性能 - 画像リストと画像辞書を比較する

私はリスト

 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); 

内のすべての認識の塊(画像)を保存私は辞書で知られている文字のライブラリーを保ちます。

var target = dict.ToList(); 

や画像の比較を行う:(ターゲット[インデックス] .KEY、ターゲット[インデックス] .Valueの)

をライブラリから - その後

  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); 

私がイメージして新しいリストを作成します

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 +文字で構成されるパターンライブラリを持っています。パフォーマンスは良いレベルになるのでしょうか?

喜んで受け入れられています。 ;)

+0

break;ループが壊れて2番目の質問が残る – Alex

+0

イメージ認識を行うには、巨大な並列コンピューティングハードウェアが必要です。 OpenCVは、このような種類のタスクによく使用されるライブラリです。高度に最適化されたSIMDコードは、そのようなハードウェアに似ています。 Emguは.NETラッパーです。 http://www.emgu.com/wiki/index.php/Main_Page –

+0

C#がパフォーマンスのボトルネックの原因になることはありません。これは単一のCPU上で行うことができますが、GPU実装を動かすことで*ロット*(速さのように)速くなります。 Cloo OpenCLライブラリを見てください。 –

答えて

2

質問1:

[削除]

質問2:

それが依存しています。
まず、パフォーマンスが十分でない場合、ボトルネックは何ですか?
私はそれがCompareMemCmp()の機能だと思うので...スピードアップできますか?

ループの各反復が前の反復とは独立しているようであれば、並列実行することができます。
これを行うには、フレームワーク4.0のタスク並列ライブラリメソッド、特にParallel.Forを参照してください。

EDIT:

我々はおよそ完璧な画像間ののマッチングを話している場合、あなたは物事をスピードアップするために辞書ルックアップを使用しようとすることができます。

まず、あなたはこのように、効率的に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); 
    } 
} 

このクラスはthis answerに触発されComputeHash方法でhascodeを計算(ただし、あなたができますちょうど元またはすべてのピクセル)。安全ではないコード(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()呼び出しを保存することができます。

+0

CompareMemCmp()は、私が今まで見た中で最も速いビットマップ比較方法の1つです(安全ではありません)。ありがとう、私はParallel.Forの詳細を掘り下げます。多分それが私が探しているものです。 "まず第一に、パフォーマンスが十分でない場合、ボトルネックは何ですか? - 私は0.5秒以内に15枚の画像を認識することを期待しています – Alex

+0

@Alex:申し訳ありませんが、私はCompareMemCmpを知らないので、ベースライブラリにはありません。私はそれが1つの[ここ](http://stackoverflow.com/questions/9348946/c-sharp-bitmap-comparison-pinvokestackimbalance-exception)と報告されているのではないでしょうか?もしそうなら、それはほとんど変わろうとは思わない。つまり、あなたのコードではパフォーマンスの問題は見られません。並列処理を利用すると、おそらくn倍速くなります(nはPCのコア/コアの数です)。 – digEmAll

+1

@Alex:確かにあなたは完璧なイメージマッチングについて話していますか(つまり、2つの比較されたビットマップは完全に等しい)、そうですか?もしそうなら、あなたはイメージのハッシュコードを計算することができます(例えば、バイトを捨てる)。そして辞書検索を利用する。私はそれが速くなる(ハッシュ計算が長くなる可能性があるので)が分かりませんが、試してみる価値があるかもしれません... – digEmAll

2

C#がジョブの適切なツールである場合、画像の大きさによって異なります。ハッシュテーブルは素晴らしいアプローチですが、一致するかどうかを確認する前に、イメージ全体を比較する必要があります。画像をXoringするのは非常に高速ですが、非常に非効率なものを見つけるまですべての画像をXORする必要があります。

より良いアプローチは、最小限のデータだけを読み取るように設計された指紋を選択することです。例えば。画像のそれぞれに異なる値を生成する画像の場合は、中央に縦線のハッシュコードを生成することができます。そうでない場合は、画像を右のバケットに割り当てるまで、画像全体を読む必要はなく、数バイトしか読み込まないアルゴリズムに到達するまでアプローチを調整します。これは、入力データに辞書の画像のみが含まれている場合にのみ機能します。さもなければ、それは確率的方法でしかない。

+0

スマートなアイデアかもしれません。とにかく、それらを辞書に入れるためにリスト内のすべての画像を取り出すことは、検索された画像をリスト内のすべての画像と比較するために計算上等しい。辞書が一杯になるとハッシュコードが格納されている場合)、さらに比較するための速度がはるかに高くなります。 1つ以上のルックアップが必要な場合は、もちろんこれは価値があります。 – digEmAll

+0

エクセルは非常に速いですが、画像のサイズによっては問題になるかもしれません。あなたが完全なイメージを必要としていないことが分かっている場合は、マッチングを行うためにイメージの関連する部分だけを読み込んでメモリをスペアすることができます。これはIO帯域幅の大幅な節約につながる可能性があります。 –