はじめに
スマホやタブレットの上で、図形や文字を混ぜ書きしつつも、文字部分に関しては、裏で手書き文字認識した結果をキーワードなりタグとして記録しておき、あとで検索の時に使いたい、なんてユースケースはよくあるかと思います。
そんな時に使えるのが、Azure Ink Recognizerです。ここではAndroid JavaアプリケーションからInk Recognizerを使う方法をご紹介します。
なお、私はInk Recognizerの担当者ではないので、ここでの記述は、とあるサンデーフルスタックエンジニアの独り言であって、特定のベンダーの保証する内容ではありません。
事前準備
Azureのアカウントを用意します。Ink Recognizer(本記事執筆時点ではプレビュー)リソースを作成し、手元にキーとエンドポイントを用意しておきます。
利用方法
GitHubに上がっている Azure-Samples/cognitive-services-java-sdk-samples を git cloneして、InkRecognitionディレクトリをAndroid Studioで開いて、ビルドします。
- Ink Recognition SDK Sample (https://github.com/Azure-Samples/cognitive-services-java-sdk-samples/tree/master/InkRecognition)
これだと英語しか認識されないので、日本語(というかデフォルトロケール)で動作するように手を入れます。
public class NoteTaker extends View {
...
private final String language;
...
public NoteTaker(Context context) throws Exception {
...
language = Locale.getDefault().toLanguageTag();
displayMetrics = getResources().getDisplayMetrics();
inkRecognizerAsyncClient = new InkRecognizerClientBuilder()
.credentials(new InkRecognizerCredentials(appKey))
.endpoint(destinationUrl)
.applicationKind(ApplicationKind.MIXED)
.language(language)
.buildAsyncClient();
....
}
}
こんな感じで日本語の手書き文字も認識されそうなのだが、認識結果は英語のみ。何度見直してもどこに誤りがあるのかわからず、途方に暮れていたものの、ちゃんとソースコードを読み進めていくと、もう一箇所、言語を設定できるポイントがありました、ということでストローク(手書きの一筆一筆)。InkStrokeImplementorのコンストラクタで言語を受け取るようにします。
class InkStrokeImplementor implements InkStroke {
...
InkStrokeImplementor(String language) {
this.strokeId = getNextNum();
this.language = language;
this.kind = InkStrokeKind.UNKNOWN;
}
...
}
言語を渡す方は次の通り。先ほど紹介したNoteTakerクラスの中で、メンバ変数としてlanguageにシステムの規定言語を納めているので、そのまま渡すようにします。
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(x, y);
stroke = new InkStrokeImplementor(language);
...
}
...
}
あとはアプリをビルドすれば、システムの規定言語で入力した文字を認識してくれるようになります。
おわりに
分かってしまえば、どうってことのない話ですが、MSのサイトにしても、REST形式での実行サンプルはあっても、Java APIを使うようなケースは(このサンプルアプリ以外は)あまり見ないので、同じように不意にハマってしまう方のお役になっていれば、幸いです。