2020年3月27日金曜日

棋譜OCRプログラムの軌跡(15)第二章 スキャナー取込

第一章では、電子本の棋譜図解読に成功したことを述べました。
しかし、解読できたのは Fix型で作成された、NHK 囲碁講座 テキストに限られ あまりにも狭い範囲 との印象はぬぐえません。

摘要範囲を広げようと
1)NHK 囲碁講座 テキストのより小さな棋譜でも解読できないか
  リフロー型対策
2)新聞に載っている囲碁記事の棋譜が解読できないか

等々試しましたが、それぞれ難題にぶつかり、早々に対応できるようには思えません。
対策できればBestですが・・

そこで、囲碁講座テキストをスキャナーで読み込んだイメージデータを入力し、解読する処理を実装することにしました。
1)スキャナーで読み込んだ画像を、回転し傾きを補正する。
  このとき図形の拡大・縮小表示も可能とする。
2)棋譜部分を指定し、棋譜部分の画像を取得する。




Window上部の2つのスライダーで画像の大きさ・傾き補正を行い、キャンバスの背景に設定します。
private void RotateResize()
{
    mat = src.Clone();
    if (degreeSlider.Value != 0)
    {
        Point2f center = new Point2f(src.Cols / 2, src.Rows / 2);
        Mat rMat = Cv2.GetRotationMatrix2D(center, -degreeSlider.Value, 1);
        Cv2.WarpAffine(src, mat, rMat, new OpenCvSharp.Size(src.Cols, src.Rows));
    }

    Mat dest = mat.Clone();
    if (sizeSlider.Value != 100)
    {
        double ratio = sizeSlider.Value * 0.01;
        Cv2.Resize(mat, dest, new OpenCvSharp.Size(mat.Width * ratio, mat.Height * ratio), 0, 0, InterpolationFlags.Cubic);
    }
    setBackgound(dest);
}

ここで
 src:スキャナーで取り込んだ画像
 degreeSlider:傾き補正用のスライダー -3° ~ +3°で0.1°刻みで 画像の中央(center)を中心と
    して、回転する角度を指定します。
    右回転を指示した場合、スライダーの値は(+)なので符号を反転することが必要です。
 sizeSlider:大きさ調整用のスライダー 10% ~ 110%で10%刻みで 調整します。
 setBackgound(dest):傾き・大きさを調整した結果をキャンバスの背景に設定する処理です。(後述参照)

上図は、スキャナーで取り込んだ画像を1.5°左回りした画像ですが、これをスライダーおよびスクロールバーを調整して下図のようにします。


次に、棋譜図を切り取る左上隅と右下隅を指定して、第一章で作成した棋譜解読処理に棋譜画像を引き渡します。
その結果下図のような解読結果が得られました。


(5,16)(10,7)の白石以外正常に解読できていることが分かります。

ちなみに、ここでテストに使った画像は、スキャナーで解像度を200DPIにして取り込んだ画像で、IrfanView 64を用いてわざと1.5°回転しています。

IrfanView 64での回転処理前の画像を入力にすると、全くノーエラーで解読できました。

さほどシビアに位置調整してスキャンしたわけではありませんが、スキャンが思いのほかうまくいっていたようです。回転処理をおこなうことにより、画像が微妙に劣化したものと思います。

結果紙ベースのテキストをスキャナーで読み取って、そのイメージデータを入力にする方法は、十分実用的な精度で使えることが分かりました。


大きさ・傾きを調整した画像は、Mat形式になっています。ところが、Canvasの背景はImageBrush形式にする必要があります。そのため以下の方法で変換を行いました。

private void setBackgound(Mat pmat)
{
    Bitmap bmp = new Bitmap(pmat.Cols, pmat.Rows);
    bmp = pmat.ToBitmap();
    System.Windows.Media.Imaging.BitmapSource bitmapSource;

    // ***********************************************************
    // MemoryStreamを利用した変換処理
    using (var ms = new System.IO.MemoryStream())
    {
        // MemoryStreamに書き出す
        bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
        // MemoryStreamをシーク
        ms.Seek(0, System.IO.SeekOrigin.Begin);
        // MemoryStreamからBitmapFrameを作成
        // (BitmapFrameはBitmapSourceを継承しているのでそのまま渡せばOK)
        bitmapSource =
            System.Windows.Media.Imaging.BitmapFrame.Create(
                ms,
                System.Windows.Media.Imaging.BitmapCreateOptions.None,
                System.Windows.Media.Imaging.BitmapCacheOption.OnLoad
            );
    }
    ImageBrush myImageBrush = new ImageBrush(bitmapSource);
    myCanvas.Width = bitmapSource.PixelWidth;
    myCanvas.Height = bitmapSource.PixelHeight;
    myCanvas.Background = myImageBrush;
}




開発環境
 OS:Windows10
 言語:C#(WPF使用)
 IDE:VisualStudio2019
 仕様Tool:OpenCvSharp v4.2.0.20200208
 使用本:NHK 囲碁講座 テキスト2020年3月号

 

0 件のコメント:

コメントを投稿