2011-10-12 14 views
14

ジェスチャライブラリを作成するために、ジェスチャビルダーを使用して、アプリでジェスチャ認識を実装する作業を進めています。私はジェスチャーの複数のバリエーションが認識(またはパフォーマンス)を助けるか妨げるかどうか疑問に思っています。たとえば、私は円形のジェスチャーを認識したいと思います。私は少なくとも時計回りの円と反時計回りの2つのバリエーションを持っていますが、同じセマンティックな意味で、ユーザーはそれについて考える必要はありません。しかし、いろいろな半径のような各方向にいくつかのジェスチャーを保存することが望ましいかどうか、私は疑問に思っています。異なる角度回転を含む卵形、楕円形などのように "十分近い"それぞれの。誰もこれを経験していますか?ジェスチャライブラリのジェスチャのバリエーションが認識を改善していますか?

答えて

19

OK、アンドロイドソースのいくつかの実験と読書の後、私はちょっと勉強しました...まず、ジェスチャーライブラリに異なる角度をカバーするために異なるジェスチャーを作成する心配はありません私の円形のジェスチャーの回転または方向(時計回り/反時計回り)。デフォルトでは、GestureStoreはSEQUENCE_SENSITIVEのシーケンスタイプ(開始点と終了点が重要であることを意味します)とORIENTATION_SENSITIVE(回転角度が重要です)という方向スタイルを使用します。ただし、これらのデフォルトは、 'setOrientationStyle(ORIENTATION_INVARIANT)'およびsetSequenceType(SEQUENCE_INVARIANT)でオーバーライドできます。

さらに、ソースのコメントから引用し...「SEQUENCE_SENSITIVEを使用する場合、単一のストロークジェスチャが現在許可されている」と「ORIENTATION_SENSITIVEとORIENTATION_INVARIANTはSEQUENCE_SENSITIVEジェスチャーのみです」。

興味深いことに、ORIENTATION_SENSITIVEは「方向性の問題」以上の意味を持つように見えます。値は2であり、それに関連するコメントと関連する(文書化されていない)定数は、異なるレベルの感度を要求できることを意味します。パラメータnumOrientationsとしてGestureLibary.recognize()への呼び出し、配向型の値(1、2、4、または8)GestureUtils.minimumCosineDistance(に渡される)の間

// at most 2 directions can be recognized 
public static final int ORIENTATION_SENSITIVE = 2; 
// at most 4 directions can be recognized 
static final int ORIENTATION_SENSITIVE_4 = 4; 
// at most 8 directions can be recognized 
static final int ORIENTATION_SENSITIVE_8 = 8; 

、いくつかの計算が実行されるところ私の給与等級を上回っています(下記参照)。誰かがこれを説明できるなら、私は興味があります。私は2つのジェスチャの角度差を計算していますが、numOrientationsパラメータを使用する方法はわかりません。私が2という値を指定すると、ジェスチャーAとジェスチャーBの2つのバリエーションの間の最小距離が見つかります.1つのバリエーションは「正規B」で、もう1つは180度まわりに回転します。したがって、私は8の値が45度の間隔を置いてBの8つの変化を考慮することを期待するでしょう。しかし、私が下の数式を完全に理解していなくても、numOrientationsの値が4または8のようなものは、どの計算でも直接使用されているようには見えませんが、2より大きい値は別のコードパスになります。たぶんそれが他の値が書かれていない理由です。私の読書に基づいて

/** 
* Calculates the "minimum" cosine distance between two instances. 
* 
* @param vector1 
* @param vector2 
* @param numOrientations the maximum number of orientation allowed 
* @return the distance between the two instances (between 0 and Math.PI) 
*/ 
static float minimumCosineDistance(float[] vector1, float[] vector2, int numOrientations) { 
    final int len = vector1.length; 
    float a = 0; 
    float b = 0; 
    for (int i = 0; i < len; i += 2) { 
     a += vector1[i] * vector2[i] + vector1[i + 1] * vector2[i + 1]; 
     b += vector1[i] * vector2[i + 1] - vector1[i + 1] * vector2[i]; 
    } 
    if (a != 0) { 
     final float tan = b/a; 
     final double angle = Math.atan(tan); 
     if (numOrientations > 2 && Math.abs(angle) >= Math.PI/numOrientations) { 
      return (float) Math.acos(a); 
     } else { 
      final double cosine = Math.cos(angle); 
      final double sine = cosine * tan; 
      return (float) Math.acos(a * cosine + b * sine); 
     } 
    } else { 
     return (float) Math.PI/2; 
    } 
} 

、私が最も簡単かつ最善のアプローチは不変にシーケンスの種類と方向を設定し、1つのストアド円形のジェスチャーを持っているだろうことを理論化。そうすれば、方向や向きに関係なく、円形のものはどれもうまく一致するはずです。だから、私はそれを試みました、そして、それは遠くに円に似ている何かのために(25から70の範囲で)高い得点を返しました。しかし、それはまた、円形(水平線、V字形など)にも近くないジェスチャについては20ほどのスコアを返した。だから、私はマッチするべきものとしてはならないものとの分離については気分が良くなかった。最も効果的であると思われるのは、各方向に1つずつ、ORIENTATION_INVARIANTと組み合わせてSEQUENCE_SENSITIVEを使用して、2つのジェスチャを格納することです。それは私に2.5以上の曖昧な円形のスコアを与えていますが、円形でないジェスチャーについては1未満のスコア(まったくマッチしません)です。

+2

さらに私の実験では、異なる半径の描画されたジェスチャーとの良好な一致を得るために、異なる半径の円形ジェスチャーをジェスチャーライブラリに格納する必要はないことを発見しました。これは、同一の記憶されたジェスチャと同等に良好に一致した(すなわち、同等のスコアを有する)。パフォーマンスに関しては、タイミングは決めていませんが、コードを見てみると、パフォーマンスはライブラリのジェスチャーの数に関してほぼ線形であると思われます。 –

+2

ここにヒントがあります:setSequenceType(GestureStore.SEQUENCE_INVARIANT)を呼び出す場合は、load()を呼び出す前に必ず実行してください。そうしないと、まったくマッチしないことがわかります。 –

+0

ありがとうございます。追加の方向感度レベルを使用して、私は同じようなストロークで異なる回転をしたジェスチャーを持っていた問題を修正しました。私がこの設定を使用する前に、プラスと同等のジェスチャーが衝突していました。 – Ehz

関連する問題