Modules

HandDetector

class GestureRecognition.modules.handdetector.HandDetector(outputSignal='detector')

Bases: Module

Modul zur Erkennung von Händen und deren Landmarken.

Dieses Modul verwendet das MediaPipe Hand Landmarker Modell, um Hände in einem Kamerabild zu erkennen und deren Landmarken zu bestimmen.

Ziel ist es, die Webcam-Bilder zu verarbeiten, eine Handdetektion durchzuführen und die erkannten Landmarken sowie eine Visualisierung an das Framework zurückzugeben.

Konstruktor des Moduls.

Ziel ist es, das Modul beim Framework korrekt zu registrieren.

Hinweise

  • Ein Modul muss definieren, welche Signale es empfangen möchte.

  • Diese werden über inputSignals angegeben.

  • Nur Signale, die hier subscribed werden, erscheinen später im data Dictionary der Methoden start() und step().

Für dieses Modul werden unter anderem folgende Signale benötigt:

  • config : Systemkonfiguration

  • webcam : aktuelles Kamerabild

Zusätzlich muss ein Output-Schema definiert werden.

Output Schema

Das Modul erzeugt ein Signal mit dem Namen detector.

Dieses Signal enthält das Ergebnis der Handdetektion, welches beispielsweise Informationen über erkannte Hände und Landmarken enthalten kann.

Beispiel:

outputSchema={"type": "object", "properties": {outputSignal: {}}}

Bemerkung

Die Basisklasse Module erwartet beim Aufruf von super().__init__ unter anderem:

  • inputSignals

  • outputSchema

  • name des Moduls

param outputSignal:

Name des erzeugten Output-Signals.

type outputSignal:

str, optional

start(data)

Initialisierung des Moduls.

Diese Methode wird einmal beim Start des Moduls ausgeführt.

Ziel ist es, das benötigte Handdetektionsmodell zu laden und für die spätere Verarbeitung vorzubereiten.

Hinweise

  • MediaPipe stellt eine Hand-Landmark-Erkennung bereit.

  • Laden sie wie im Artikel beschrieben das Modell ein und speichern sie das detector Objekt in einem Attribut des Moduls. z.B. self.detector

Tipp

Halte die Initialisierung strikt getrennt von der Verarbeitung. In start sollte nur vorbereitet, nicht gerechnet werden.

param data:

Eingabedaten des Frameworks. Enthält unter anderem das Signal config.

type data:

dict

returns:

Ein leeres Dictionary.

rtype:

dict

step(data)

Verarbeitung eines einzelnen Frames.

Ziel ist es, ein Kamerabild zu analysieren, Hände zu erkennen und deren Landmarken zu bestimmen.

Hinweise

  • Greife auf das webcam Signal zu, um das aktuelle Bild zu erhalten.

  • Das Bild liegt typischerweise als np.ndarray vor.

  • Für MediaPipe muss das Bild ggf. in ein geeignetes Format konvertiert werden (mp.Image).

  • Anschließend kann das Bild an den Handdetektor übergeben werden.

  • Das Ergebnis enthält Informationen über erkannte Hände sowie deren Landmarken.

  • Für jede erkannte Hand können die Landmarken anschließend visualisiert werden.

  • Für die Visualisierung kann ein GALY Objekt verwendet werden.

  • Die Funktion draw_hand_landmarks() kann genutzt werden, um Landmarken und Verbindungen darzustellen.

Tipp

Arbeite schrittweise:
  1. Bild holen

  2. Format konvertieren

  3. Detektion durchführen

  4. Ergebnis verarbeiten / visualisieren

Warnung

Achte darauf, dass:
  • das Bildformat korrekt ist (RGB vs. BGR)

  • die Detektion pro Frame effizient bleibt (Live-Demo)

param data:

Enthält unter anderem:

  • webcam : aktuelles Kamerabild

  • config : Systemkonfiguration

type data:

dict

returns:

