(Maus)Gestenerkennung mit unterschiedlichen Größen der Gesten



  • Hi,

    ich möchte gerne (Maus)Gesten erkennen. Prinzipiell klappt das auch, aber ich habe dabei ein Problem: Die gezeichnete Geste muss genau so groß sein, wie die "Vorlage". Ich möchte diese Einschränkung gerne aufheben.

    Das Bild wird gezeichnet und in einem

    int Daten[BILDSCHIRM_X][BILSCHIRM_Y]
    

    gespeichert.

    Zeichnet man nun direkt in der Mitte des Bildschirms, dann hat man natürlich viele leere Zwischenräume:

    [i]0 0 0 0 0 0 0 0 0 0 0 0 [/i]
    [i]0 0 0 [/i][b]1 1 1 1 1[/b][i] 0 0 0 0[/i]
    [i]0 0 0 0 0 0 0 0 0 0 0 0[/i]
    

    Meine Frage lautet nun: Wie kann ich aus einem Array von Koordinaten ein neues Bild erstellen das z.B. nur 16x16 Pixel groß ist und die leeren Zwischenräume gar nicht beachtet?

    Zur Zeit habe ich eine 16x16 Matrix und fülle diese in einer Schleife so mit den Koordinaten der (Maus)Geste:

    data[(it->x) / (screenW / 16)]
        [(it->y) / (screenH / 16)] = 1;
    

    Allerdings werden natürlich auch die leeren Zwischenräume wieder übernommen. Ich möchte aber in der 16x16 Matrix nur die Koordinaten haben. Aus diesem Grund muss ich das irgendwie rausrechnen und das Bild beim Verkleinern dementsprechen anpassen. Aber wie macht man das? Habe leider keine Idee 😞

    Würde mich über eure Hilfe sehr freuen 🙂

    Liebe Grüße
    Devy



  • Ich würde die Gesten überhaupt nur rein über die relative Mausbewegung erkennen lassen. Bewegt der Benutzer die Maus über mindestens x Längeneinheiten in eine Richtung (= Winkelabweichung von der Richtung beträgt maximal y Grad) speicherst du das als Mausbewegung in einer Liste ab. Jedesmal wenn du etwas in der Liste abspeicherst überprüfst du ob nun die obersten Elemente insgesamt eine Mausgeste ergeben. Wenn ja, führst du die Geste aus und löscht die Liste.

    MfG SideWinder



  • SideWinder schrieb:

    Ich würde die Gesten überhaupt nur rein über die relative Mausbewegung erkennen lassen. Bewegt der Benutzer die Maus über mindestens x Längeneinheiten in eine Richtung (= Winkelabweichung von der Richtung beträgt maximal y Grad) speicherst du das als Mausbewegung in einer Liste ab. Jedesmal wenn du etwas in der Liste abspeicherst überprüfst du ob nun die obersten Elemente insgesamt eine Mausgeste ergeben. Wenn ja, führst du die Geste aus und löscht die Liste.

    MfG SideWinder

    Hi,

    ich möchte aber nicht nur "Striche" als Geste haben sondern z.B. auch ein Quadrat, ein "L" oder ähnliches. Zur Zeit mache ich es wie folgt:

    Solange der Benutzer die Maustaste gedrückt hat, speicher ich die X/Y-Koordinaten in einer Liste ab. Wird die Maustaste wieder gelöst, dann soll anhand der ermittelten Koordinaten entschieden werden, ob es sich um eine Geste handelt und um welche. Anschließend wird die Liste wieder gelöscht und steht für neue Gesten bereit. Ich bin im Prinzip fast nach diesem Tutorial vorgegangen:

    http://www.tutorials.de/forum/programming-tutorials/219094-its-magic-mit-mausgesten-zaubern.html

    Allerdings will ich auf dem Desktop zeichnen und nicht in einer SDL-Anwendung. Außerdem sollen die Gesten auch bei unterschiedlichen Größen erkannt werden.

    Insgesamt bin ich etwas ratlos...



  • Ich als Benutzer möchte eigentlich nicht die ganze Zeit aufpassen ob ich nun ein Rechteck oder ein Quadrat als Geste liefere. Und ein Viereck sind 4 Commands hintereinander in der Liste die jeweils die nächste Richtung (im oder gegen den Uhrzeigersinn) besitzen. Ein L ist einmal SOUTH und einmal EAST.

    Wenn du aber unbedingt zwischen Rechtecken und Quadraten bzw. allgemeiner zwischen verschiedenen Längen differenzieren willst dann kannst du dir ja einfach zur relativen Bewegung die du erkannt hast auch die Länge dieser relativen Bewegung speichern und dann überprüfen ob die 4 Seiten eines Quadrats beispielsweise nur eine Abweichung von maximal x haben.

    MfG SideWinder



  • BTW: Eventuell ist das Tutorial auch einfach nicht fein.

    Eine gesamte Surface mit heutzutage 1600x1200 Pixeln ~ 1,83MB in den RAM zu schieben nur weli der Benutzer wahrscheinlich irgendwo in einer kleinen Ecke am Schirm innerhalb von 200 Quadratpixeln eine Geste malt und dabei nicht einmal 5% dieser 1,83 MB zum Tragen kommen?

    Also relative Bewegungen sind da imho besser. Die benötigen evtl. einen klicks mehr Rechenaufwand. Dafür sind sie sehr viel weniger speicherintensiv, und du kannst Bewegungen sehr schön erkennen und musst keine viel viel viel rechenaufwendigeren Mustervergleiche durchführen.

    MfG SideWinder



  • SideWinder schrieb:

    BTW: Eventuell ist das Tutorial auch einfach nicht fein.

    Eine gesamte Surface mit heutzutage 1600x1200 Pixeln ~ 1,83MB in den RAM zu schieben nur weli der Benutzer wahrscheinlich irgendwo in einer kleinen Ecke am Schirm innerhalb von 200 Quadratpixeln eine Geste malt und dabei nicht einmal 5% dieser 1,83 MB zum Tragen kommen?

    Also relative Bewegungen sind da imho besser. Die benötigen evtl. einen klicks mehr Rechenaufwand. Dafür sind sie sehr viel weniger speicherintensiv, und du kannst Bewegungen sehr schön erkennen und musst keine viel viel viel rechenaufwendigeren Mustervergleiche durchführen.

    MfG SideWinder

    Überredet 😃 Nur wie setze ich das am Besten um? Mir reicht es allgemeine Muster zu erkennen. Es muss auch nicht zwangsläufig eine Unterschiedung geben, ob es sich um ein Quadrat handelt oder um ein Rechteck. Hauptsache es hat 4 Seiten.

    Wie sollte ich nun vorgehen? Prinzipiell ist es doch weiterhin notwendig alle X/Y-Koordinaten aufzuzeichnen solange die Maustaste gedrückt ist? Okay, diesen Schritt hätte ich bereits erledigt. Nun habe ich also die Koordinaten und müsste nunermitteln, was diese aussagen. Wie du bereits angedeteutet hast: EAST, SOUTH, etc.

    Da bin ich mir aber nicht sicher, wie ich das genau machen soll.

    Aber ich hätte zumindest eine -wahrscheinlich sehr naive- Idee:

    Also ich prüfe, ob die größte Y-Koordinate minus die kleinste Y-Koordinate einen Wert kleiner als 50 ergibt. Das würde ja bedeuten, dass es sich entweder um eine sehr(!) kleine Senkrechte handelt oder es sich um eine Waagerechte handelt. Ich denke, ich kann voraussetzen das man lang genug zeichnet. Es ist also eine Waagerechte. Anschließend müsste ich nur noch testen, was in der ersten gespeicherten Koordinate drinne steht. Ist die erste Koordinate kleiner als die zweite, dann wäre das eine Waagerechte von Links nach Rechts. So würde ich auch für die X-Koordinaten verfahren...

    Ich würde dann immer die 5 letzten Segmente oder so speichern und bei jedem neu erkannten Segment prüfen, ob sich daraus z.B. ein "L" oder ähnliches konstruieren lässt.

    Ist das wohl so machbar oder geht das eher in Richtung Träumerei? 😃

    Ein Problem sehe ich aber, falls das tatsächlich so funktioniert: Wie soll ich zwischen L, Quadrat und einem einfachen | unterscheiden? Ich müsste diese ja sozusagen einzeln zusammensetzen. Aber wenn ich dann mit einem | anfange, dann wird dieser sofort als dieser erkannt. Ich kann mein L also gar nicht zu Ende zeichnen. Das wäre etwas unschön und schränkt die Möglichkeiten ernom ein. Hmm... Jetzt bin ich wieder ratlos 😃



  • Ich würde die gemalte Figur (nur die Figur, nicht den gesamten Bildschirm) herunter- bzw raufskalieren, auf 100x100 Pixel oder so. Dann versuchst du, Richtungen zu erkennen, also gehst die Koordinaten durch und checkst dabei, ob sie halbwegs auf einer Linie sind. Z.B. um eine horizontale Bewegung zu erkennen, schaust du, dass die x-Werte sich bei jedem Schritt erhöhen/verkleinern und die gesamten y-Koordinaten in diesem Bereich sich nicht um ~5-10% der Figur-Größe unterscheiden. An den Ecken der Figur wirst du wohl ein bisschen Waschi-Waschi erhalten, also diese am Besten ignorieren. Und Linien erst ab einer Länge von X% zählen.

    edit: Am Besten, du versuchst nicht alles auf einmal, sondern implementierst erst die Erkennung von EAST-Linien, dann die nächste Linien-Art usw.



  • ie sollte ich nun vorgehen? Prinzipiell ist es doch weiterhin notwendig alle X/Y-Koordinaten aufzuzeichnen solange die Maustaste gedrückt ist? Okay, diesen Schritt hätte ich bereits erledigt. Nun habe ich also die Koordinaten und müsste nunermitteln, was diese aussagen. Wie du bereits angedeteutet hast: EAST, SOUTH, etc.

    du musst nicht alle punkte speichern.
    ich wüde nur den anfangspunkt speichern und schauen, ob die maus sich auf einer geraden line (entsprechnd den erwartungen deiner gesten) bewegt.
    weiterhin würde ich die letzten paar koordinaten aufheben (zirkulärer puffer) und schauen, ob der Benutzer die richtung wechselt. und ein neuer anfangspunkt für einen weiteren teil der geste gesetzt werden muss (nachdem der alte anfangs- und endpunktin die kommandliste eingetragen wurden).

    es gibt doch ein firefox plugin für mausgesten, schau doch da einfach mal in den source.

    nebenbei:
    mausgesten sind meiner meinung nach kein gutes mittel für benutzer interaktionen.
    ich hatte am anfang auch im firefox die gestenerweiterung drin, aber nur eigendlich nur vor/zurück und tab schließen benutzt, da ich mir die seltener gebrauchten nicht merken konnte.
    jetzt benutze ich nur noch easygestures, das ist so ein kreismenu, probiers mal aus, es sit echt angenehmer.
    Kreismenus kombinieren kontext-menüs mit gesten.
    man hat kein lineares menü, wo man sich die entfernung merken muss, die man nach klicken zurücklegt, sondern ein kreisförmig angeordnetes, wo man sich nur eine richtung merken muss. Gegnüber Gesten hat es den vorteil, dass man sich nicht einprägen muss, welche Geste was bewirkt, da ein icon die zuordnung geste->funktion unterstützt.



  • Devy schrieb:

    Meine Frage lautet nun: Wie kann ich aus einem Array von Koordinaten ein neues Bild erstellen das z.B. nur 16x16 Pixel groß ist und die leeren Zwischenräume gar nicht beachtet?

    vielleicht hilft dir das: http://www.codeproject.com/KB/system/gestureapp.aspx
    🙂


Anmelden zum Antworten