Zadanie MediaPipe Pose pointer umożliwia wykrywanie na zdjęciach lub filmach punktów orientacyjnych ludzkich ciał. Możesz używać tego zadania do identyfikowania kluczowych lokalizacji ciała, analizowania postawy i kategoryzowania ruchów. To zadanie wykorzystuje modele systemów uczących się, które działają z pojedynczymi obrazami lub filmami. Zadanie wyprowadza punkty orientacyjne ustalania pozycji ciała we współrzędnych zdjęcia 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 tego zadania znajdziesz w sekcji Omówienie.
Przykładowy kod
Przykładowy kod MediaPipe Tasks to prosta implementacja aplikacji Pose Kraina na Androida. W tym przykładzie używamy aparatu na fizycznym urządzeniu z Androidem, aby wykrywać pozycje w ciągłym strumieniu wideo. Może też wykrywać pozy na zdjęciach i filmach z galerii urządzenia.
Możesz użyć aplikacji jako punktu wyjścia dla własnej aplikacji na Androida lub odwołać się do niej podczas modyfikowania istniejącej aplikacji. Przykładowy kod Pose pointer jest hostowany na GitHub.
Pobieranie kodu
Z instrukcji poniżej 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 tak, aby używała rozproszonego procesu płatności, aby mieć tylko pliki dla przykładowej aplikacji Pose pointer:
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 na Androida.
Kluczowe elementy
Te pliki zawierają kluczowy kod tej przykładowej aplikacji z elementami charakterystycznymi dla pozy:
- PoseLandmarkerHelper.kt – inicjuje punkt orientacyjny pozycji i obsługuje model oraz wybór przedstawicieli.
- CameraFragment.kt – obsługuje aparat urządzenia oraz przetwarza wejściowe dane obrazu i filmu.
- GalleryFragment.kt – wchodzi w interakcję z elementem
OverlayView
, by wyświetlić obraz lub film wyjściowy. - OverlayView.kt – implementuje ekran w przypadku wykrytych pozycji.
Konfiguracja
W tej sekcji opisujemy najważniejsze czynności, jakie należy wykonać podczas konfigurowania środowiska programistycznego i projektów kodowania, tak aby można było używać aplikacji Pose pointer. Ogólne informacje o konfigurowaniu środowiska programistycznego na potrzeby zadań MediaPipe, w tym o wymaganiach dotyczących wersji platformy, znajdziesz w przewodniku konfiguracji na Androida.
Zależności
Zadanie Tworzenie punktu orientacyjnego 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 pointer wymaga wytrenowanego pakietu modeli, który jest z nim zgodny. Więcej informacji o dostępnych wytrenowanych modelach dla funkcji Punkt orientacyjny pozycji znajdziesz w opisie zadania w sekcji „Modele”.
Wybierz i pobierz model, a następnie zapisz go w katalogu projektu:
<dev-project-root>/src/main/assets
Podaj ścieżkę modelu w parametrze ModelAssetPath
. W przykładowym kodzie model jest zdefiniowany w pliku PoseLandmarkerHelper.kt
:
val modelName = "pose_landmarker_lite.task"
baseOptionsBuilder.setModelAssetPath(modelName)
Tworzenie zadania
Zadanie MediaPipe Pose w sam raz do skonfigurowania tego zadania używa funkcji createFromOptions()
. Funkcja createFromOptions()
akceptuje wartości opcji konfiguracji. Więcej informacji o opcjach konfiguracji znajdziesz w artykule Opcje konfiguracji.
Narzędzie do oznaczania pozycji obsługuje następujące typy danych wejściowych: obrazy, pliki wideo i strumienie wideo na żywo. Podczas tworzenia zadania musisz określić tryb działania odpowiadającym typowi danych wejściowych. Wybierz kartę z typem danych wejściowych, aby zobaczyć, jak utworzyć zadanie.
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 kodu przykładowej Pose Kraina umożliwia użytkownikowi przełączanie się między trybami przetwarzania. Takie podejście zwiększa złożoność kodu tworzenia zadania i może nie być odpowiednie w Twoim przypadku. Ten kod znajdziesz w funkcji setupPoseLandmarker()
w pliku PoseLandmarkerHelper.kt
.
Opcje konfiguracji
To zadanie ma te opcje konfiguracji aplikacji na Androida:
Nazwa opcji | Opis | Zakres wartości | Wartość domyślna |
---|---|---|---|
runningMode |
Ustawia tryb działania zadania. Są 3 tryby: IMAGE: tryb wprowadzania pojedynczych obrazów. WIDEO: tryb dekodowanych klatek filmu. TRANSMISJA NA ŻYWO: tryb transmisji danych wejściowych na żywo, np. z kamery. W tym trybie należy wywołać metodę resultListener, aby skonfigurować odbiornik, który będzie odbierał wyniki asynchronicznie. |
{IMAGE, VIDEO, LIVE_STREAM } |
IMAGE |
numposes |
Maksymalna liczba pozycji, które może wykryć Punkt orientacyjny pozycji. | Integer > 0 |
1 |
minPoseDetectionConfidence |
Minimalny poziom ufności, że wykrywanie pozycji zostanie uznane za udane. | Float [0.0,1.0] |
0.5 |
minPosePresenceConfidence |
Minimalny wskaźnik ufności dotyczący obecności pozycji podczas wykrywania punktu orientacyjnego pozycji. | Float [0.0,1.0] |
0.5 |
minTrackingConfidence |
Minimalny wskaźnik ufności pozwalający na uznanie śledzenia pozycji za udane. | Float [0.0,1.0] |
0.5 |
outputSegmentationMasks |
Określa, czy Kreator elementów budowy pozycji generuje maskę podziału na segmenty dla wykrytej pozycji. | Boolean |
False |
resultListener |
Ustawia detektor wyników tak, aby asynchronicznie otrzymywał wyniki dotyczące punktów orientacyjnych, gdy kreator pozycji jest w trybie transmisji na żywo.
Tego ustawienia można używać tylko wtedy, gdy tryb biegowy jest ustawiony na LIVE_STREAM |
ResultListener |
N/A |
errorListener |
Ustawia opcjonalny detektor błędów. | ErrorListener |
N/A |
Przygotuj dane
Narzędzie do oznaczania pozycji obsługuje obrazy, pliki wideo i transmisje wideo na żywo. To zadanie obsługuje wstępne przetwarzanie danych wejściowych, w tym zmianę rozmiaru, rotację i normalizację wartości.
Poniższy kod pokazuje, jak przekazywać dane do przetwarzania. Obejmują one szczegółowe informacje na temat postępowania z danymi z obrazów, plików wideo i strumieni wideo 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 Pose pointer przygotowanie danych odbywa się 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 detect()
w przypadku pojedynczych obrazów, detectForVideo()
– klatek w plikach wideo, a detectAsync()
w przypadku strumieni wideo. Gdy wykrywasz treści w strumieniu wideo, pamiętaj o uruchomieniu wykrywania w osobnym wątku, aby uniknąć zablokowania takiego wątku.
Poniższe przykłady kodu pokazują proste przykłady uruchamiania punktu orientacyjnego Pose 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)
Uwaga:
- Gdy korzystasz z trybu wideo lub transmisji na żywo, musisz w zadaniu „punkt orientacyjny pozycji” podać sygnaturę czasową klatki wejściowej.
- W trybie graficznym lub wideo zadanie Punkt orientacyjny do pozycjonowania blokuje bieżący wątek do momentu zakończenia przetwarzania obrazu lub klatki wejściowej. Aby uniknąć blokowania interwencji użytkownika, przetwarzaj dane w wątku w tle.
- W trybie transmisji na żywo zadanie Punkt orientacyjny pozycji wraca natychmiast i nie blokuje bieżącego wątku. Wywoła on detektor wyników z wynikiem wykrywania za każdym razem, gdy zakończy przetwarzanie ramki wejściowej.
W przykładowym kodzie Pose Symbol Oznacz funkcje detect
, detectForVideo
i detectAsync
są zdefiniowane w pliku PoseLandmarkerHelper.kt
.
Obsługa i wyświetlanie wyników
Punkt orientacyjny pozycji zwraca obiekt poseLandmarkerResult
przy każdym uruchomieniu wykrywania. Wynikowy obiekt zawiera współrzędne każdego punktu orientacyjnego umiejscowienia.
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)
Dla każdego punktu orientacyjnego dane wyjściowe zawierają zarówno znormalizowane współrzędne (Landmarks
), jak i współrzędne świata (WorldLandmarks
).
Dane wyjściowe zawierają te znormalizowane współrzędne (Landmarks
):
x
iy
: współrzędne punktu orientacyjnego znormalizowane od 0,0 do 1,0 według szerokości obrazu (x
) i wysokości (y
).z
: głębokość punktu orientacyjnego, której początek znajduje się w połowie bioder. Im mniejsza wartość, tym bliżej kamery znajduje się punkt orientacyjny. Wielkość „z” jest mniej więcej taka sama jak w przypadku właściwościx
.visibility
: prawdopodobieństwo, że punkt orientacyjny będzie widoczny na zdjęciu.
Dane wyjściowe zawierają te współrzędne świata (WorldLandmarks
):
x
,y
iz
: rzeczywiste trójwymiarowe współrzędne w metrach, gdzie punktem początkowym jest środek bioder.visibility
: prawdopodobieństwo, że punkt orientacyjny będzie widoczny na zdjęciu.
Poniższy obraz przedstawia wizualizację wyników zadania:
Opcjonalna maska podziału na segmenty reprezentuje prawdopodobieństwo, że każdy piksel należy do wykrytej osoby. Ten obraz przedstawia maskę podziału danych wyjściowych zadania:
Przykładowy kod Znacznika elementu położenia pokazuje, jak wyświetlać wyniki zwrócone z zadania. Więcej informacji znajdziesz w klasie OverlayView
.