Windowsは手書き認識エンジンを持っている.というわけでそれを使ってみることにした.存在自体は知っていたけど,単にあたえられたものを文字として認識するだけだと思っていた.そうだとノート一ページ丸ごとあたえてもまともに解析してくれるとは思えない.実際にはきちんとレイアウトの解析までしてくれる模様.目的は「手書きノートに文字列を埋め込んだPDFを作る」こと.
実際にやってみた簡単なテスト.わかりやすくするため,認識した場所の上に赤文字で出しています.数式もないし,ということで文字単位では100%正しく認識されています.ただ,英単語が基本的にぶちぎられているので,検索で「This」とやってもひっかからない……意味ないし.適当に調整したらどうにかなるかなぁ.
WPFで作る.Windows.Formsやストアアプリでも作れるけど,方法が各々違うらしい.ストアアプリが一番楽で,というかそれ以外は追加でのインストールが必要.というわけで環境準備から.WDN Engineer's Blogに色々情報があるのでそれを参照.まずはWindows SDK for Vistaをインストール.Vistaって…….その後参照にIAWinFX.dllとIALoader.dllを追加.手元では以下のパスにあった.
- C:\Program Files\Reference Assemblies\Microsoft\Tablet PC\v1.7\IAWinFx.dll
- C:\Program Files\Microsoft SDKs\Windows\v6.0\Bin\IALoader.dll
更に,App.configのstartupを次のように書き換える.もともと
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
</startup>
となっていたので,
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
</startup>
とした.
これでSystem.Windows.Ink.InkAnalyzerが使えるようになっている.とりあえず解析させる.描かれたストロークの入っているStrokeCollectionクラスStrokesを解析させるには
using System.Windows.Ink;
using(var analyzer = new InkAnalyzer()){
analyzer.AddStrokes(Strokes);
analyzer.Analyze();
}
とする.これで解析結果がanalyzer内に格納される.やっぱりではあるけど,それなりに時間がかかる.とりあえず手元の目的が「解析結果をPDFに透明テキストで埋め込む」なので,時間は気にしないことにした.検索とかをしたい場合は考えないとなぁ.解析結果はツリー構造になっているらしい.なんだか色々タイプがあるみたいだが,簡単のためにツリー構造とかは一切無視し,さらに認識された単語のみを取り出すことにする.
using System.Windows.Ink;
using(var analyzer = new InkAnalyzer()){
analyzer.AddStrokes(Strokes);
analyzer.Analyze();
var nodes = analyzer.FindNodesOfType(ContextNodeType.InkWord);
foreach(var node in nodes) {
var rect = node.Location.GetBounds();
// 何か描画しているつもり
DrawString(((InkWordNode) node).GetRecognizedString(), rect.Left, rect.Bottom);
}
}
色々適当ですが大体こんな感じ.FindNodesOfTypeで指定したタイプ(この場合はInkWord=認識された単語)を列挙.もしツリー構造を反映したい場合はanalyzer.RootNodeからSubNodesをたどっていけばよいようです.例えば上と等価な処理としてはこんな感じ.
using System.Windows.Ink;
void Func(ContextNode node){
if(node.Type == ContextNodeType.InkWord){
var rect = node.Location.GetBounds();
DrawString(((InkWordNode) node).GetRecognizedString(), rect.Left, rect.Bottom);
}
foreach(var n in node.SubNodes) Func(n);
}
using(var analyzer = new InkAnalyzer()){
analyzer.AddStrokes(Strokes);
analyzer.Analyze();
Func(analyzer.Rootnode);
}
0 件のコメント:
コメントを投稿
コメントの追加にはサードパーティーCookieの許可が必要です