Androidでアプリにジェスチャーを実装する場合、いくつか方法が考えられます。
タッチイベントをトレースしてベクトルから何が描かれたか推測する方法や、OpenCVなどを使って画像をテンプレートと比較して類似度から判定する方法など。
ここではAndroid SDKのサンプルにあるGestureBuilderとGestureライブラリーを使って判定してみます。
ジェスチャーデータ作成アプリ
Eclipseを起動してGestureBuilderをインポートしてプロジェクトをつくり、これを使ってデータを作ってみます。
File->New->Projectで、「Android Project from Existing Code」を使ってGestureBuilderのプロジェクトを作成します。
Root Directoryは、Eclipseを普通にインストールした場合、C:\Program Files\Android\android-sdk\samples\android-17\GestureBuilderです。
エラーが出た場合は、PropertiesでAPI Levelを変更したり、manifestにandroid:targetSdkVersionを追加したりして対処してください。
実機にデプロイすると以下のような画面がでます。
ジェスチャーのデータはSDカードに保存されるようになっているので、SDカードが使えるかどうか確認しておきます。
「Add gesture」をタップすると、ジェスチャーにつける名前を聞いてきます。
一筆書き以外を描くのは結構難しい。
一筆書きと言えば、かつてのPalmのGrafityなんかが参考になるかも。
描画して「Done」をタップ。
ジェスチャーは複数作成できますので、いくつか作っておきます。
改名や削除は項目を長押し(LongPress)すればダイアログが出ます。
描画して「Done」をタップするごとに追加されていきます。
このままアプリを終了します。
データは、sdcard/gesturesという拡張子なしのファイルになっています。
ジェスチャー認識アプリ
EclipseのFile->New->Projectで、「Android Application Project」を使って新規プロジェクトを作成します。
新規プロジェクトのres/rawにジェスチャーデータのgesturesファイルを置きます。
ジェスチャー認識のための基本コード。
記述の仕方はいくつかあるようですが、WisteriaHillで動作確認できたコードは以下のとおり。
import android.gesture.Gesture;
import android.gesture.GestureLibrary;
import android.gesture.GestureLibraries;
import android.gesture.GestureOverlayView;
import android.gesture.GestureOverlayView.OnGesturePerformedListener;
import android.gesture.Prediction;
import java.util.ArrayList;
import android.view.View;
import android.view.WindowManager.LayoutParams;
public class MainActivity extends Activity implements OnGesturePerformedListener{
private GestureLibrary gLibrary;
private GestureOverlayView gView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gView = new GestureOverlayView(this);
gView.setGestureVisible(true);//描いている際の軌跡を非表示にする場合はfalse
追加
gView.setGestureStrokeType(0);//single:0,multiple:1
View inflate = getLayoutInflater().inflate(R.layout.activity_main, null);
gView.addView(inflate);
gView.addOnGesturePerformedListener(this);
gLibrary = GestureLibraries.fromRawResource(this, R.raw.gestures);
if (!gLibrary.load()) {
finish();
}
addContentView(gView,new WindowManager.LayoutParams());
}
public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
ArrayList<Prediction> predictions = gLibrary.recognize(gesture);
if (predictions.size() > 0) {
Prediction prediction = predictions.get(0);
// スコアが1.0より低い場合は却下
if (prediction.score > 1.0) {
//ToDo
//登録した名前を取得
String gesturename = prediction.name;
}
}
}
}
丸く円を描いてみます。
認識した場合。
上記のジェスチャーにある「hexagram」のように2つの図形が合わさっている場合はこんな感じになります。
まず最初の三角形を描きます。
これは別登録しておいた「三角(triangle)」として認識されます。
二番目の三角形を描いた時点で「六芒星(hexagram)」として認識されます。
2つの図形が合わさっているような場合は、setGestureStrokeTypeをmultipleにします。
上のコードに追加している部分、GestureOverlayViewに設定します。
ただ複雑な図形は精度が落ちるので基本ストロークタイプはsingle、つまり一筆書きです。
で、逆の順番で三角形を描いた場合は認識されませんでした。
どうも複数の画像が合わさっている場合は、最初のパーツを単体として登録しておく必要があるのかなぁ?
kagomeが認識されないのは、そのせいか?
android.gestureのパターンマッチングのアルゴリズムってどうなってるんでしょう?
調べてまたレポします。
ところで、下の3つの図形、一筆書きで描けます。
1番目と2番目は、同じ考え方でいけます。
どう描くか分かります?
答えは、次回ページアップデートの時に。
アプリでジェスチャーの練習をしてみましょう。
ゆっくり描くのがコツです。
このアプリはGestureBuilderと同様にMultipleがデフォルトになっています。「六芒星」は何故かSingleの方が認識率がいいです。
メニュで変更できます。
インストール
Target:Android 2.3.3 or later
動作確認実機:Xperia acro(docomo) Android 2.3.4
インストール・実行は自己責任でお願いします、
アプリをQRコードからインストールする方法はコチラを参照
タブレットの場合
QRコードでダウンロードすると、Downloadフォルダー内でzipファイルになってインストールできない状態の場合があります。
その場合は、拡張子のzipをapkに変更してファイル名をタップすればインストール用のダイアログが出ますので、そこからインストールしてください。