Soll das Ergebnis der Handdetektion sowie optional ein GALY Objekt für die Visualisierung enthalten.

Beispiel:

return {outputSignal: result, "galy": galy}

rtype:

dict

stop(data)

Wird aufgerufen, wenn das Modul beendet wird.

Ziel ist es, bei Bedarf Ressourcen freizugeben oder interne Zustände zurückzusetzen.

Hinweise

  • In vielen Fällen ist keine spezielle Bereinigung notwendig.

Bemerkung

Diese Methode ist optional, kann aber wichtig werden, wenn externe Ressourcen (z. B. Modelle, Streams) verwendet werden.

param data:

Letzte übergebene Daten des Frameworks.

type data:

dict

TrailMarker

class GestureRecognition.modules.trailmarker.TrailMarker(outputSignal='trailmarker')

Bases: Module

Modul zum Zeichnen einer Spur anhand der Bewegung eines Fingers.

Die Position eines bestimmten Finger-Landmarks wird über mehrere Frames hinweg gespeichert. Aus diesen Punkten kann anschließend eine Linie erzeugt werden, die den Bewegungsverlauf des Fingers visualisiert.

Ziel ist es, die Verarbeitung der Landmark-Daten sowie die Verwaltung eines Zustands über mehrere Frames hinweg selbst zu implementieren.

Konstruktor des Moduls.

Ziel ist es, das Modul beim Framework korrekt zu registrieren.

Hinweise

  • Ein Modul muss definieren, welche Signale es empfangen möchte.

  • Diese werden über inputSignals angegeben.

  • Nur Signale, die hier subscribed werden, erscheinen später im data Dictionary der Methoden start() und step().

Für dieses Modul werden unter anderem folgende Signale benötigt:

  • config : Systemkonfiguration

  • detector : Ergebnisse der Handdetektion

Zusätzlich muss ein Output-Schema definiert werden.

Output Schema

Da dieses Modul keine eigenen Daten erzeugt, reicht beispielsweise:

outputSchema={"type": "object", "properties": {outputSignal: {}}}

Bemerkung

Die Basisklasse Module erwartet beim Aufruf von super().__init__ unter anderem:

  • inputSignals

  • outputSchema

  • name des Moduls

param outputSignal:

Name des erzeugten Output-Signals.

type outputSignal:

str, optional

start(data)

Initialisierung des Modulzustands.

Diese Methode wird einmal beim Start des Moduls ausgeführt.

Ziel ist es, alle Variablen vorzubereiten, die während der Laufzeit des Moduls benötigt werden.

Hinweise

  • Lese benötigte Parameter aus der Konfiguration.

  • Bestimme beispielsweise, welcher Finger verfolgt werden soll.

  • Lege eine Datenstruktur an, in der mehrere vergangene Fingerpositionen gespeichert werden können, z.B. collections.deque mit einer maximalen Größe.

  • Diese Historie wird später verwendet, um eine Spur zu zeichnen.

  • Speichere aus der Konfiguration weitere benötigte Parameter, z.B. Finger-Index, maximale Anzahl verlorener Frames oder Webcam-Parameter.

  • Für den Zugriff auf verschachtelte Konfigurationswerte kann get_nested_key() verwendet werden.

Tipp

Eine deque ist ideal für Trajektorien, da sie effizient alte Punkte entfernt.

Bemerkung

Initialisiere hier nur Zustände und Parameter, keine eigentliche Verarbeitung.

param data:

Eingabedaten des Frameworks. Enthält unter anderem das Signal config.

type data:

dict

returns:

Ein leeres Dictionary.

rtype:

dict

step(data)

Verarbeitung eines einzelnen Frames.

Ziel ist es, die aktuelle Position eines Fingers zu bestimmen, diese Position in einer Trajektorie zu speichern und daraus eine visuelle Spur zu erzeugen.

