Mittels Hand-Tracking lassen sich Gesten erkennen. Wir wollen ein trainiertes Gesten-Modell verwenden und damit über die Webcam mit Hand-Bewegungen ein «Spiel» steuern.
Aufgabe: Auftrag
Arbeit dich in einer Zweier- oder Dreier-Gruppe durch diese Seite durch und versuche den letzten Auftrag als Projekt zu realisieren.
Übersicht
- Bild von Webcam einlesen
- Geste im Bild erkennen
- Turtle steuern
Webcam
Um Bilder über die Webcam einzulesen können wir das Python-Package OpenCV verwenden. Wir können das in Thonny unter «Verwalte Pakete» installieren indem wir nach opencv-contrib-python
suchen.
OpenCV bietet auch Möglichkeiten Bilder zu bearbeiten und anzuzeigen. Das untenstehende Programm liest Bilder von der Webcam, spiegelt diese vertikal (wie ein Spiegel) und zeigt sie in einem Fenster solange an, bis der Anwender mit der Taste q das Programm beendet.
import cv2
# gewünschte Webcam-Auflösung setzen
width, height = 1280, 720
# erster Video-Capture-Device wählen (ev. mehrere Webcams)
cam = cv2.VideoCapture(0)
cam.set(3, width) # Höhe setzen
cam.set(4, height) # Breite setzen
# Kamera-Loop
while cam.isOpened():
# Einzelbild holen
success, frame = cam.read()
if not success:
print("Webcam-Bild nicht verfügbar!")
continue
# Bild spiegeln
frame = cv2.flip(frame, 1)
# Bild anzeigen
cv2.imshow("Webcam-Bild", frame)
# Tastendruck «q» beendet Schleife
if cv2.waitKey(20) == 113:
break
# Webcam freigeben und Fenster schliessen
cam.release()
cv2.destroyAllWindows()
# Nochmals auf Tasteneingabe warten (Fix damit Fenster zugeht)
cv2.waitKey(20)
Aufgabe: Webcam
- installiere OpenCV
- kopiere, starte und teste das Beispiel
- kannst du die Spiegelung deaktivieren?
- kannst du horizontal statt vertikal spiegeln?
Gestenerkennung
MediaPipe von Google ist ein ML-Framework zur Bilderkennung. Eine Möglichkeit ist Gestenerkennung der Hand.
Mit dem trainierten Standard-Modell gesture_recognizer.task
werden die folgenden Gesten erkannt:
👍 👎 ✌️ ☝️ ✊ 🖐️ 🤟
import mediapipe as mp
from mediapipe.tasks import python
from mediapipe.tasks.python import vision
# GestureRecognizer-Objekt erstellen basieren auf heruntergeladenem Modell
base_options = python.BaseOptions(model_asset_path='gesture_recognizer.task')
options = vision.GestureRecognizerOptions(base_options=base_options)
recognizer = vision.GestureRecognizer.create_from_options(options)
# Liste von lokalen Bild-Dateien
files = ['thumbs_down.jpg', 'victory.jpg', 'thumbs_up.jpg', 'pointing_up.jpg']
# Schleife über alle Dateien
for file in files:
# Bild aus Datei lesen
image = mp.Image.create_from_file(file)
# Bild durch Recognizer schicken
recognition_result = recognizer.recognize(image)
# Top-Geste der Erkennung auslesen
top_gesture = recognition_result.gestures[0][0]
# Ergebnis ausgeben
print(file, top_gesture)
Die verlinkte Zip-Datei beinhalten die 4 Beispiel-Bilder und das vortrainierte Model:
Aufgabe: Gesten
- installiere das Python-Package
mediaPipe
- speichere die 4 Bilder und das Model
gesture_recognizer.task
(aus Zip-Datei) - starte und teste das obenstehende Programm
- schaffst du es nur den Namen der Geste auszugeben?
- schaffst du es die Gesten als Emoji auszugeben?
Aufgabe: Gesten mit Webcam
Kombiniere nun die Gestenerkennung mit der Webcam: Statt Bilder aus Dateien, analysierst du nun die «Frames» die du von deiner Webcam erhältst.
Tipp:
Du musst den Frame der Webcam in ein mediaPipe-Bild umwandeln bevor du es dem Recognizer übergeben kannst:
mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=frame)
Turtle
Um eine Turtle steuerbar zu machen, brauchen wir eine Schleife und müssen auf Veränderungen reagieren. Sind das nun erkannte Handgesten oder – wie im Beispiel – gedrückte Tasten auf der Tastatur. Die Tastatureingaben werden allerdings nicht im Loop abgefragt, sondern als Events
registriert. Diese Events bewirken über die Variable koopa.rotation
eine Richtungsänderung der Turtle:
from turtle import Turtle
# Turtle erzeugen und Screen-Objekt holen
koopa = Turtle()
screen = koopa.getscreen()
# Drehgeschwindigkeit initialisieren
koopa.rotation = 0
# Drehgeschwindigkeit links
def left():
koopa.rotation = -3
# Drehgeschwindigkeit rechts
def right():
koopa.rotation = 3
# Geradeaus
def straight():
koopa.rotation = 0
# Events registrieren
screen.onkey(left, "Left")
screen.onkey(right, "Right")
screen.onkey(straight, "Up")
# auf Events reagieren
screen.listen()
# Loop starten
while True:
koopa.forward(1) # immer vorwärts
koopa.right(koopa.rotation) # je nach Drehgeschwindigkeit drehen
koopa.done()
Aufgabe: Turtle
- test das Turtle-Beispiel
- kannst du den Kurvenradius variieren?
- kannst du eine Steuerung der Turtlegeschwindigkeit einbauen?
Auftrag
Aufgabe: Turtle-Gesten-Steuerung
Versuche mit der Hand-Gestenerkennung eine Turtle-Steuerung zu implementieren.
- Basis
- eine Turtle lässt sich nach links und rechts steuern (2 Gesten)
- Erweitert
- weitere Gesten für weitere Steuerbefehle
- zwei Turtles gesteuert von zwei Spieler (resp. zwei Händen)
- daraus ein Spiel mit einem Ziel machen
- …
Zusatzaufgabe
Wende deine Steuerung auf ein anderes Game – etwas was du ev. schon mal programmiert hast – an:
- Sokoban (haben wir programmiert)
- Pong (Klassiker, einfach zu programmieren)
- Flappy Bird-Klon (source-code erhältlich -> fts)
- Meteoriten (ev. mal im OF programmiert)
- …