先日、画像内の単純なテキストを認識する必要がありましたが、アルゴリズムを実装する必要はまったくありませんでした。 私は理論に精通しており、これはそれほど単純な問題ではないことを知っているので、すぐに既製のライブラリの市場を最初に調べることにしました。 グーグルへのいくつかのリクエストと私は、tessnet2ライブラリとして私にふさわしいものが見つからないことに気づきました。 私はHabrを絶えず読んでおり、OCRの理論に関する記事がたくさんあることを知っています。そして、tessnet2ライブラリについて何もないことに非常に驚きました。
tessnet2はTesseract OCRに基づいています
Tesseract OCRエンジンは、1995年にUNLV精度テストで導入された3つの最高のエンジンの1つです。 1995年から2006年の間に、わずかに変更されましたが、おそらくオープンソースで利用できる最も正確なOCRエンジンの1つです。 使用可能なコードは、バイナリ画像、グレー画像、またはカラー画像を読み取り、テキストを表示します。 TIFF読み取りは、非圧縮のTIFFイメージを読み取るように設計されています。または、Libtiffを追加して圧縮イメージを読み取ることができます。
Tessnet2の使用方法:
1. ライブラリをダウンロードし、.NETプロジェクトのTessnet2.dllへのリンク(参照)を追加します。
2.必要な言語をダウンロードし(個人的には英語が必要です)( tesseract-2.00.eng.tar.gz )、それをtessdataフォルダーに入れます。 tessdataフォルダーは、アプリケーションの実行可能ファイルの隣にある必要があります。
画像からテキストを読み取るには、そのようなテキストで十分です。
Bitmap image = new Bitmap ( "eurotext.tif" );
tessnet2.Tesseract ocr = new tessnet2.Tesseract();
ocr.SetVariable( "tessedit_char_whitelist" , "0123456789" ); // If digit only
ocr.Init( @"c:\temp" , " eng " , false ); // To use correct tessdata
List <tessnet2.Word> result = ocr.DoOCR(image, Rectangle.Empty);
foreach (tessnet2.Word word in result)
Console .WriteLine( "{0} : {1}" , word.Confidence, word.Text);
* This source code was highlighted with Source Code Highlighter .
結果に非常に満足していたので、1つのプロジェクトのキャプチャを解決するために数か月前にサービスを台無しにしたことをすぐに思い出しました。すぐに良いことは何もなかったと思います。そこにスピードが必要でしたが、そこに到達できませんでした。に。 そのようなサービスはそれを提供することができず、結果は通常嘆かわしく、理解可能である。 正しく入力された1000のキャプチャに対して$ 1から支払います。これは控えめに言ってもひどいです。 したがって、実験のために、その例を使用してこのライブラリを使用することにしました。
最初のデータはcaptchaになります。キャプチャでは、2つの数値に対して簡単なアクションを実行し、答えを取得する必要があります。 とても簡単に聞こえますが、問題はすべてのシンボルが異なる色であり、動的な背景があり、そこに書かれているものをすぐに理解するのが難しいことです。
すぐにプログラムの結果をお伝えします。その後、すべての仕組みを説明します。
スクリーンショットは、一連の行のためにライブラリが何も解決できないことを明確に示しています。完全に削除されていない背景も干渉する場合があります。 したがって、私は写真をきれいにするための小さなアルゴリズムを開発しましたが、そこには壮大なものはありません。端から数ピクセル離れて長方形を駆け抜けてそこに色を集め、最初の数字の後と記号の前に色を集めます(後者はよりハックですが、 .k。記事は別の記事に専念しているため、そのまま残されています)。 私がしなければならないのは、私のコレクションに来て、白ではないすべての色の上にペイントすることです。
すべてのアルゴリズムの中で、最も役立つのはビットマップの面積充填アルゴリズムのみです。
void FloodFill( Bitmap bitmap, int x, int y, Color color)
{
BitmapData data = bitmap.LockBits(
new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
int [] bits = new int [data.Stride / 4 * data.Height];
Marshal.Copy(data.Scan0, bits, 0, bits.Length);
LinkedList<Point> check = new LinkedList<Point>();
int floodTo = color.ToArgb();
int floodFrom = bits[x + y * data.Stride / 4];
bits[x + y * data.Stride / 4] = floodTo;
if (floodFrom != floodTo)
{
check.AddLast( new Point(x, y));
while (check.Count > 0)
{
Point cur = check.First.Value;
check.RemoveFirst();
foreach (Point off in new Point[] {
new Point(0, -1), new Point(0, 1),
new Point(-1, 0), new Point(1, 0)})
{
Point next = new Point(cur.X + off.X, cur.Y + off.Y);
if (next.X >= 0 && next.Y >= 0 &&
next.X < data.Width &&
next.Y < data.Height)
{
if (bits[next.X + next.Y * data.Stride / 4] == floodFrom)
{
check.AddLast(next);
bits[next.X + next.Y * data.Stride / 4] = floodTo;
}
}
}
}
}
Marshal.Copy(bits, 0, data.Scan0, bits.Length);
bitmap.UnlockBits(data);
}
}
* This source code was highlighted with Source Code Highlighter .
実験に興味がある人のために、 ソースコードを添付します 。
まとめ
かなり興味深いtessnet2ライブラリに精通し、実際の状態でその動作を確認し、複雑な画像(captcha)でかなり良い解決結果を達成しました。もちろんエラーもありますが、その数は無視できます。特にこのタイプのcaptchaでは、正規表現を使用してチェックを追加できます解かれたテキストが目的の形式に対応していることが確実にわかります。