Hinweise

  • Greife auf das detector Signal zu, um erkannte Hände und deren Landmarken zu erhalten.

  • Falls keine Hand erkannt wurde, kann beispielsweise ein Zähler für verlorene Frames erhöht werden.

  • Wird eine Hand erkannt, kann die Landmarke des gewünschten Fingers extrahiert werden.

  • Die Position kann zur bestehenden Trajektorie hinzugefügt werden.

  • Zwischen aufeinanderfolgenden Punkten können Linien gezeichnet werden, um eine Spur darzustellen.

  • Für die Visualisierung kann line() der GALY verwendet werden.

Tipp

Typischer Ablauf:
  1. Landmark extrahieren

  2. Punkt speichern

  3. Trajektorie aktualisieren

  4. Linien zwischen Punkten zeichnen

Warnung

Achte darauf, dass:
  • keine leeren Landmark-Daten verarbeitet werden

  • die Trajektorie nicht unendlich wächst

  • verlorene Frames sinnvoll behandelt werden

param data:

Enthält unter anderem:

  • detector : erkannte Hände und Landmarken

  • config : Systemkonfiguration

type data:

dict

returns:

Um die Zeichenoperationen auszuführen, sollte ein GALY Objekt zurückgegeben werden.

Beispiel:

return { ..., "galy": galy}

rtype:

dict

stop(data)

Wird aufgerufen, wenn das Modul beendet wird.

Ziel ist es, bei Bedarf Ressourcen freizugeben oder interne Zustände zurückzusetzen.

Hinweise

  • In vielen Fällen ist keine spezielle Bereinigung notwendig.

Bemerkung

Diese Methode ist optional, kann aber sinnvoll sein, wenn Zustände explizit zurückgesetzt werden sollen.

param data:

Letzte übergebene Daten des Frameworks.

type data:

dict

Preprocessor

class GestureRecognition.modules.preprocessor.Preprocessor(outputSignal='preprocessor')

Bases: Module

Modul zur Vorverarbeitung von Fingertrajektorien.

Dieses Modul verarbeitet die vom Handdetektor gelieferten Landmarken und extrahiert daraus die Bewegung eines bestimmten Fingers über mehrere Frames hinweg.

Ziel ist es, eine Trajektorie zu sammeln, diese zu normalisieren und anschließend als Eingabe für nachfolgende Module bereitzustellen.

Konstruktor des Moduls.

Ziel ist es, das Modul beim Framework korrekt zu registrieren.

Hinweise

  • Ein Modul muss definieren, welche Signale es empfangen möchte.

  • Diese werden über inputSignals angegeben.

  • Nur Signale, die hier subscribed werden, erscheinen später im data Dictionary der Methoden start() und step().

Für dieses Modul werden unter anderem folgende Signale benötigt:

  • config : Systemkonfiguration

  • detector : Ergebnisse der Handdetektion

Zusätzlich muss ein Output-Schema definiert werden.

Output Schema

Das Modul erzeugt ein Signal mit dem Namen preprocessor.

Dieses Signal enthält entweder eine normalisierte Trajektorie oder None, falls noch nicht genügend Daten gesammelt wurden.

Beispiel:

outputSchema={"type": "object", "properties": {outputSignal: {}}}

Bemerkung

Die Basisklasse Module erwartet beim Aufruf von super().__init__ unter anderem:

  • inputSignals

  • outputSchema

  • name des Moduls

param outputSignal:

Name des erzeugten Output-Signals.

type outputSignal:

str, optional

start(data)

Initialisierung des Modulzustands.

Diese Methode wird einmal beim Start des Moduls ausgeführt.

Ziel ist es, alle benötigten Parameter aus der Konfiguration zu lesen und interne Datenstrukturen vorzubereiten.

Hinweise

  • Lese relevante Parameter aus der Konfiguration, z.B. den zu verfolgenden Finger.

  • Lege eine Datenstruktur an, um mehrere vergangene Fingerpositionen zu speichern, z.B. collections.deque mit einer maximalen Größe.

  • Speichere außerdem Parameter wie die maximale Anzahl verlorener Frames oder die minimale Anzahl benötigter Punkte.

  • Zum Zugriff auf verschachtelte Konfigurationswerte kann get_nested_key() verwendet werden.

