Opcje klasyfikacji ułożenia

Dzięki interfejsowi ML Kit Pose Detection API możesz uzyskać istotne interpretacje pozy, sprawdzając względne pozycje różnych części ciała. Na tej stronie znajdziesz kilka przykładów.

Klasyfikacja pozy i zliczanie 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 zbudowaliśmy niestandardowy klasyfikator postaw za pomocą MediaPipe Colab, oraz pokazujemy działający klasyfikator w naszej przykładowej aplikacji ML Kit.

Jeśli nie znasz Google Colaboratory, zapoznaj się z przewodnikiem wprowadzającym.

Do rozpoznawania póz używamy algorytmu najbliższych sąsiadów, ponieważ jest on prosty i łatwy do rozpoczęcia. Algorytm określa klasę obiektu na podstawie najbliższych próbek w zbiorze szkoleniowym.

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

1. Zbieranie przykładów 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 zebrać próbki, które obejmują różne kąty kamery, warunki środowiskowe, kształty ciała i wariacje ćwiczeń.

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

2. Uruchom wykrywanie pozycji na przykładowych obrazach

W ten sposób powstaje 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ć właśnie uzyskane punkty orientacyjne pozy.

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, aby uzyskać dostęp do kodu klasyfikatora i przeprowadzić szkolenie modelu.

Aby policzyć powtórzenia, użyliśmy innego algorytmu Colab do monitorowania progu prawdopodobieństwa docelowej pozycji postawy. 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 spadnie poniżej progu, algorytm oznacza, że klasa postawy „w dół” została zamknięta, i zwiększa licznik.
Rysunek 2. Przykład zliczania 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. Z tej sekcji dowiesz się, jak zintegrować plik CSV z aplikacją quickstart ML Kit na Androida, aby wyświetlać klasyfikację niestandardowych póz 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 funkcji PoseClassifierProcessor zaktualizuj zmienne POSE_SAMPLES_FILEPOSE_CLASSES, aby pasowały do pliku CSV i próbek pozy.
  • Skompiluj i uruchom 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 spróbować samodzielnie, skorzystaj z MediaPipe Colabprzewodnika po klasyfikacji MediaPipe.

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

Jeśli 2 lub więcej punktów orientacyjnych znajduje się blisko siebie, można ich użyć do rozpoznawania gestów. Jeśli na przykład punkt orientacyjny odpowiadający co najmniej jednemu palcu na dłoni jest blisko punktu orientacyjnego odpowiadającego nosowi, można wywnioskować, że użytkownik najprawdopodobniej dotyka twarzy.

Rysunek 3. Interpretacja pozycji

rozpoznawanie pozycji jogi za pomocą heurystyki kąta;

Możesz określić pozycję jogi, obliczając kąty różnych stawów. Na przykład rysunek 2 poniżej przedstawia pozycję jogi Wojownik II. Przybliżone kąty, które identyfikują tę pozę, są podane w tych formatach:

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 w obu łokciach
  • Kąt 90° w przypadku przedniej części nogi i talii
  • Kąt pod kątem 180 stopni w tylnej części kolana
  • Kąt pod kątem 135 stopni w talii

Aby obliczyć te kąty, możesz użyć punktów orientacyjnych pozy. Na przykład kąt na prawej nodze z przodu i na wysokości talii to kąt między linią od prawego ramienia do prawego biodra i linią 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ą. Najlepsze wyniki uzyskasz, jeśli zrobisz zdjęcie z boku, z przodu i w poziomie. 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 punktów orientacyjnych na urządzeniach z Androidem

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 punktów orientacyjnych na iOS

W tej metodzie obliczany jest kąt między dowolnymi trzema punktami orientacyjnymi. 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 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]];