2019年11月16日土曜日

棋譜OCRプログラムの軌跡(4-2)手順番号検出(黒石処理)

前回の処理で、石の位置と色が取得できました。今回は黒石の手順番号を検出します。切り取った黒石の画像を見ると、黒石の中に手順番号が白で描かれています。

切り取った画像を加工して、Tesseractで手順番号を検出します。
  1. 周囲の白を黒で埋める。
                for (int y = 0; y < h; y++)
                {
                    for (int x = 0; x < w / 2; x++)
                    {
                        if (!setBlack2Mat(matw, x, y)) break;
                    }
    
                    for (int x = w - 1; x > w / 2; x--)
                    {
                        if (!setBlack2Mat(matw, x, y)) break;
                    }
                }
    matw:一つの石を切り取った画像
    h     :matwの高さ
    w     :matwの幅
    切り取った画像の、左側・右側それぞれ 中央に向かい、関数 setBlack2Mat を使って、黒ピクセルが見つかるまで白ピクセルを黒に変更します。
    private Boolean setBlack2Mat(Mat matw, int x, int y)
    {
        var pix = matw.Get<vec3b>(y, x);
        int b = pix[0];
        int g = pix[1];
        int r = pix[2];
    
        if (!(r == 0 && g == 0 && b == 0) || x == 0 || y == 0)
        {
            pix[0] = 0;
            pix[1] = 0;
            pix[2] = 0;
            matw.Set<vec3b>(y, x, pix);
            return true;
        }
        else
        {
            return false;
        }
    }

    この処理で、文字部分のみ残し黒で埋められます。

    また 手順番号が無い黒石  の場合は、黒四角 になります。

  2. 文字検出処理
    周囲の白を黒で埋めた後、文字検出処理を実行します。
    //黒四角を判定
    if (Cv2.CountNonZero(matw) < 5)    return "--";
    
    //tesseract用のbitmapを準備する
    Bitmap bitmap = matw.ToBitmap();
    
    //  言語データの場所と言語名を引数で指定する
    var tesseract = new Tesseract.TesseractEngine(@"C:\temp\tessdata", "eng");
    // 数字のみ認識するよう指定する
    tesseract.SetVariable("tessedit_char_whitelist", "1234567890");
    // OCRの実行
    Tesseract.Page page = tesseract.Process(bitmap);
    string str = page.GetText();
    return str.Trim();
    matw :1.の処理で周囲の白を黒で埋めたMat
    このMatに 黒(0,0,0)以外のピクセルが4以下の場合、黒四角とみなし手順番号無し("--")を返します。
    以外、OCRを行うオブジェクト tesseractを生成し、数字のみ検出します。

    この状態で、文字を検出した結果を見ると 以下のようになります。

    【元の画像】

    【検出結果を電子碁盤用に表示した結果】
    (8,16) (9,16) (10,13) (11,15)の石の文字が認識できず ”??”と表示されています。
  3. 周囲を黒マージンで囲んだ後文字検出
                //黒四角を判定
                if (Cv2.CountNonZero(matw) < 5)  return "--";
    
                //縦横3倍のMatを準備する
                Mat mat = new Mat(matw.Width * 3, matw.Height * 3, MatType.CV_8UC1, Scalar.Black);
                
                //中央に貼り付け
                var rect = new OpenCvSharp.Rect(matw.Width, matw.Height, matw.Width, matw.Height);
                mat[rect] = matw;
                
                //tesseract用のbitmapを準備する
                Bitmap bitmap = mat.ToBitmap();
                
                //  言語データの場所と言語名を引数で指定する
                var tesseract = new Tesseract.TesseractEngine(@"C:\temp\tessdata", "eng");
                tesseract.SetVariable("tessedit_char_whitelist", "1234567890");
                
                // OCRの実行
                Tesseract.Page page = tesseract.Process(bitmap);
                string str = page.GetText();
                return str.Trim();

    周囲に黒マージンを加えたことにより、2.で検出不能だった石の手順番号が検出できました。






開発環境
 OS:Windows10
 言語:C#(WPF使用)
 IDE:VisualStudio2019
 仕様Tool:OpenCvSharp v4.0.0.20181129
      Tesseract v3.3.0.0
 使用電子本:電子書店パピレスのNHK 囲碁講座 テキスト

0 件のコメント:

コメントを投稿