Opcje klasyfikacji ułożenia

Dzięki interfejsowi ML Kit Pose Detection API możesz wyciągać wnioski ułożenia pozycji przez sprawdzenie względnych pozycji różnych części ciała. Ta strona przedstawi kilka przykładów.

Klasyfikacja pozycji i liczenie powtórzeń za pomocą algorytmu k-NN

Jednym z najczęstszych zastosowań wykrywania pozycji jest śledzenie aktywności. Tworzenie klasyfikatora pozycji, który rozpoznaje określone pozycje i liczebniki sprawności fizycznej i powtórzenia to nie lada wyzwanie dla programistów.

W tej sekcji opisujemy, jak utworzyć niestandardową pozę klasyfikatora za pomocą MediaPipe Colab, zademonstrować działający klasyfikator w naszej przykładowej aplikacji ML Kit.

Jeśli nie znasz Google Colaboratory, zapoznaj się z przewodnika.

Do rozpoznawania póz używamy algorytmu k-najbliższych sąsiadów (k-NN), ponieważ jest on prosty jest łatwa w użyciu. Algorytm określa klasę obiektu na podstawie jak najbliższe próbki w zbiorze treningowym.

Aby utworzyć i wytrenować moduł rozpoznawania, wykonaj te czynności:

1. Zbieranie próbek obrazów

Zebraliśmy z różnych źródeł próbki obrazów ćwiczeń docelowych. Śr wybrać po kilkaset zdjęć dla każdego ćwiczenia, np. "w górę", i „w dół” pozycje do pompek. Ważne jest, aby zbierać próbki obejmujące różne aparaty kątów, warunków środowiskowych, kształtów ciała i wahań ćwiczeń.

Rysunek 1. Pozycje pompki w górę i w dół

2. Uruchom wykrywanie pozycji na przykładowych obrazach

W ten sposób powstanie zestaw punktów orientacyjnych pozycji do trenowania. Nie jesteśmy zainteresowanym samym wykrywaniem pozycji, ponieważ będziemy trenować dla swojego modelu.

Wybrany algorytm k-NN do niestandardowej klasyfikacji pozycji wymaga reprezentacja wektorów cech dla każdej próby i wskaźnika do obliczenia odległość między dwoma wektorami, aby znaleźć wartość docelową najbliższą danej pozycji. Oznacza to, że musimy przekonwertować uzyskane punkty orientacyjne pozycji.

Aby przekonwertować punkty orientacyjne ułożenia na wektor cech, korzystamy z odległości w parach między wstępnie zdefiniowanymi listami stawów, np. odległość między nadgarstkiem ramiona, kostki i biodra, a także lewe i prawe nadgarstki. Skala obrazów mogą się wahać, znormalizowaliśmy pozycje, aby miały taki sam rozmiar tułowia i pionową sylwetkę przed przekształceniem punktów orientacyjnych.

3. Wytrenuj model i zlicz powtórzenia

Użyliśmy MediaPipe Colab, by uzyskać dostęp do kodu klasyfikatora. i wytrenować model.

Do liczenia powtórzeń użyliśmy innego algorytmu Colab do monitorowania prawdopodobieństwa, w pozycji docelowej. Na przykład:

  • Gdy prawdopodobieństwo spadku wartości klasa pozycji przekracza określony próg dla za pierwszym razem algorytm zaznacza, że słowo „w dół” klasa pozycji została opublikowana.
  • Gdy prawdopodobieństwo spada poniżej progu, algorytm oznacza, że „w dół” klasa pozycji została zamknięta i zwiększa licznik.
Rysunek 2. Przykład liczenia powtórzeń

4. Integracja z aplikacją ML Kit

Powyższy kod Colab generuje plik CSV, w którym możesz podać całą ustaloną pozycję przykłady. W tej sekcji dowiesz się, jak zintegrować plik CSV z narzędziem Aplikacja ML Kit na Androida z niestandardową klasyfikacją pozycji w czasie rzeczywistym.

Wypróbuj klasyfikację pozycji z przykładami dostępnymi w aplikacji z krótkim wprowadzeniem

Dodaj własny plik CSV

  • Dodaj plik CSV do folderu zasobów aplikacji.
  • W klastrze PoseClassifierProcessor zaktualizuj zmienne POSE_SAMPLES_FILE i POSE_CLASSES, tak by pasowały do Plik CSV i przykłady pozycji.
  • Skompilować i uruchomić aplikację.

Pamiętaj, że klasyfikacja może nie działać dobrze, jeśli nie ma wystarczającej liczby próbek. Ogólnie potrzebujesz około 100 próbek na każdą klasę pozycji.

Aby dowiedzieć się więcej i samodzielnie wypróbować tę funkcję, zajrzyj do MediaPipe Colab i Przewodnik po klasyfikacji MediaPipe.

Rozpoznawanie prostych gestów przez obliczanie odległości do punktu orientacyjnego

Gdy co najmniej dwa punkty orientacyjne znajdują się blisko siebie, można ich używać do: rozpoznawania gestów. Na przykład gdy punkt orientacyjny dla co najmniej jednego palca na zdjęciu jest blisko punktu orientacyjnego nosa, można więc wywnioskować, że użytkownik najbardziej dotyka twarzy.

Rysunek 3. Interpretacja pozycji

Rozpoznawanie pozycji jogi na podstawie heurystyki kąta

Pozycję jogi można rozpoznać po pomiarze kątów różnych stawów. Dla: Rysunek 2 poniżej przedstawia pozycję jogi Wojownika II. Przybliżone kąty identyfikujące tę pozę są zapisane w języku:

Rysunek 4. Podział ujęć pod kątem różnych pozycji

Ta pozycja może zostać opisana w ten sposób: kąty części:

  • Kąt pod kątem obu ramion
  • 180 stopni na obu łokciach
  • Kąt pod kątem 90 stopni z przedniej nogi i talii
  • Kąt pod kątem 180 stopni w tylnej części kolana
  • Kąt pod kątem 135 stopni w talii

Możesz użyć punktów orientacyjnych pozycji, aby obliczyć te kąty. Na przykład kąt przy prawej przedniej nodze, a w pasie to kąt między linią od prawej od ramienia do prawego biodra i linii od prawego biodra do prawego kolana.

Po obliczeniu wszystkich kątów potrzebnych do określenia pozycji możesz sprawdzić aby sprawdzić, czy uda Ci się znaleźć dopasowanie. W takim przypadku rozpoznasz pozy.

Fragment kodu poniżej pokazuje, jak używać współrzędnych X i Y do oblicz kąt między dwiema częściami ciała. Takie podejście do klasyfikacji ma pewne ograniczenia. Po zaznaczeniu tylko wartości X i Y obliczone kąty będą się różnić zgodnie z kątem między obiektem a kamerą. Otrzymasz aby uzyskać najlepsze wyniki, wystarczająco proste. Możesz też spróbuj rozszerzyć ten algorytm, korzystając z Współrzędna Z i sprawdzić, czy sprawdza się lepiej w Twoim przypadku użycia.

Obliczanie kątów punktu orientacyjnego na Androidzie

Poniższa metoda oblicza kąt między dowolnymi 3 dowolnych punkty orientacyjne. Daje on pewność, że zwrócony kąt znajduje się między 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 przy prawej 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ądzeniach z iOS

Poniższa metoda oblicza kąt między dowolnymi 3 dowolnych punkty orientacyjne. Daje on pewność, że zwrócony kąt znajduje się między 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 przy prawej 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]];