Zadanie MediaPipe Pose Landmarker umożliwia wykrywanie punktów orientacyjnych ciała ludzkiego na obrazie lub filmie. Za pomocą tego zadania możesz identyfikować kluczowe części ciała, analizować postawę oraz kategoryzować ruchy. To zadanie korzysta z modeli systemów uczących się, które działają z pojedynczymi obrazami lub filmami. Zadanie wyprowadza punkty orientacyjne postawy ciała w współrzędnych obrazu i w trójwymiarowych współrzędnych świata.
Przykładowy kod opisany w tych instrukcjach jest dostępny na GitHub. Więcej informacji o możliwościach, modelach i opcjach konfiguracji związanych z tym zadaniem znajdziesz w sekcji Omówienie.
Przykładowy kod
Przykładowy kod MediaPipe Tasks to prosta implementacja aplikacji do wykrywania punktów orientacyjnych postawy na Androida. Przykład wykorzystuje kamerę na fizycznym urządzeniu z Androidem do wykrywania póz w ciągłym strumieniu wideo. Aplikacja może też wykrywać pozy w obrazach i filmach z galerii urządzenia.
Możesz użyć tej aplikacji jako punktu wyjścia do tworzenia własnej aplikacji na Androida lub skorzystać z niej podczas modyfikowania istniejącej aplikacji. Przykładowy kod usługi Pose Landmarker jest hostowany na GitHub.
Pobieranie kodu
Z tych instrukcji dowiesz się, jak utworzyć lokalną kopię przykładowego kodu za pomocą narzędzia wiersza poleceń git.
Aby pobrać przykładowy kod:
- Sklonuj repozytorium Git za pomocą tego polecenia:
git clone https://github.com/google-ai-edge/mediapipe-samples
- Opcjonalnie skonfiguruj instancję git do użycia rzadkiego sprawdzania, aby mieć tylko pliki przykładowej aplikacji Pose Landmarker:
cd mediapipe git sparse-checkout init --cone git sparse-checkout set examples/pose_landmarker/android
Po utworzeniu lokalnej wersji przykładowego kodu możesz zaimportować projekt do Android Studio i uruchomić aplikację. Instrukcje znajdziesz w przewodniku konfiguracji Androida.
Kluczowe komponenty
W tych plikach znajduje się kod, który jest kluczowy dla przykładowej aplikacji do oznaczania punktów orientacyjnych pozy:
- PoseLandmarkerHelper.kt – inicjalizuje punkt orientacyjny pozy i obsługuje model oraz wybór delegata.
- CameraFragment.kt – obsługuje kamerę urządzenia i przetwarza dane wejściowe obrazu i wideo.
- GalleryFragment.kt – współpracuje z
OverlayView
, aby wyświetlić obraz lub film wyjściowy. - OverlayView.kt – implementuje wyświetlanie wykrytych póz.
Konfiguracja
W tej sekcji opisaliśmy kluczowe kroki konfigurowania środowiska programistycznego i projektów kodu w celu używania narzędzia Pose Landmarker. Ogólne informacje o konfigurowaniu środowiska programistycznego do korzystania z zadań MediaPipe, w tym wymagania dotyczące wersji platformy, znajdziesz w przewodniku konfiguracji na Androida.
Zależności
Zadanie polegające na wyznaczaniu punktów orientacyjnych w pozie korzysta z biblioteki com.google.mediapipe:tasks-vision
. Dodaj tę zależność do pliku build.gradle
aplikacji na Androida:
dependencies {
implementation 'com.google.mediapipe:tasks-vision:latest.release'
}
Model
Zadanie MediaPipe Pose Landmarker wymaga przetestowanego modelu, który jest zgodny z tym zadaniem. Więcej informacji o dostępnych wytrenowanych modelach usługi Pose Landmarker znajdziesz w sekcji Modele w omówieniu zadania.
Wybierz i pobierz model, a potem zapisz go w katalogu projektu:
<dev-project-root>/src/main/assets
W parametrze ModelAssetPath
podaj ścieżkę do modelu. W przykładowym kodzie model jest zdefiniowany w pliku PoseLandmarkerHelper.kt
:
val modelName = "pose_landmarker_lite.task"
baseOptionsBuilder.setModelAssetPath(modelName)
Tworzenie zadania
Do konfiguracji zadania MediaPipe Pose Landmarker służy funkcja createFromOptions()
. Funkcja createFromOptions()
akceptuje wartości opcji konfiguracji. Więcej informacji o opcjach konfiguracji znajdziesz w artykule Opcje konfiguracji.
Narzędzie Pose Landmarker obsługuje te typy danych wejściowych: obrazy, pliki wideo i transmisje wideo na żywo. Podczas tworzenia zadania musisz określić tryb wykonywania odpowiadający typowi danych wejściowych. Aby dowiedzieć się, jak utworzyć zadanie, wybierz kartę odpowiadającą typowi danych wejściowych.
Obraz
val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(modelName) val baseOptions = baseOptionBuilder.build() val optionsBuilder = poseLandmarker.poseLandmarkerOptions.builder() .setBaseOptions(baseOptionsBuilder.build()) .setMinPoseDetectionConfidence(minPoseDetectionConfidence) .setMinTrackingConfidence(minPoseTrackingConfidence) .setMinPosePresenceConfidence(minposePresenceConfidence) .setNumPoses(maxNumPoses) .setRunningMode(RunningMode.IMAGE) val options = optionsBuilder.build() poseLandmarker = poseLandmarker.createFromOptions(context, options)
Wideo
val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(modelName) val baseOptions = baseOptionBuilder.build() val optionsBuilder = poseLandmarker.poseLandmarkerOptions.builder() .setBaseOptions(baseOptionsBuilder.build()) .setMinPoseDetectionConfidence(minPoseDetectionConfidence) .setMinTrackingConfidence(minPoseTrackingConfidence) .setMinPosePresenceConfidence(minposePresenceConfidence) .setNumPoses(maxNumPoses) .setRunningMode(RunningMode.VIDEO) val options = optionsBuilder.build() poseLandmarker = poseLandmarker.createFromOptions(context, options)
Transmisja na żywo
val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(modelName) val baseOptions = baseOptionBuilder.build() val optionsBuilder = poseLandmarker.poseLandmarkerOptions.builder() .setBaseOptions(baseOptionsBuilder.build()) .setMinPoseDetectionConfidence(minPoseDetectionConfidence) .setMinTrackingConfidence(minPoseTrackingConfidence) .setMinPosePresenceConfidence(minposePresenceConfidence) .setNumPoses(maxNumPoses) .setResultListener(this::returnLivestreamResult) .setErrorListener(this::returnLivestreamError) .setRunningMode(RunningMode.LIVE_STREAM) val options = optionsBuilder.build() poseLandmarker = poseLandmarker.createFromOptions(context, options)
Implementacja przykładowego kodu usługi Pose Landmarker umożliwia użytkownikowi przełączanie się między trybami przetwarzania. Takie podejście skomplikuje kod tworzący zadanie i może nie być odpowiednie w Twoim przypadku. Ten kod znajdziesz w funkcji setupPoseLandmarker()
w pliku PoseLandmarkerHelper.kt
.
Opcje konfiguracji
W tym zadaniu dostępne są te opcje konfiguracji aplikacji na Androida:
Nazwa opcji | Opis | Zakres wartości | Wartość domyślna |
---|---|---|---|
runningMode |
Ustawia tryb działania zadania. Dostępne są 3 tryby: OBRAZ: tryb dla pojedynczych obrazów wejściowych. FILM: tryb dekodowanych klatek filmu. LIVE_STREAM: tryb transmisji na żywo danych wejściowych, takich jak dane z kamery. W tym trybie należy wywołać metodę resultListener, aby skonfigurować odbiornik, który będzie asynchronicznie odbierał wyniki. |
{IMAGE, VIDEO, LIVE_STREAM } |
IMAGE |
numposes |
Maksymalna liczba poz, które może wykryć Landmarker poz. | Integer > 0 |
1 |
minPoseDetectionConfidence |
Minimalna wartość ufności wykrywania pozycji, która jest uznawana za prawidłową. | Float [0.0,1.0] |
0.5 |
minPosePresenceConfidence |
Minimalny wynik ufności obecności pozycji w wykrywaniu punktów orientacyjnych postawy. | Float [0.0,1.0] |
0.5 |
minTrackingConfidence |
Minimalny wynik ufności śledzenia pozycji ciała, aby uznać go za udany. | Float [0.0,1.0] |
0.5 |
outputSegmentationMasks |
Określa, czy narzędzie Pose Landmarker wygeneruje maskę segmentacji dla wykrytej postawy. | Boolean |
False |
resultListener |
Ustawia odbiornik wyników tak, aby asynchronicznie otrzymywał wyniki wyszukiwania punktów orientacyjnych, gdy punkt orientacyjny w ramach funkcji Pose Landmarker jest w trybie transmisji na żywo.
Można go używać tylko wtedy, gdy tryb działania ma wartość LIVE_STREAM . |
ResultListener |
N/A |
errorListener |
Ustawia opcjonalny odbiornik błędów. | ErrorListener |
N/A |
Przygotuj dane
Pose Landmarker działa z obrazami, plikami wideo i transmisjami wideo na żywo. Zadanie to obsługuje wstępną obróbkę danych wejściowych, w tym zmianę rozmiaru, obrót i normalizację wartości.
Poniższy kod pokazuje, jak przekazywać dane do przetwarzania. Te przykłady zawierają szczegółowe informacje o obsługiwaniu danych z obrazów, plików wideo i transmisji na żywo.
Obraz
import com.google.mediapipe.framework.image.BitmapImageBuilder import com.google.mediapipe.framework.image.MPImage // Convert the input Bitmap object to an MPImage object to run inference val mpImage = BitmapImageBuilder(image).build()
Wideo
import com.google.mediapipe.framework.image.BitmapImageBuilder import com.google.mediapipe.framework.image.MPImage val argb8888Frame = if (frame.config == Bitmap.Config.ARGB_8888) frame else frame.copy(Bitmap.Config.ARGB_8888, false) // Convert the input Bitmap object to an MPImage object to run inference val mpImage = BitmapImageBuilder(argb8888Frame).build()
Transmisja na żywo
import com.google.mediapipe.framework.image.BitmapImageBuilder import com.google.mediapipe.framework.image.MPImage // Convert the input Bitmap object to an MPImage object to run inference val mpImage = BitmapImageBuilder(rotatedBitmap).build()
W przykładowym kodzie usługi Pose Landmarker przygotowanie danych jest obsługiwane w pliku PoseLandmarkerHelper.kt
.
Uruchamianie zadania
W zależności od typu danych, z którymi pracujesz, użyj metody poseLandmarker.detect...()
odpowiedniej dla tego typu danych. Użyj wartości detect()
dla pojedynczych obrazów, detectForVideo()
dla klatek w plikach wideo oraz detectAsync()
dla strumieni wideo. Podczas wykrywania treści w strumieniu wideo pamiętaj, aby uruchamiać wykrywanie na osobnym wątku, aby nie blokować wątku interpolacji użytkownika.
Poniższe przykłady kodu pokazują proste przykłady uruchamiania usługi Pose Landmarker w różnych trybach danych:
Obraz
val result = poseLandmarker.detect(mpImage)
Wideo
val timestampMs = i * inferenceIntervalMs poseLandmarker.detectForVideo(mpImage, timestampMs) .let { detectionResult -> resultList.add(detectionResult) }
Transmisja na żywo
val mpImage = BitmapImageBuilder(rotatedBitmap).build() val frameTime = SystemClock.uptimeMillis() poseLandmarker.detectAsync(mpImage, frameTime)
Pamiętaj:
- W trybie wideo lub trybie transmisji na żywo zadanie wyodrębniania punktów orientacyjnych w pozie musi zawierać sygnaturę czasową ramki wejściowej.
- W trybie obrazu lub filmu zadanie wyszukiwania punktów orientacyjnych w pozie blokuje bieżący wątek, dopóki nie zakończy przetwarzania obrazu wejściowego lub klatki. Aby uniknąć blokowania interfejsu użytkownika, przeprowadź przetwarzanie w procesie w tle.
- W trybie transmisji na żywo zadanie dotyczące wyznaczenia punktów orientacyjnych pozycji powraca natychmiast i nie blokuje bieżącego wątku. Za każdym razem, gdy skończy przetwarzać daną klatkę wejściową, wywoła komponent odbiorczy z wynikiem wykrywania.
W przykładowym kodzie funkcji do wyznaczania punktów orientacyjnych w położeniu funkcje detect
, detectForVideo
i detectAsync
są zdefiniowane w pliku PoseLandmarkerHelper.kt
.
Obsługa i wyświetlanie wyników
Funkcja Pose Landmarker zwraca obiekt poseLandmarkerResult
dla każdego przebiegu wykrywania. Obiekt wyniku zawiera współrzędne każdego punktu orientacyjnego pozy.
Poniżej znajdziesz przykład danych wyjściowych z tego zadania:
PoseLandmarkerResult:
Landmarks:
Landmark #0:
x : 0.638852
y : 0.671197
z : 0.129959
visibility : 0.9999997615814209
presence : 0.9999984502792358
Landmark #1:
x : 0.634599
y : 0.536441
z : -0.06984
visibility : 0.999909
presence : 0.999958
... (33 landmarks per pose)
WorldLandmarks:
Landmark #0:
x : 0.067485
y : 0.031084
z : 0.055223
visibility : 0.9999997615814209
presence : 0.9999984502792358
Landmark #1:
x : 0.063209
y : -0.00382
z : 0.020920
visibility : 0.999976
presence : 0.999998
... (33 world landmarks per pose)
SegmentationMasks:
... (pictured below)
Dane wyjściowe zawierają zarówno znormalizowane współrzędne (Landmarks
), jak i współrzędne globalne (WorldLandmarks
) dla każdego punktu orientacyjnego.
Dane wyjściowe zawierają te sformatowane współrzędne (Landmarks
):
x
iy
: współrzędne punktu orientacyjnego znormalizowane w zakresie od 0,0 do 1,0 przez szerokość (x
) i wysokość (y
) obrazu.z
: głębokość punktu orientacyjnego, w której głębokość w środku bioder jest traktowana jako punkt początkowy. Im mniejsza wartość, tym obiekt jest bliżej kamery. Wielkość z używa mniej więcej tej samej skali cox
.visibility
: prawdopodobieństwo, że punkt orientacyjny jest widoczny na zdjęciu.
Dane wyjściowe zawierają te współrzędne świata (WorldLandmarks
):
x
,y
iz
: rzeczywiste współrzędne 3D w metrach, z środkiem bioder jako punktem początkowym.visibility
: prawdopodobieństwo, że punkt orientacyjny jest widoczny na zdjęciu.
Na ilustracji poniżej widać wynik wykonania zadania:
Opcjonalna maska podziału na segmenty reprezentuje prawdopodobieństwo, że dany piksel należy do wykrytej osoby. Następujący obraz przedstawia maskę podziału na segmenty danych wyjściowych zadania:
Przykładowy kod usługi do wyznaczania punktów orientacyjnych na podstawie pozy demonstruje, jak wyświetlać wyniki zwrócone przez zadanie. Więcej informacji znajdziesz w klasie OverlayView
.