.NETによる光学式文字認識

たとえば、写真を数字で表示する人気のあるサイトに広告を作成しました。











番号自体は次のとおりです。







まず、このような写真に含まれるすべてのキャラクターの辞書が必要になるので、この電話からではなく、トレーニングから始めます。 これを行うために、同じ広告サイトで、考えられるすべての10桁を含む2つの電話を見つけて、1つの画像に接着しました。







各シンボルは、背景とマージされないことを強調し、各同じシンボルは同じ方法で描画されます。 まず、透明度を削除しましょう。



void RemoveAlphaChannel(Bitmap src) { for (int y = 0; y < src.Height; y++) for (int x = 0; x < src.Width; x++) { var pxl = src.GetPixel(x, y); if (pxl.A == 0) src.SetPixel(x, y, Color.FromArgb(255, 255, 255, 255)); } }
      
      







余分な部分を切り取ります



 private Bitmap CropImage(Bitmap sourceBitmap) { var upperLeft = GetCorner(sourceBitmap, true); var lowerRight = GetCorner(sourceBitmap, false); var width = lowerRight.X - upperLeft.X; var height = lowerRight.Y - upperLeft.Y; Bitmap target = new Bitmap(width, height); using (Graphics g = Graphics.FromImage(target)) { g.DrawImage(sourceBitmap, new Rectangle(0, 0, target.Width, target.Height), new Rectangle(ul, new Size(width, height)), GraphicsUnit.Pixel); } return target; }
      
      





GetCornerメソッドについては特に説明しません。 つまり、ピクセルごとに色を比較し、使用可能な領域を囲む四角形の左上または右下のポイントを返します。



次に、結果の画像を文字に解析し、コレクションに追加します。 私は左の文字で各反復を摘むアルゴリズムを使用しました:



 private void CropChars(Bitmap bitmapPattern, string stringPattern) { var croped = CropImage(bitmapPattern); RemoveAlphaChannel(croped); int cntr = 0; for (int x = 0; x < croped.Width; x++) { for (int y = 0; y < croped.Height; y++) { if ( (y == croped.Height - 1 && x > 0) || (x == croped.Width - 1 && x > 0) ) { var rect = new Rectangle(0, 0, x, croped.Height); //  if (_charInfoDictionary.FirstOrDefault(c => c.Char == stringPattern[cntr]) == null) _charInfoDictionary.Add(new CharInfo(CropImage(croped, rect), stringPattern[cntr])); ++cntr; if (croped.Width - x <= 1) return; croped = CropImage(croped, new Rectangle(x, 0, croped.Width - x, croped.Height)); x = 0; } if (!IsEmptyPixel(croped.GetPixel(x, y))) { break; } } } }
      
      







ここで重要な点は2です。



1. stringPatternは、用語「8929520-51-488926959-74-93」を表し、その各文字は文字のグラフィック表現に対応します。



2.シンボルを説明するエンティティ:



 public class CharInfo { //  public int[] _hsbSequence; //- ,     ,     (   ) private const int XPoints = 4; private const int YPoints = 4; //   public char Char { get; set; } //   public Bitmap CharBitmap { get; private set; } public CharInfo(Bitmap charBitmap, char letter) { Char = letter; CharBitmap = charBitmap; //      -  Bitmap resized = new Bitmap(charBitmap, XPoints, YPoints); _hsbSequence = new int[XPoints * YPoints]; int i = 0; //   *10.  ,  double  0.0()  1.0() for (int y = 0; y < YPoints; y++) for (int x = 0; x < XPoints; x++) _hsbSequence[i++] = (int)(resized.GetPixel(x, y).GetBrightness()*10); } /// <summary> ///     ,    /// </summary> /// <param name="charInfo"></param> /// <returns> </returns> public int Compare(CharInfo charInfo) { int matches = 0; for (int i = 0; i < _hsbSequence.Length; i++) { if (_hsbSequence[i] == charInfo._hsbSequence[i]) ++matches; } return matches; } }
      
      





ここで、広告内の数値に戻った後も、同様のコレクションをまとめるだけで(1つの違いは、各要素のシンボリック表現がスペースを占有します)、各要素を辞書と比較することだけです。



 public IEnumerable<CharInfo> Recognize(Bitmap bitmap) { RemoveAlphaChannel(bitmap); var charsToRecognize = CropChars(bitmap); List<CharInfo> result = new List<CharInfo>(); foreach (var charInfo in charsToRecognize) { CharInfo closestChar = null; int maxMatches = 0; foreach (var dictItem in _charInfoDictionary) { var matches = dictItem.Compare(charInfo); if (matches > maxMatches) { maxMatches = matches; closestChar = dictItem; } } result.Add(closestChar); } return result; }
      
      







その結果、鉄片が拾い上げてすべての数字を正しく配置したキャラクターのコレクションができました。



  StringBuilder sb = new StringBuilder(); foreach (var charInfo in charsToRecognize) sb.Append(charInfo.Char); textBox1.Text = sb.ToString();
      
      









文字「»」などのアルファベットの文字の認識は、コンポーネントを持ち、フレーミング長方形を見つけるためにより複雑なアルゴリズムを必要とするため、やや複雑ですが、比較アルゴリズム自体は同じです。



PSサードパーティのライブラリについては、その時点でいくつかのライブラリを見つけましたが、その中から(ただし、他のライブラリの名前を覚えていません)MicrosoftのMODIライブラリ(MS Officeの一部でした)を自分の目的のために選択しました。 彼女はテキストを完全に認識しました。 マイナスの点-1つのプロセスのコンテキストでは、1つの認識手順のみが機能します。 彼女はいくつかのスレッドに並列化したくなかっただけです。



All Articles