Android 手势库中手势的变化是否能提高识别能力?

Android 手势库中手势的变化是否能提高识别能力?,android,gesture,gesture-recognition,gestures,Android,Gesture,Gesture Recognition,Gestures,我正在我的应用程序中实现手势识别,使用手势生成器创建手势库。我想知道一个手势的多种变化是否有助于或阻碍识别(或表现)。例如,我想识别一个圆形手势。我将至少有两种变体——一种是顺时针的,另一种是逆时针的,具有相同的语义含义,这样用户就不必考虑它了。但是,我想知道是否需要为每个方向保存几个手势,例如,不同半径的手势,或者使用“足够接近”的不同形状的手势,例如蛋形、椭圆等,包括每个方向的不同角度旋转。有人有过这方面的经验吗?好的,经过一些经验和对android源代码的阅读,我学到了一些。。。首先,我似

我正在我的应用程序中实现手势识别,使用手势生成器创建手势库。我想知道一个手势的多种变化是否有助于或阻碍识别(或表现)。例如,我想识别一个圆形手势。我将至少有两种变体——一种是顺时针的,另一种是逆时针的,具有相同的语义含义,这样用户就不必考虑它了。但是,我想知道是否需要为每个方向保存几个手势,例如,不同半径的手势,或者使用“足够接近”的不同形状的手势,例如蛋形、椭圆等,包括每个方向的不同角度旋转。有人有过这方面的经验吗?

好的,经过一些经验和对android源代码的阅读,我学到了一些。。。首先,我似乎不必担心在我的手势库中创建不同的手势来覆盖我的圆形手势的不同角度旋转或方向(顺时针/逆时针)。默认情况下,GestureStore使用序列类型敏感(表示起点和终点重要)和方向样式敏感(表示旋转角度重要)。但是,可以使用“setOrientionStyle(ORIENTATION_不变量)”和setSequenceType(SEQUENCE_不变量)”覆盖这些默认值

此外,引用来源中的评论。。。“当使用序列敏感时,当前只允许单笔画手势”和“方向敏感和方向不变仅适用于序列敏感手势”

有趣的是,方向敏感似乎不仅仅意味着“方向问题”。它的值是2,与之相关的注释和一些相关的(未记录的)常量意味着您可以请求不同级别的敏感度

// 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;
在调用GestureLibrary.Recognite()的过程中,方向类型值(1、2、4或8)作为参数NuMorentations传递给GestureUtils.MinimumCosInDistance(),然后执行一些高于我的薪资等级的计算(见下文)。如果有人能解释,我很感兴趣。我知道它是在计算两个手势之间的角度差,但我不明白它使用numOrientations参数的方式。我的期望是,如果我指定一个值2,它会找到手势a和手势B的两个变体之间的最小距离——一个变体是“正常B”,另一个变体是旋转180度左右的B。因此,我预计8的值会考虑B的8个变化,相隔45度。然而,尽管我不完全理解下面的数学,但在我看来,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;
    }
}
/**
*计算两个实例之间的“最小”余弦距离。
* 
*@param向量1
*@param向量2
*@param numOrientations允许的最大方向数
*@返回两个实例之间的距离(介于0和Math.PI之间)
*/
静态浮点最小余弦距离(浮点[]向量1,浮点[]向量2,整数){
最终int len=向量1.1长度;
浮点数a=0;
浮动b=0;
对于(int i=0;i2&&Math.abs(角度)>=Math.PI/numOrientations){
return(float)Math.acos(a);
}否则{
最终双余弦=数学余弦(角度);
最终双正弦=余弦*tan;
返回(浮点)数学acos(a*余弦+b*正弦);
}
}否则{
返回(浮点)Math.PI/2;
}
}

根据我的阅读,我推断最简单和最好的方法是存储一个循环手势,将序列类型和方向设置为不变。这样,无论方向如何,任何圆形的物体都应该非常匹配。所以我试过了,它确实在几乎任何类似于圆的东西上得到了高分(大约在25到70分之间)。然而,对于甚至不接近圆形(水平线、V形等)的手势,它也会返回20分左右的分数。所以,我对应该匹配和不应该匹配之间的分离感觉不好。似乎最有效的方法是存储两个手势,每个方向一个,并结合使用序列敏感和方向不变。对于任何模糊的循环动作,我的分数都是2.5分或更高,但对于非循环动作,我的分数低于1分(或根本没有匹配项)。

此外,在我的实验中,我发现,没有必要将不同半径的圆形手势存储到手势库中,以便与绘制的不同半径的手势进行良好匹配——我在屏幕上绘制的不同半径的圆形手势与存储的相同手势匹配得同样好(即分数相当)。关于性能,我没有进行计时,但根据代码的分析,我怀疑性能与库中手势的数量大致呈线性关系。这里有一个提示:如果调用setSequenceType(GestureStore.SEQUENCE_不变量),请确保在调用load()之前执行此操作,否则你会发现根本没有匹配项。谢谢你。使用额外的方向敏感度水平修复了我在使用类似笔划但旋转不同的手势时遇到的问题。像加号和等号这样的手势