Tesseract OCRを使って3つの画像の文字を正しく認識できるか実験してみました。



(赤地に白)プレゼント員(惜しい!)
(黒地に白)レル2かさ(ぜんぜんダメ)
(白地に黒)プレゼント中(正しく認識できる)
白地の場合は正しく認識されましたが、黒地と赤地はうまくいきませんでした。黒地にいたっては全然ダメです。
そこで背景を白地に変換するにはどうすればいいかを考えます。
まず白黒にすることを考えましょう。
このサイトを参考にしました。
2値化して、1bppの白黒画像を作成する – .NET Tips (VB.NET,C#…)
白黒のビットマップはBitmapクラスのコンストラクタにPixelFormat.Format1bppIndexedを指定することで作成できます。しかし、
Bitmap srcBitmapを白黒化するとして
|
Bitmap newBitmap = new Bitmap( srcBitmap.Width, srcBitmap.Height, System.Drawing.Imaging.PixelFormat.Format1bppIndexed); |
これはいいのですが、
|
Graphics g = Graphics.FromImage(newBitmap); // これができない g.DrawImage(srcBitmap, new Point(0, 0)); |
コンパイルはできるのですが、実行すると例外が発生します。
|
for(int row = 0; row < srcBitmap.Height; row++) { for(int colum = 0; colum < srcBitmap.Width; colum++) { Color color = srcBitmap.GetPixel(colum, row); newBitmap.SetPixel(colum, row, color); // これもできない } } |
これもコンパイルはできるのですが、実行すると例外が発生します。
1bppのBitmapに色を付けるには、Bitmap.LockBitsメソッドを使うしかありません。
白黒化するにはピクセルの色の明るさが設定した閾値を越えれば白くし、越えなければ黒くするという方法をとります。色の明るさはColor.GetBrightnessメソッドで取得できます。
リンク先の記事の丸写しではおもしろくないので、白黒反転もできるようにしました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
|
using System.Drawing.Imaging; using System.Runtime.InteropServices; public static Bitmap Create1bppImage(Bitmap srcBitmap, float threshold, bool reverse) { //1bppイメージを作成する Bitmap newImg = new Bitmap(srcBitmap.Width, srcBitmap.Height, PixelFormat.Format1bppIndexed); //Bitmapをロックする BitmapData bmpData = newImg.LockBits( new Rectangle(0, 0, newImg.Width, newImg.Height), ImageLockMode.WriteOnly, newImg.PixelFormat); //新しい画像のピクセルデータを作成 byte[] pixels = new byte[bmpData.Stride * bmpData.Height]; for(int y = 0; y < bmpData.Height; y++) { for(int x = 0; x < bmpData.Width; x++) { //ピクセルデータの位置 int pos = (x >> 3) + bmpData.Stride * y; if(!reverse) { //明るさが閾値以上の時は白くする if(threshold <= srcBitmap.GetPixel(x, y).GetBrightness()) { //白くする byte b = (byte)(0x80 >> (x & 0x7)); pixels[pos] |= b; } } else { //明るさが閾値以下の時は白くする if(threshold >= srcBitmap.GetPixel(x, y).GetBrightness()) { byte b = (byte)(0x80 >> (x & 0x7)); pixels[pos] |= b; } } } } //作成したピクセルデータをコピー IntPtr ptr = bmpData.Scan0; Marshal.Copy(pixels, 0, ptr, pixels.Length); // ロックを解除 newImg.UnlockBits(bmpData); return newImg; } |
実験してみると赤のGetBrightnessを調べてみると0.5を超えているため、第二引数に0.5を指定すると、生成される画像は真っ白になります。適切な値に調整する必要があります(赤なら0.52以上にするとよい)。

これも実験してみました。
処理なし

なにも表示されない。
閾値50%で処理

当然、なにも表示されない。
閾値80%で処理

本日は5のつく日
EDZEI:生|
またはヤフーカード
ご利用額の+ %
閾値80%で処理して白黒反転

本日は5のつく日
PayPay残高
または ヤフーカード
ご利用額の+ %
白黒をはっきりさせたほうが精度はよくなります。また背景が黒の場合はあまりうまくいかないようです。
鳩でも分かるC#管理人からのお願い
できる仕事であれば請け負います。鳩でもわかるC#管理人はクラウドワークスに在宅ワーカーとして登録しています。お仕事の依頼もお待ちしております。
⇒ 仕事を依頼する
コメントについて
コメントで英語などの外国語でコメントをされる方がいますが、管理人は日本語以外はわからないので基本的に内容が理解できず、承認することもありません。それからへんな薬を売っているサイトやリンク先のサイトが存在しないというスパムコメントも多々あります。
Some people make comments in foreign languages such as English, but since the manager does not understand anything other than Japanese, he basically cannot understand the content and does not approve it. Please use Japanese when making comments.
そんななか日本語のコメントもいただけるようになりました。「○○という変数はどこで宣言されているのか?」「××というメソッドはどこにあるのか」「例外が発生する」「いっそのことソース丸ごとくれ」という質問ですが、管理人としては嬉しく思います。「自分が書いた記事は読まれているんだな」と。疑問点には可能な限り答えます。記事に問題があれば修正いたします。
そのうえでお願いがあります。「匿名」という味も素っ気もない名前ではなく、捨てハンでいいのでなにかハンドルネームをつくってほしいと思います。
管理人のモチベーションアップのために
よろしければご支援お願いします。
⇒ 管理人の物乞いリスト