Dzięki interfejsowi ML Kit Pose Detection API możesz uzyskać istotne interpretacje pozycji, sprawdzając względne położenie różnych części ciała. Na tej stronie znajdziesz kilka przykładów.
Klasyfikacja pozycji i zliczanie powtórzeń za pomocą algorytmu k-NN
Jednym z najczęstszych zastosowań wykrywania pozycji jest monitorowanie aktywności fizycznej. Dla deweloperów stworzenie klasyfikatora pozycji, który rozpoznaje określone pozycje fitness i zlicza powtórzenia, może być wyzwaniem.
W tej sekcji opisujemy, jak za pomocą MediaPipe Colab stworzyliśmy klasyfikator pozycji niestandardowej, a także zademonstrowaliśmy działający klasyfikator w naszej przykładowej aplikacji ML Kit.
Jeśli nie znasz jeszcze Google Colaboratory, zapoznaj się z przewodnikiem wprowadzającym.
Do rozpoznawania pozycji używamy algorytmu k-najbliższych sąsiadów (k-NN), ponieważ jest on prosty i łatwy. Algorytm określa klasę obiektu na podstawie najbliższych przykładów w zbiorze treningowym.
Aby utworzyć i wytrenować moduł rozpoznawania, wykonaj te czynności:
1. Zbieranie próbek obrazów
Zebraliśmy próbki obrazów docelowych ćwiczeń z różnych źródeł. Do każdego ćwiczenia wybraliśmy kilkaset obrazów, np. w przypadku pompek i pozycji „w górę” i „w dół”. Ważne jest, by zbierać próbki przedstawiające różne kąty kamery, warunki otoczenia, budowę ciała i warianty ćwiczeń.
2. Uruchom wykrywanie pozycji na przykładowych obrazach
W ten sposób powstaje zestaw punktów orientacyjnych umiejscowienia do wykorzystania podczas trenowania. Nie interesuje nas samo wykrywanie pozycji, ponieważ w kolejnym kroku będziemy wytrenować własny model.
Algorytm k-NN wybrany do niestandardowej klasyfikacji pozycji wymaga przedstawienia wektorowej reprezentacji każdej próbki oraz danych do obliczenia odległości między 2 wektorami w celu znalezienia miejsca docelowego najbliżej próbki pozycji. Oznacza to, że musimy przekonwertować uzyskane w ten sposób punkty orientacyjne.
Aby przekonwertować punkty orientacyjne ułożenia na wektor cech, korzystamy z odległości między predefiniowanymi listami stawów, np. odległości między nadgarstkiem a ramieniem, kostką i biodrem oraz lewym i prawym nadgarstkiem. Ponieważ skala zdjęć może być różna, znormalizowaliśmy pozycje tak, aby miały tę samą wielkość tułów i pionową orientację tułów, zanim przekonwertujemy punkty orientacyjne.
3. Wytrenuj model i zliczaj powtórzenia
Użyliśmy usługi MediaPipe Colab, aby uzyskać dostęp do kodu klasyfikatora i wytrenować model.
Aby zliczyć powtórzenia, zastosowaliśmy inny algorytm Colab do monitorowania progu prawdopodobieństwa wystąpienia pozycji docelowej. Na przykład:
- Gdy prawdopodobieństwo, że klasa pozycji „w dół” po raz pierwszy przekroczy dany próg, algorytm zaznaczy, że wpisano klasę „niżej”.
- Gdy prawdopodobieństwo spada poniżej progu, algorytm oznacza, że klasa pozycji „w dół” została opuszczona, i zwiększa licznik.
4. Integracja z aplikacją z krótkim wprowadzeniem do ML Kit
Powyższe polecenie w Colab utworzy plik CSV, w którym możesz umieścić wszystkie przykładowe pozycje. W tej sekcji dowiesz się, jak zintegrować plik CSV z aplikacją z krótkim wprowadzeniem do aplikacji ML Kit na Androida, aby zobaczyć klasyfikację niestandardowych pozycji w czasie rzeczywistym.
Wypróbuj klasyfikację pozycji z przykładami dołączonymi do aplikacji z krótkim wprowadzeniem
- Pobierz z GitHuba projekt aplikacji krótkiego wprowadzenia do systemu ML Kit na Androida i sprawdź, czy kompilowa się ona i działa poprawnie.
- Otwórz
LivePreviewActivity
i włącz Wykrywanie pozycjiRun classification
na stronie Ustawienia. Teraz umiesz klasyfikować pompki i przysiady.
Dodaj własny plik CSV
- Dodaj plik CSV do folderu komponentów w aplikacji.
- W PoseClassifierProcessor zaktualizuj zmienne
POSE_SAMPLES_FILE
iPOSE_CLASSES
, aby pasowały do pliku CSV i próbek pozy. - Skompiluj i uruchom aplikację.
Pamiętaj, że klasyfikacja może nie działać prawidłowo, jeśli nie ma wystarczającej liczby próbek. Na każdą klasę pozycji potrzebujesz około 100 próbek.
Aby dowiedzieć się więcej i samodzielnie wypróbować tę funkcję, zapoznaj się z artykułami na temat MediaPipe Colab i przewodnika po klasyfikacji MediaPipe.
Rozpoznawanie prostych gestów przez obliczanie odległości punktu orientacyjnego
Jeśli co najmniej 2 punkty orientacyjne znajdują się blisko siebie, można ich używać do rozpoznawania gestów. Jeśli na przykład punkt orientacyjny co najmniej jednego palca na dłoni znajduje się blisko punktu orientacyjnego z nosem, możesz wywnioskować, że użytkownik najprawdopodobniej dotyka twarzy.
Rozpoznawanie pozycji jogi za pomocą heurystyki kąta
Pozycja jogi można rozpoznać po obliczeniu kątów różnych stawów. Na przykład rysunek 2 poniżej przedstawia pozycję w jodze Wojownik II. Przybliżone kąty, które określają tę pozycję, są zapisane:
Tę pozycję można opisać jako kombinację przybliżonych kątów ciała:
- Obie ramiona pod kątem 90 stopni
- 180 stopni na obu łokciach
- Pod kątem 90 stopni przy przedniej nodze i talii
- Kąt kolana z tyłu pod kątem 180 stopni
- Kąt w pasie pod kątem 135 stopni
Możesz użyć punktów orientacyjnych pozycji do obliczenia tych kątów. Na przykład kąt między przednimi nogami i talią to kąt między linii od prawego ramienia do prawego biodra i linii od prawego biodra do prawego kolana.
Gdy obliczysz wszystkie kąty potrzebne do zidentyfikowania pozycji, możesz sprawdzić, czy nic nie pasuje i wtedy udało Ci się rozpoznać pozę.
Fragment kodu poniżej pokazuje, jak użyć współrzędnych X i Y do obliczenia kąta między dwiema częściami ciała. Takie podejście do klasyfikacji ma pewne ograniczenia. Wystarczy zaznaczyć X i Y, a obliczone kąty będą się różnić zależnie od kąta między obiektem a kamerą. Najlepsze wyniki uzyskasz, używając poziomego obrazu z przodu. Możesz też spróbować rozszerzyć ten algorytm, używając współrzędnej Z, i sprawdzić, czy sprawdza się on w Twoim przypadku.
Obliczanie kątów punktu orientacyjnego na Androidzie
Ta metoda oblicza kąt między dowolnymi 3 punktami orientacyjnymi. Zapewnia on, że zwrócony kąt wynosi od 0 do 180 stopni.
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; }
Oto jak obliczyć kąt w prawym biodrze:
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));
Obliczanie kątów punktu orientacyjnego na urządzeniu z iOS
Ta metoda oblicza kąt między dowolnymi 3 punktami orientacyjnymi. Zapewnia on, że zwrócony kąt wynosi od 0 do 180 stopni.
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; }
Oto jak obliczyć kąt w prawym biodrze:
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]];