Mit der ML Kit Pose Detection API können Sie die relativen Positionen verschiedener Körperteile prüfen und so aussagekräftige Interpretationen einer Pose ableiten. Auf dieser Seite werden einige Beispiele vorgestellt.
Posenklassifizierung und Zählung von Wiederholungen mit dem k-NN-Algorithmus
Eine der häufigsten Anwendungen der Posenerkennung ist das Fitness-Tracking. Das Erstellen eines Posenklassifikators, der bestimmte Fitnesspositionen erkennt und Wiederholungen zählt, kann für Entwickler eine Herausforderung sein.
In diesem Abschnitt wird beschrieben, wie wir mit MediaPipe Colab einen benutzerdefinierten Posenklassifikator erstellt und einen funktionierenden Klassifikator in unserer ML Kit-Beispiel-App demonstriert haben.
Wenn Sie mit Google Colaboratory nicht vertraut sind, lesen Sie die Einführung.
Um Posen zu erkennen, verwenden wir den Algorithmus der k-nächsten Nachbarn (k-NN), da er einfach und leicht zu beginnen ist. Der Algorithmus bestimmt die Klasse des Objekts basierend auf den nächstgelegenen Beispielen im Trainingssatz.
Führen Sie die folgenden Schritte aus, um die Erkennung zu erstellen und zu trainieren:
1. Bildbeispiele erfassen
Wir haben Bildbeispiele der Zielübungen aus verschiedenen Quellen gesammelt. Für jede Übung wählen wir ein paar hundert Bilder aus, z. B. die „nach oben“- und „nach unten“-Positionen für Liegestütze. Es ist wichtig, Proben zu sammeln, die verschiedene Kamerawinkel, Umgebungsbedingungen, Körperformen und Trainingsvarianten abdecken.
2. Posenerkennung für Beispielbilder ausführen
Dadurch werden eine Reihe von Posen-Markierungspunkten erstellt, die für das Training verwendet werden können. Wir sind nicht an der Posenerkennung selbst interessiert, da wir im nächsten Schritt unser eigenes Modell trainieren.
Der k-NN-Algorithmus, den wir für die benutzerdefinierte Posenklassifizierung ausgewählt haben, erfordert eine Featurevektordarstellung für jede Stichprobe und einen Messwert zur Berechnung der Entfernung zwischen zwei Vektoren, um das Ziel zu finden, das der Posenprobe am nächsten ist. Das bedeutet, dass wir die gerade erhaltenen Posen-Markierungen konvertieren müssen.
Um Posen-Markierungen in einen Featurevektor umzuwandeln, verwenden wir paarweise Abstände zwischen vordefinierten Listen von Posenverbindungen, z. B. den Abstand zwischen Handgelenk und Schulter, Knöchel und Hüfte sowie linkes und rechtes Handgelenk. Da der Maßstab von Bildern variieren kann, haben wir die Posen vor dem Konvertieren der Orientierungspunkte so normalisiert, dass sie dieselbe Rumpfgröße und vertikale Rumorausrichtung haben.
3. Modell trainieren und Wiederholungen zählen
Wir haben MediaPipe Colab verwendet, um auf den Code für den Klassifikator zuzugreifen und das Modell zu trainieren.
Zum Zählen von Wiederholungen haben wir einen weiteren Colab-Algorithmus verwendet, um den Wahrscheinlichkeitsgrenzwert einer Zielposition zu überwachen. Beispiel:
- Wenn die Wahrscheinlichkeit der Posenklasse „nach unten“ zum ersten Mal einen bestimmten Grenzwert überschreitet, markiert der Algorithmus, dass die Posenklasse „nach unten“ eingegeben wurde.
- Wenn die Wahrscheinlichkeit unter den Grenzwert fällt, markiert der Algorithmus, dass die Posenklasse „Abwärts“ beendet wurde, und erhöht den Zähler.
4. ML Kit-Kurzanleitungs-App einbinden
Das obige Colab erstellt eine CSV-Datei, in die Sie alle Ihre Posen-Beispiele einfügen können. In diesem Abschnitt erfahren Sie, wie Sie Ihre CSV-Datei in die ML Kit Android-Kurzanleitungs-App einbinden, um benutzerdefinierte Posenklassifizierung in Echtzeit zu sehen.
Mit Beispielen, die in der Kurzanleitung gebündelt sind, die Positionsklassifizierung testen
- Laden Sie das ML Kit Android-Kurzanleitungs-App-Projekt von GitHub herunter und prüfen Sie, ob es einwandfrei erstellt und ausgeführt werden kann.
- Rufe
LivePreviewActivity
auf und aktiviere auf der Seite „Einstellungen“ die PositionserkennungRun classification
. Jetzt solltest du Liegestütze und Kniebeugen klassifizieren können.
Eigene CSV-Datei hinzufügen
- Fügen Sie die CSV-Datei dem Asset-Ordner der App hinzu.
- Aktualisieren Sie in PoseClassifierProcessor die Variablen
POSE_SAMPLES_FILE
undPOSE_CLASSES
, damit sie Ihrer CSV-Datei entsprechen und Beispiele darstellen. - Erstellen Sie die Anwendung und führen Sie sie aus.
Beachten Sie, dass die Klassifizierung möglicherweise nicht gut funktioniert, wenn nicht genügend Beispiele vorhanden sind. Im Allgemeinen benötigen Sie etwa 100 Beispiele pro Posenklasse.
Weitere Informationen und dazu, wie Sie dies selbst ausprobieren können, finden Sie im MediaPipe Colab- und im MediaPipe-Klassifizierungsleitfaden.
Einfache Gesten durch Berechnung der Entfernung von Orientierungspunkten erkennen
Wenn zwei oder mehr Orientierungspunkte nah beieinander sind, können sie verwendet werden, um Gesten zu erkennen. Wenn sich beispielsweise die Markierung für einen oder mehrere Finger einer Hand nahe an der Markierung für die Nase befindet, können Sie daraus ableiten, dass der Nutzer am ehesten das Gesicht berührt.
Eine Yogastellung mit Winkelheuristik erkennen
Du kannst eine Yogastellung bestimmen, indem du die Winkel verschiedener Gelenke berechnest. Abbildung 2 unten zeigt zum Beispiel die Yogastellung von Warrior II. Die ungefähren Winkel, die diese Pose identifizieren, sind so angegeben:
Diese Pose kann als folgende Kombination aus ungefähren Winkeln der Körperteile beschrieben werden:
- 90-Grad-Winkel an beiden Schultern
- 180 Grad bei beiden Ellbogen
- 90-Grad-Winkel an vorderem Bein und an der Taille
- 180-Grad-Winkel am hinteren Knie
- 135-Grad-Winkel an der Taille
Sie können die Positionsmarkierungen verwenden, um diese Winkel zu berechnen. Beispielsweise ist der Winkel am rechten vorderen Bein und an der Taille der Winkel zwischen der Linie von der rechten Schulter zur rechten Hüfte und der Linie von der rechten Hüfte zum rechten Knie.
Nachdem Sie alle Winkel berechnet haben, die zum Identifizieren der Position erforderlich sind, können Sie überprüfen, ob es eine Übereinstimmung gibt. In diesem Fall haben Sie die Position erkannt.
Das folgende Code-Snippet zeigt, wie mithilfe der x- und y-Koordinaten der Winkel zwischen zwei Körperteilen berechnet wird. Dieser Klassifizierungsansatz hat einige Einschränkungen. Indem Sie nur X und Y überprüfen, variieren die berechneten Winkel entsprechend dem Winkel zwischen Objekt und Kamera. Die besten Ergebnisse erzielen Sie mit einem neutralen, direkt ausgerichteten Bild. Sie können auch versuchen, diesen Algorithmus mithilfe der Z-Koordinate zu erweitern, um festzustellen, ob er für Ihren Anwendungsfall besser funktioniert.
Winkel der Sehenswürdigkeiten unter Android berechnen
Mit der folgenden Methode wird der Winkel zwischen drei beliebigen Sehenswürdigkeiten berechnet. Sie sorgt dafür, dass der zurückgegebene Winkel zwischen 0 und 180 Grad liegt.
Kotlin
fun getAngle(firstPoint: PoseLandmark, midPoint: PoseLandmark, lastPoint: PoseLandmark): Double { var result = Math.toDegrees(atan2(lastPoint.getPosition().y - midPoint.getPosition().y, lastPoint.getPosition().x - midPoint.getPosition().x) - atan2(firstPoint.getPosition().y - midPoint.getPosition().y, firstPoint.getPosition().x - midPoint.getPosition().x)) result = Math.abs(result) // Angle should never be negative if (result > 180) { result = 360.0 - result // Always get the acute representation of the angle } return result }
Java
static double getAngle(PoseLandmark firstPoint, PoseLandmark midPoint, PoseLandmark lastPoint) { double result = Math.toDegrees( atan2(lastPoint.getPosition().y - midPoint.getPosition().y, lastPoint.getPosition().x - midPoint.getPosition().x) - atan2(firstPoint.getPosition().y - midPoint.getPosition().y, firstPoint.getPosition().x - midPoint.getPosition().x)); result = Math.abs(result); // Angle should never be negative if (result > 180) { result = (360.0 - result); // Always get the acute representation of the angle } return result; }
So berechnen Sie den Winkel an der rechten Hüfte:
Kotlin
val rightHipAngle = getAngle( pose.getPoseLandmark(PoseLandmark.Type.RIGHT_SHOULDER), pose.getPoseLandmark(PoseLandmark.Type.RIGHT_HIP), pose.getPoseLandmark(PoseLandmark.Type.RIGHT_KNEE))
Java
double rightHipAngle = getAngle( pose.getPoseLandmark(PoseLandmark.Type.RIGHT_SHOULDER), pose.getPoseLandmark(PoseLandmark.Type.RIGHT_HIP), pose.getPoseLandmark(PoseLandmark.Type.RIGHT_KNEE));
Winkel der Sehenswürdigkeiten unter iOS berechnen
Mit der folgenden Methode wird der Winkel zwischen drei beliebigen Sehenswürdigkeiten berechnet. Sie sorgt dafür, dass der zurückgegebene Winkel zwischen 0 und 180 Grad liegt.
Swift
func angle( firstLandmark: PoseLandmark, midLandmark: PoseLandmark, lastLandmark: PoseLandmark ) -> CGFloat { let radians: CGFloat = atan2(lastLandmark.position.y - midLandmark.position.y, lastLandmark.position.x - midLandmark.position.x) - atan2(firstLandmark.position.y - midLandmark.position.y, firstLandmark.position.x - midLandmark.position.x) var degrees = radians * 180.0 / .pi degrees = abs(degrees) // Angle should never be negative if degrees > 180.0 { degrees = 360.0 - degrees // Always get the acute representation of the angle } return degrees }
Objective-C
(CGFloat)angleFromFirstLandmark:(MLKPoseLandmark *)firstLandmark midLandmark:(MLKPoseLandmark *)midLandmark lastLandmark:(MLKPoseLandmark *)lastLandmark { CGFloat radians = atan2(lastLandmark.position.y - midLandmark.position.y, lastLandmark.position.x - midLandmark.position.x) - atan2(firstLandmark.position.y - midLandmark.position.y, firstLandmark.position.x - midLandmark.position.x); CGFloat degrees = radians * 180.0 / M_PI; degrees = fabs(degrees); // Angle should never be negative if (degrees > 180.0) { degrees = 360.0 - degrees; // Always get the acute representation of the angle } return degrees; }
So berechnen Sie den Winkel an der rechten Hüfte:
Swift
let rightHipAngle = angle( firstLandmark: pose.landmark(ofType: .rightShoulder), midLandmark: pose.landmark(ofType: .rightHip), lastLandmark: pose.landmark(ofType: .rightKnee))
Objective-C
CGFloat rightHipAngle = [self angleFromFirstLandmark:[pose landmarkOfType:MLKPoseLandmarkTypeRightShoulder] midLandmark:[pose landmarkOfType:MLKPoseLandmarkTypeRightHip] lastLandmark:[pose landmarkOfType:MLKPoseLandmarkTypeRightKnee]];