Czy posiadanie odmian gestów w bibliotece gestów poprawia rozpoznawanie?

Pracuję nad implementacją rozpoznawania gestów w mojej aplikacji, używając Kreatora gestów do stworzenia biblioteki gestów. Zastanawiam się, czy posiadanie wielu wariantów gestu pomoże lub utrudni rozpoznanie (lub wykonanie). Na przykład chcę rozpoznać okrągły gest. Będę miał co najmniej dwie odmiany-jedną dla okręgu zgodnego z ruchem wskazówek zegara, a drugą dla ruchu przeciwnym do ruchu wskazówek zegara, o tym samym znaczeniu semantycznym, aby użytkownik nie musiał o tym myśleć. Jednakże, Zastanawiam się, czy byłoby pożądane aby zapisać kilka gestów dla każdego kierunku, na przykład o różnych promieniach, lub o różnych kształtach, które są "wystarczająco blisko" - jak kształty jaj, elipsy, itp., w tym różne obroty kątowe każdego z nich. Ktoś ma z tym doświadczenie?

Author: Andy Dennie, 2011-10-12

1 answers

OK, po kilku eksperymentach i przeczytaniu źródła Androida, nauczyłem się trochę... Po pierwsze, wydaje się, że niekoniecznie muszę martwić się o tworzenie różnych gestów w mojej bibliotece gestów, aby pokryć różne obroty kątowe lub kierunki (zgodnie z ruchem wskazówek zegara/przeciwnie do ruchu wskazówek zegara) mojego okrągłego gestu. Domyślnie GestureStore używa typu sekwencji SEQUENCE_SENSITIVE (co oznacza, że punkt początkowy i końcowy mają znaczenie) oraz stylu orientacyjnego ORIENTATION_SENSITIVE (co oznacza, że kąt obrotu ma znaczenie). Jednak te wartości domyślne mogą zostać nadpisane za pomocą ' setOrientationStyle (ORIENTATION_INVARIANT)' i setSequenceType (SEQUENCE_INVARIANT).

Ponadto, cytując z komentarzy w źródle... "gdy używany jest SEQUENCE_SENSITIVE, obecnie dozwolone są tylko gesty pojedynczego obrysu", a "ORIENTATION_SENSITIVE i ORIENTATION_INVARIANT są tylko dla gestów SEQUENCE_SENSITIVE".

Co ciekawe, ORIENTACJA_SENSYWNA wydaje się oznaczać więcej niż tylko "orientacja ma znaczenie". Jego wartość wynosi 2, a komentarze z nim związane i niektóre powiązane (nieudokumentowane) stałe sugerują, że można żądać różnych poziomów czułości.

// 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;

Podczas wezwania do GestureLibary.recognition(), wartość typu orientacyjnego (1, 2, 4 lub 8) jest przekazywana do GestureUtils.minimumCosineDistance() jako parametr numOrientations, po czym wykonywane są niektóre obliczenia, które są powyżej mojej kategorii płac(patrz poniżej). Jeśli ktoś potrafi wyjaśnić to mnie interesuje. Rozumiem, że wylicza różnicę kątową między dwoma gestami, ale nie rozumiem, w jaki sposób używa parametru numorients. Oczekuję, że jeśli podam wartość 2, znajdzie minimalną odległość między gestem A i dwoma wariantami gestu B - jedna odmiana to "normalny B", a druga to B obrócona o 180 stopni. Dlatego spodziewałbym się, że wartość 8 rozważy 8 odmian B, oddalonych od siebie o 45 stopni. Jednak mimo Nie do końca rozumiem poniższą matematykę, nie wygląda mi to na to, że wartość liczbowa 4 lub 8 jest używana bezpośrednio w jakichkolwiek obliczeniach, chociaż wartości większe niż 2 dają odrębną ścieżkę kodu. Może dlatego te inne wartości są nieudokumentowane.

/**
 * 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;
    }
}

Bazując na mojej lekturze, teoretyzowałem, że najprostszym i najlepszym podejściem byłoby mieć jeden zapisany okrągły gest, ustawiając Typ sekwencji i orientację na niezmienną. W ten sposób wszystko, co okrągłe, powinno pasować do ładnych bez względu na kierunek czy orientację. Więc próbowałem to, i to nie zwrócić wysokie wyniki (w zakresie około 25 do 70) dla prawie wszystko zdalnie przypominające koło. Zwracała jednak również 20 punktów za gesty, które nie były nawet zbliżone do okrągłych (poziome linie, kształty V itp.). Więc nie czułem się dobrze z rozdzieleniem między tym, co powinno być dopasowane, a tym, co nie powinno. To, co wydaje się działać najlepiej, to mieć dwa zapisane gesty, po jednym w każdym kierunku, i używając SEQUENCE_SENSITIVE w połączeniu z ORIENTATION_INVARIANT. To daje mi wyniki 2.5 lub wyższe za cokolwiek niejasno okrągłe, ale wyniki poniżej 1 (lub w ogóle nie pasuje) za gesty, które nie są okrągłe.

 19
Author: Andy Dennie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-14 17:14:43