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に変更してファイル名をタップすればインストール用のダイアログが出ますので、そこからインストールしてください。