Tipp

Eine deque mit fester Länge ist ideal für Trajektorien, da alte Punkte automatisch verworfen werden.

Bemerkung

Trenne klar zwischen:
  • Initialisierung von Parametern (start)

  • Verarbeitung von Daten (step)

param data:

Eingabedaten des Frameworks. Enthält unter anderem das Signal config.

type data:

dict

returns:

Ein leeres Dictionary.

rtype:

dict

step(data)

Verarbeitung eines einzelnen Frames.

Ziel ist es, eine Fingerposition aus den erkannten Landmarken zu extrahieren und diese in einer Trajektorie zu speichern.

Hinweise

  • Greife auf das detector Signal zu, um erkannte Handlandmarks zu erhalten.

  • Falls keine Hand erkannt wurde, sollte ein interner Zähler für verlorene Frames erhöht werden.

  • Wird eine Hand erkannt, kann die Landmarke des gewünschten Fingers extrahiert werden.

  • Die Position dieses Fingers kann anschließend in einer Trajektorie gespeichert werden.

  • Sobald genügend Punkte gesammelt wurden, kann die Trajektorie weiterverarbeitet werden.

Mögliche Verarbeitungsschritte:

  • Umwandlung der gespeicherten Punkte in ein numpy.ndarray

  • Berechnung eines Zentrums der Trajektorie

  • Skalierung oder Normalisierung der Punkte

Tipp

Arbeite schrittweise:
  1. Prüfen, ob Landmarken vorhanden sind

  2. Fingerposition extrahieren

  3. In Trajektorie speichern

  4. Optional normalisieren

Warnung

Achte darauf, dass:
  • genügend Punkte vorhanden sind

  • keine fehlerhaften Frames verarbeitet werden

  • verlorene Frames sinnvoll behandelt werden

param data:

Enthält unter anderem:

  • detector : erkannte Hände und Landmarken

  • config : Systemkonfiguration

type data:

dict

returns:

Gibt entweder None oder eine normalisierte Trajektorie zurück.

Beispiel:

return {outputSignal: trajectory}

rtype:

dict

stop(data)

Wird aufgerufen, wenn das Modul beendet wird.

Ziel ist es, bei Bedarf interne Zustände zurückzusetzen oder Ressourcen freizugeben.

Hinweise

  • In vielen Fällen ist keine spezielle Bereinigung notwendig.

Bemerkung

Diese Methode ist optional, kann aber relevant werden, wenn interne Zustände explizit zurückgesetzt werden sollen.

param data:

Letzte übergebene Daten des Frameworks.

type data:

dict

HMMModule

class GestureRecognition.modules.hiddenmarkov.HMMModule(outputSignal='markov', model_path='data/hmm.pkl', **kwargs)

Bases: Module

Modul zur Klassifikation von Gesten mittels Hidden Markov Models.

Dieses Modul erhält eine vorverarbeitete Fingertrajektorie vom Preprocessor Modul und verwendet ein trainiertes Hidden-Markov-Modell, um eine Geste zu klassifizieren.

Ziel ist es, eine geladene Modellstruktur zu verwenden, um eine Entscheidung über die aktuell ausgeführte Bewegung zu treffen und das Ergebnis an das Framework zurückzugeben.

Konstruktor des Moduls.

Ziel ist es, das Modul beim Framework korrekt zu registrieren.

Hinweise

  • Ein Modul muss definieren, welche Signale es empfangen möchte.

  • Diese werden über inputSignals angegeben.

  • Nur Signale, die hier subscribed werden, erscheinen später im data Dictionary der Methoden start() und step().

Für dieses Modul werden unter anderem folgende Signale benötigt:

  • config : Systemkonfiguration

  • preprocessor : normalisierte Trajektorien

Zusätzlich muss ein Output-Schema definiert werden.

Output Schema

