Lauffehler mit Python, OpenCV und Computer Vision erkennen
Erfahren Sie, wie Sie mit Python, OpenCV und MediaPipe Laufstilfehler wie Overstriding und vertikale Oszillation im Video automatisch erkennen.
Auf dieser Seite
Ob Sie ein erfahrener Marathonläufer sind oder gerade erst mit dem Laufen beginnen: Die richtige Lauftechnik ist sowohl für die Leistung als auch für die Verletzungsprävention entscheidend. Zwei der häufigsten und nachteiligsten Fehler in der Lauftechnik sind Overstriding und eine übermäßige vertikale Oszillation (Hüpfen). Diese Probleme können zu Energieverlust und einem erhöhten Risiko für Verletzungen wie das Schienbeinkantensyndrom und das Läuferknie führen.
Traditionell erforderte eine Rückmeldung zur Lauftechnik eine teure Einheit mit einer Trainerin oder einem Trainer oder einen Besuch in einem spezialisierten Ganganalyselabor. Was aber, wenn Sie wertvolle Erkenntnisse allein mit einem Video von sich selbst beim Laufen und etwas Python-Code gewinnen könnten?
In diesem Tutorial erstellen wir einen Lauftechnik-Analysator, der Overstriding und eine übermäßige vertikale Oszillation automatisch aus einer Videodatei erkennen kann. Wir nutzen die Möglichkeiten von OpenCV für die Videoverarbeitung und die MediaPipe-Bibliothek von Google für eine genaue Pose-Schätzung. Dieses Projekt ist ein hervorragendes Beispiel dafür, wie Computer Vision in der Fitness- und Gesundheitstechnologie eingesetzt werden kann.
Voraussetzungen:
- Grundlegendes Verständnis von Python.
- Vertrautheit mit NumPy für numerische Operationen.
- Python und pip auf Ihrem System installiert.
- Ein Video einer Person, die auf einem Laufband läuft, von der Seite gefilmt.
Das Problem verstehen
Die Biomechanik von Lauffehlern
Um unseren Detektor zu erstellen, müssen wir zunächst verstehen, wonach wir suchen.
1. Overstriding: Dies geschieht, wenn Ihr Fuß zu weit vor dem Körperschwerpunkt aufsetzt, oft mit einem gestreckten Knie. Dadurch entsteht bei jedem Schritt eine Bremskraft, die Sie verlangsamt und die Belastung Ihrer Gelenke erhöht. Overstriding lässt sich erkennen, indem wir den Schienbeinwinkel in dem Moment messen, in dem der Fuß den Boden berührt. Ein nahezu senkrechtes Schienbein ist ideal, während ein großer Vorwärtswinkel auf Overstriding hinweist.
2. Übermäßige vertikale Oszillation: Dies ist die „hüpfende“ Bewegung, die manche Läuferinnen und Läufer zeigen. Ein gewisses Maß an vertikaler Bewegung ist notwendig, doch zu viel davon bedeutet, dass Sie Energie verschwenden, indem Sie sich auf und ab statt vorwärts bewegen. Eine typische vertikale Oszillation bei effizienten Läuferinnen und Läufern liegt zwischen 5 und 10 cm. Wir können dies messen, indem wir die vertikale Bewegung der Hüfte über den Gangzyklus hinweg verfolgen.
Voraussetzungen
Richten wir unsere Python-Umgebung ein. Es ist gute Praxis, eine virtuelle Umgebung zu verwenden, um die Abhängigkeiten Ihres Projekts zu verwalten.
# Create a virtual environment
python -m venv running_analyzer_env
# Activate the virtual environment
# On Windows:
running_analyzer_env\Scripts\activate
# On macOS/Linux:
source running_analyzer_env/bin/activate
# Install the necessary libraries
pip install opencv-python mediapipe numpy
Sie sollten für jedes dieser Pakete eine Meldung über die erfolgreiche Installation sehen.
Schritt 1: Einrichten der Pose-Schätzungs-Pipeline
Was wir tun
Zuerst müssen wir das Video Bild für Bild verarbeiten und MediaPipe verwenden, um die Körperlandmarken der Läuferin oder des Läufers zu erkennen. Das Pose-Modell von MediaPipe liefert 33 Schlüsselpunkte am Körper, was für unsere Analyse mehr als ausreichend ist.
Umsetzung
Erstellen Sie eine neue Python-Datei, zum Beispiel running_analyzer.py, und beginnen wir mit dem Import der erforderlichen Bibliotheken und der Initialisierung des MediaPipe-Pose-Modells.
# running_analyzer.py
import cv2
import mediapipe as mp
import numpy as np
# Initialize MediaPipe Pose
mp_pose = mp.solutions.pose
pose = mp_pose.Pose(min_detection_confidence=0.5, min_tracking_confidence=0.5)
mp_drawing = mp.solutions.drawing_utils
def process_video(video_path):
cap = cv2.VideoCapture(video_path)
if not cap.isOpened():
print("Error: Could not open video.")
return
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# Convert the BGR image to RGB
image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
image.flags.writeable = False
# Make detection
results = pose.process(image)
# Recolor back to BGR
image.flags.writeable = True
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
# Render detections
if results.pose_landmarks:
mp_drawing.draw_landmarks(image, results.pose_landmarks, mp_pose.POSE_CONNECTIONS)
cv2.imshow('Running Form Analysis', image)
if cv2.waitKey(10) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
# Replace 'running_video.mp4' with the path to your video
process_video('running_video.mp4')
So funktioniert es
- Wir importieren
cv2für die Videoverarbeitung,mediapipefür die Pose-Schätzung undnumpyfür Berechnungen. - Wir initialisieren die Klasse
mp.solutions.pose.Pose, die das Machine-Learning-Modell zur Erkennung von Körperlandmarken enthält. - Die Funktion
process_videoöffnet die Videodatei und liest sie Bild für Bild ein. - Für jedes Bild wandeln wir es von BGR (dem Standard von OpenCV) in RGB um, was MediaPipe erwartet.
pose.process(image)führt das Pose-Schätzungsmodell für das Bild aus.- Die Ergebnisse enthalten die erkannten Landmarken, die wir anschließend mit
mp_drawing.draw_landmarkszur Visualisierung auf das Bild zeichnen. - Abschließend zeigen wir das verarbeitete Bild an.
Häufige Fallstricke
- Videopfad: Stellen Sie sicher, dass der Pfad zu Ihrer Videodatei korrekt ist.
- Kamerawinkel: Damit diese Analyse genau ist, sollte das Video eine klare Seitenansicht der Läuferin oder des Läufers zeigen.
Schritt 2: Gelenkwinkel berechnen und Overstriding erkennen
Was wir tun
Nun zur Kernlogik der Erkennung von Overstriding. Wir müssen:
- Den Moment des „Foot Strike“ identifizieren – also den Zeitpunkt, an dem der Fuß der Läuferin oder des Läufers erstmals den Boden berührt.
- In diesem Moment den Winkel des Schienbeins (die Linie vom Knie zum Sprunggelenk) relativ zu einer senkrechten Linie berechnen.
Umsetzung
Erstellen wir eine Hilfsfunktion zur Winkelberechnung und integrieren wir sie anschließend in unsere Hauptverarbeitungsschleife für das Video.
# Add this function to running_analyzer.py
def calculate_angle(a, b, c):
"""Calculates the angle between three points."""
a = np.array(a) # First point
b = np.array(b) # Mid point
c = np.array(c) # End point
radians = np.arctan2(c[1] - b[1], c[0] - b[0]) - np.arctan2(a[1] - b[1], a[0] - b[0])
angle = np.abs(radians * 180.0 / np.pi)
if angle > 180.0:
angle = 360 - angle
return angle
# ... (rest of the code)
# Inside the 'while' loop of the process_video function, after getting the 'results':
# try:
# landmarks = results.pose_landmarks.landmark
#
# # Get coordinates for left side of the body
# left_hip = [landmarks[mp_pose.PoseLandmark.LEFT_HIP.value].x, landmarks[mp_pose.PoseLandmark.LEFT_HIP.value].y]
# left_knee = [landmarks[mp_pose.PoseLandmark.LEFT_KNEE.value].x, landmarks[mp_pose.PoseLandmark.LEFT_KNEE.value].y]
# left_ankle = [landmarks[mp_pose.PoseLandmark.LEFT_ANKLE.value].x, landmarks[mp_pose.PoseLandmark.LEFT_ANKLE.value].y]
#
# # Simple foot strike detection (when ankle is at its lowest point)
# # A more robust method would be needed for varied terrain
# if 'prev_left_ankle_y' not in locals():
# prev_left_ankle_y = left_ankle[1]
#
# if prev_left_ankle_y < left_ankle[1]: # If ankle is moving down
# # Foot strike is likely happening or about to happen
# vertical_point = [left_knee[0], left_knee[1] + 0.1] # A point directly below the knee
# shin_angle = calculate_angle(left_ankle, left_knee, vertical_point)
#
# # Display shin angle and check for overstriding
# cv2.putText(image, f"Shin Angle: {int(shin_angle)}",
# (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2, cv2.LINE_AA)
#
# if shin_angle > 15: # Threshold for overstriding
# cv2.putText(image, "Overstriding Detected",
# (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2, cv2.LINE_AA)
#
# prev_left_ankle_y = left_ankle[1]
#
# except:
# pass
Hinweis: Der Einfachheit halber zeigt das obige Codebeispiel die Logik. Sie sollten dies in die while-Schleife der Funktion process_video integrieren und berücksichtigen, welches Bein vorn ist.
So funktioniert es
- Die Funktion
calculate_anglenimmt drei Punkte entgegen und verwendet den Arkustangens ihrer Koordinaten, um den Winkel am Mittelpunkt zu bestimmen. - Wir extrahieren die x- und y-Koordinaten für Hüfte, Knie und Sprunggelenk aus den MediaPipe-Landmarken.
- Für die Erkennung des Foot Strike auf einem Laufband besteht eine einfache Heuristik darin, den Zeitpunkt zu finden, an dem das Sprunggelenk in einem Schritt seinen tiefsten vertikalen Punkt erreicht.
- Um den Schienbeinwinkel relativ zur Senkrechten zu berechnen, erzeugen wir einen Punkt direkt unter dem Knie und berechnen den Winkel zwischen Sprunggelenk, Knie und diesem senkrechten Punkt.
- Anschließend zeigen wir diesen Winkel auf dem Bildschirm an. Überschreitet er einen bestimmten Schwellenwert (z. B. 15 Grad bei Fersenläuferinnen und Fersenläufern), kennzeichnen wir ihn als Overstriding.
Häufige Fallstricke
- Koordinatensystem: Denken Sie daran, dass die y-Achse in OpenCV nach unten zunimmt.
- Erkennung des Foot Strike: Diese einfache Methode funktioniert am besten beim Laufen auf dem Laufband. Für das Laufen im Freien kann ein fortgeschrittenerer Algorithmus erforderlich sein, um zu erkennen, wann der Fuß relativ zum Boden aufhört, sich zu bewegen.
Schritt 3: Vertikale Oszillation messen
Was wir tun
Um die vertikale Oszillation zu messen, verfolgen wir die vertikale Position der Hüfte im Zeitverlauf. Wir müssen den höchsten und den niedrigsten Punkt der Hüfte während eines Gangzyklus finden, um das Ausmaß des Hüpfens zu bestimmen.
Umsetzung
Wir müssen die vertikale Position der Hüfte über mehrere Bilder hinweg verfolgen.
# Add these variables before the 'while' loop in process_video
hip_y_positions = []
vertical_oscillation = 0
# Inside the 'while' loop, within the 'try' block:
# # ... (after getting landmark coordinates)
#
# left_hip_y = landmarks[mp_pose.PoseLandmark.LEFT_HIP.value].y
# hip_y_positions.append(left_hip_y)
#
# # Analyze over a window of frames (e.g., 30 frames)
# if len(hip_y_positions) > 30:
# max_hip_y = max(hip_y_positions)
# min_hip_y = min(hip_y_positions)
#
# # Convert normalized coordinates to pixels to get a meaningful measurement
# frame_height, frame_width, _ = image.shape
# vertical_oscillation_pixels = (max_hip_y - min_hip_y) * frame_height
#
# # You'd need a reference object of known size in the frame to convert pixels to cm
# # For now, we'll just display the pixel value
# cv2.putText(image, f"Vertical Oscillation (pixels): {int(vertical_oscillation_pixels)}",
# (10, 90), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2, cv2.LINE_AA)
#
# hip_y_positions.pop(0) # Keep the list size constant
So funktioniert es
- Wir speichern die vertikale (
y-)Koordinate der Hüfte für jedes Bild in einer Liste. - Wir verwenden einen gleitenden Fensteransatz, um die maximalen (tiefster Punkt auf dem Bildschirm) und minimalen (höchster Punkt) y-Werte der letzten 30 Bilder zu finden.
- Die Differenz zwischen diesen Werten ergibt die vertikale Oszillation in normalisierten Koordinaten.
- Um eine reale Messung (in cm) zu erhalten, müssten Sie das System kalibrieren, indem Sie ein Objekt bekannter Größe im Videobild platzieren, um ein Verhältnis von Pixeln zu Zentimetern festzulegen.
Alles zusammenfügen
Hier ist die vollständigere Codestruktur:
import cv2
import mediapipe as mp
import numpy as np
# ... (calculate_angle function here) ...
def analyze_running_form(video_path):
mp_pose = mp.solutions.pose
pose = mp_pose.Pose(min_detection_confidence=0.5, min_tracking_confidence=0.5)
mp_drawing = mp.solutions.drawing_utils
cap = cv2.VideoCapture(video_path)
hip_y_positions = []
prev_ankle_y = 0
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
image.flags.writeable = False
results = pose.process(image)
image.flags.writeable = True
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
try:
landmarks = results.pose_landmarks.landmark
# Use the side that is more visible to the camera
hip = landmarks[mp_pose.PoseLandmark.LEFT_HIP.value]
knee = landmarks[mp_pose.PoseLandmark.LEFT_KNEE.value]
ankle = landmarks[mp_pose.PoseLandmark.LEFT_ANKLE.value]
# --- Overstriding Detection ---
if prev_ankle_y > 0 and ankle.y > prev_ankle_y: # Simple foot strike detection
vertical_point = [knee.x, knee.y + 0.1]
shin_angle = calculate_angle([ankle.x, ankle.y], [knee.x, knee.y], vertical_point)
if shin_angle > 15:
cv2.putText(image, "OVERSTRIDING", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2, cv2.LINE_AA)
prev_ankle_y = ankle.y
# --- Vertical Oscillation ---
hip_y_positions.append(hip.y)
if len(hip_y_positions) > 30: # Sliding window of 30 frames
min_y = min(hip_y_positions)
max_y = max(hip_y_positions)
oscillation_normalized = max_y - min_y
# To convert to cm, you need a reference object
# oscillation_cm = oscillation_normalized * frame_height_in_pixels * (real_object_height_cm / object_height_in_pixels)
if oscillation_normalized * 1000 > 60: # Example threshold
cv2.putText(image, "EXCESSIVE BOUNCE", (50, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2, cv2.LINE_AA)
hip_y_positions.pop(0)
except Exception as e:
# print(e) # For debugging
pass
mp_drawing.draw_landmarks(image, results.pose_landmarks, mp_pose.POSE_CONNECTIONS)
cv2.imshow('Running Form Analyzer', image)
if cv2.waitKey(5) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
analyze_running_form('running_video.mp4')
Tipps für den Produktionseinsatz
- Kalibrierung: Für genaue reale Messungen (cm statt Pixel) müssen Sie eine Kamerakalibrierung durchführen. Dazu könnte ein Objekt bekannter Höhe (z. B. ein Kegel) neben dem Laufband platziert werden.
- Leistung: MediaPipe ist recht effizient, doch für eine Echtzeitanalyse auf Geräten mit geringer Rechenleistung können Sie ein leichteres Modell verwenden oder die Videoauflösung verringern.
- Benutzeroberfläche: Für eine benutzerfreundliche Anwendung könnten Sie mit Flask oder Streamlit eine einfache Weboberfläche erstellen, über die Benutzerinnen und Benutzer ihre Videos hochladen und die Ergebnisse ansehen können.
Fazit
Wir haben erfolgreich ein Werkzeug erstellt, das Läuferinnen und Läufern wertvolles biomechanisches Feedback geben kann. Mithilfe von OpenCV und MediaPipe konnten wir über die einfache Videowiedergabe hinausgehen und in den Bereich der quantitativen Analyse vordringen. Dieses Projekt zeigt die Möglichkeiten der Computer Vision im Gesundheits- und Fitnessbereich und ist ein guter Ausgangspunkt für fortgeschrittenere Projekte in der Sportanalytik.
Nächste Schritte
- Implementieren Sie einen robusteren Algorithmus zur Erkennung des Foot Strike.
- Ergänzen Sie die Analyse um weitere Laufkennzahlen wie die Kadenz (Schritte pro Minute).
- Erstellen Sie ein System, das Veränderungen der Lauftechnik im Zeitverlauf verfolgt, um den Fortschritt zu überwachen.
Ressourcen
- OpenCV-Dokumentation: https://docs.opencv.org/
Kurzüberblick
| Aspekt | Wichtige Information |
|---|---|
| Thema | Entwicklung |
| Relevanz | Patienteninformation und Aufklärung |
| Maßnahme | Besprechen Sie dies mit Ihrer Ärztin oder Ihrem Arzt |
| Häufigkeit | Wie von Ihrem Behandlungsteam empfohlen |
| Evidenz | Basierend auf aktuellen klinischen Leitlinien |
Häufig gestellte Fragen
F: Wie weiß ich, ob das auf mich zutrifft? A: Besprechen Sie Ihre persönliche und familiäre Krankengeschichte mit Ihrer Ärztin oder Ihrem Arzt, um Ihre individuellen Risikofaktoren zu beurteilen und geeignete nächste Schritte festzulegen.
F: Was sollte ich meine Ärztin oder meinen Arzt fragen? A: Gute Fragen sind: „Was bedeuten meine Ergebnisse?“, „Welche Möglichkeiten habe ich?“, „Welche Lebensstiländerungen würden helfen?“ und „Wann sollte ich zur Nachsorge kommen?“
F: Gibt es Lebensstiländerungen, die helfen können? A: Die meisten Erkrankungen profitieren von grundlegenden Maßnahmen: ausgewogene Ernährung, regelmäßige körperliche Aktivität (150+ Minuten/Woche), erholsamer Schlaf (7–9 Stunden), Stressbewältigung und Verzicht auf Tabak.
Medizinischer Haftungsausschluss
Dieser Artikel dient ausschließlich der Information und stellt keine medizinische Beratung dar. Konsultieren Sie stets eine qualifizierte medizinische Fachperson, bevor Sie Entscheidungen über Ihre Gesundheit, Behandlung oder Versorgung treffen. Individuelle Umstände unterscheiden sich, und was für eine Person angemessen ist, muss für eine andere nicht angemessen sein.
Wenn Sie einen medizinischen Notfall erleben, rufen Sie sofort 911 (oder Ihre örtliche Notrufnummer) an.