泥庭

2013年5月18日

手書き文字を認識する

Filed under: .NET, ストアアプリ, Windows8 — タグ: , , , — yone64 @ 3:58 午後

WindowsStoreAppではInkManagerクラスを利用することで、比較的簡単に手書き文字を認識することができます。

サンプルはGitHubにあげてありますので、そちらを参照ください。

まず、GetRecognizersメソッドでInkRecongizerのコレクションを取得し、その中から日本語のInkRecongizerをDefaultRecognizerに設定します。

// 文字識別用のInkRecognizerを取得する。
var recongnizer =
    inkmanager.GetRecognizers()
    .FirstOrDefault(r => r.Name.Contains("日本語"));

// 取得できた場合はInkManagerに設定
if (recongnizer != null)
{
    inkmanager.SetDefaultRecognizer(recongnizer);
}

次に、PointerPressed/PointerMoved/PointerReleasedの各イベントで、それぞれInkManager.ProcessPointerXXXXメソッドを呼び出し手書き情報をInkManagerに認識させます。なお、InkManagerには書き順も認識させないといけないため、PointerPress時のPointerIdを保持し異なる入力イベントが同時に発生することを抑制しています。

// 描画開始
private void Canvas_PointerPressed(object sender, PointerRoutedEventArgs e)
{
    // 入力中のPointerがある場合は、新しい入力は開始しない。
    if (pid != null)
    {
        return;
    }

    // PointerPointの取得
    var canvas = sender as Canvas;
    var point = e.GetCurrentPoint(canvas);

    // 線の初期化
    polyline = new Polyline
    {
        StrokeThickness = 3,
        Stroke = new SolidColorBrush(Colors.Red)
    };

    // 線に頂点を追加
    polyline.Points.Add(point.Position);

    // Canvasに登録して描画
    canvas.Children.Add(polyline);

    // MoveイベントがCanvasで発生するようにキャプチャ
    canvas.CapturePointer(e.Pointer);

    // InkManagerに描画が始まったことを通知
    inkmanager.ProcessPointerDown(point);

    // PointerIdを保持
    pid = point.PointerId;
}

// 描画中
private void Canvas_PointerMoved(object sender, PointerRoutedEventArgs e)
{
    // PointerPointの取得
    var canvas = sender as Canvas;
    var point = e.GetCurrentPoint(canvas);

    // 開始した描画ポイントととこなる場合は、処理しない。
    if (pid != point.PointerId) return;

    // InkManagerに描画ポイントを追加
    polyline.Points.Add(point.Position);

    // InkManagerに描画ポイントの追加
    inkmanager.ProcessPointerUpdate(point);
}

// 描画終了
private void Canvas_PointerReleased(object sender, PointerRoutedEventArgs e)
{
    // PointerPointの取得
    var canvas = (Canvas)sender;
    var point = e.GetCurrentPoint(canvas);

    // 現在描画中の入力デバイス以外からのイベントは受け取らない
    if (pid != point.PointerId)
    {
        return;
    }

    // マウスをリリース
    canvas.ReleasePointerCapture(e.Pointer);

    // InkManagerに描画が終わったことを通知
    inkmanager.ProcessPointerUp(point);
    pid = null;
}

最後にRecognizeAsyncを呼び出して、認識された文字列を取得します。

var rec = await inkmanager.
    RecognizeAsync(InkRecognitionTarget.All);

textBox1.Text =
    string.Join(",",
        rec.FirstOrDefault().GetTextCandidates()
    );

実行結果

スクリーンショット (17)

image

認識された文字列が、確度の高いものから順番に取得できます。

 

WordPress.com Blog.