Das Modul erzeugt ein Signal mit dem Namen markov.

Dieses Signal enthält Informationen über die erkannte Geste sowie deren Klassifikationsscore.

Beispiel:

outputSchema={"type": "object", "properties": {outputSignal: {}}}

Bemerkung

Die Basisklasse Module erwartet beim Aufruf von super().__init__ unter anderem:

  • inputSignals

  • outputSchema

  • name des Moduls

param outputSignal:

Name des erzeugten Output-Signals.

type outputSignal:

str, optional

param model_path:

Pfad zu einem gespeicherten HMM-Modell.

type model_path:

str, optional

param **kwargs:

Weitere Parameter, die an Module weitergegeben werden.

start(data)

Initialisierung des Moduls.

Diese Methode wird einmal beim Start des Moduls ausgeführt.

Ziel ist es, ein zuvor trainiertes Hidden-Markov-Modell zu laden, das später zur Klassifikation verwendet wird.

Hinweise

  • Das Modell kann aus einer Datei geladen werden.

  • Typischerweise wird dafür eine Klassenmethode verwendet, die ein gespeichertes Modell rekonstruiert.

  • Das geladene Modell sollte als Attribut des Moduls gespeichert werden, damit es in step() verwendet werden kann.

Tipp

Trenne klar zwischen:
  • Modell laden (start)

  • Modell anwenden (step)

Warnung

Stelle sicher, dass:
  • der Pfad korrekt ist

  • das Modell zum erwarteten Datenformat passt

param data:

Eingabedaten des Frameworks.

type data:

dict

returns:

Ein leeres Dictionary.

rtype:

dict

step(data)

Verarbeitung eines einzelnen Frames.

Ziel ist es, eine vorverarbeitete Trajektorie zu klassifizieren und die wahrscheinlichste Geste zu bestimmen.

Hinweise

  • Greife auf das preprocessor Signal zu.

  • Falls keine Trajektorie vorhanden ist, kann die Verarbeitung übersprungen werden.

  • Das geladene HMM-Modell kann anschließend verwendet werden, um eine Entscheidung für die aktuelle Bewegung zu berechnen.

  • Das Ergebnis enthält typischerweise Scores für mehrere Klassen.

  • Die Klasse mit dem höchsten Score kann als Ergebnis gewählt werden.

Zusätzlich kann eine Visualisierung erzeugt werden:

  • Erzeuge ein GALY Objekt.

  • Lege eine neue Zeichenebene an.

  • Verwende putText(), um Score und Label darzustellen.

  • Für die Skalierung der Zeichenebene können Parameter aus der Konfiguration über get_nested_key() gelesen werden.

Tipp

Typischer Ablauf:
  1. Daten prüfen (existiert eine Sequenz?)

  2. Modell anwenden

  3. Scores interpretieren

  4. Ergebnis visualisieren

Bemerkung

Du entscheidest selbst:
  • wie du Scores darstellst

  • ob du nur das beste Label oder mehrere Kandidaten zeigst

Warnung

Achte darauf, dass:
  • das Eingabeformat exakt zum Trainingsformat passt

  • keine leeren oder fehlerhaften Sequenzen verarbeitet werden

param data:

Enthält unter anderem:

  • preprocessor : normalisierte Trajektorie

  • config : Systemkonfiguration

type data:

dict

returns:

Soll die erkannte Geste sowie optional Visualisierungsdaten enthalten.

Beispiel:

return {outputSignal: result, "galy": galy}

rtype:

dict

stop(data)

Wird aufgerufen, wenn das Modul beendet wird.

Ziel ist es, bei Bedarf interne Zustände zurückzusetzen oder Ressourcen freizugeben.

Hinweise

  • In vielen Fällen ist keine spezielle Bereinigung notwendig.

Bemerkung

Diese Methode ist optional, kann aber relevant werden, wenn Modelle oder externe Ressourcen verwaltet werden.

param data:

Letzte übergebene Daten des Frameworks.

type data:

dict