Zadanie MediaPipe Face Landmarker umożliwia wykrywanie punktów charakterystycznych twarzy i mimiki na obrazach i w filmach. Możesz używać tego interfejsu do rozpoznawania ludzkich wyrazów twarzy, stosowania filtrów i efektów do twarzy oraz tworzenia wirtualnych awatarów. To zadanie korzysta z modeli uczenia maszynowego, które mogą przetwarzać pojedyncze obrazy lub ciągły strumień obrazów. Zadanie zwraca trójwymiarowe punkty charakterystyczne twarzy, wyniki blendshape (współczynniki reprezentujące mimikę) do wnioskowania o szczegółowych powierzchniach twarzy w czasie rzeczywistym oraz macierze przekształceń do wykonywania przekształceń wymaganych do renderowania efektów.
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 tym artykule.
Przykładowy kod
Przykładowy kod MediaPipe Tasks to proste wdrożenie aplikacji Face Landmarker na Androida. W przykładzie używamy aparatu na fizycznym urządzeniu z Androidem do wykrywania twarzy w ciągłym strumieniu wideo. Aplikacja może też wykrywać twarze na zdjęciach i filmach z galerii urządzenia.
Możesz użyć tej aplikacji jako punktu wyjścia do utworzenia własnej aplikacji na Androida lub skorzystać z niej podczas modyfikowania istniejącej aplikacji. Przykładowy kod Face Landmarker jest hostowany w GitHub.
Pobieranie kodu
Z poniższych 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 możesz skonfigurować instancję Git, aby używać rzadkiego wyewidencjonowania. Dzięki temu będziesz mieć tylko pliki przykładowej aplikacji Face Landmarker:
cd mediapipe-samples git sparse-checkout init --cone git sparse-checkout set examples/face_landmarker/android
Po utworzeniu lokalnej wersji przykładowego kodu możesz zaimportować projekt do Androida Studio i uruchomić aplikację. Instrukcje znajdziesz w przewodniku po konfiguracji na Androida.
Kluczowe komponenty
Te pliki zawierają kluczowy kod dla tej przykładowej aplikacji do wyznaczania punktów charakterystycznych twarzy:
- FaceLandmarkerHelper.kt – inicjuje narzędzie do wykrywania punktów charakterystycznych twarzy i obsługuje wybór modelu oraz delegata.
- CameraFragment.kt – obsługuje aparat urządzenia i przetwarza dane wejściowe obrazu i wideo.
- GalleryFragment.kt – wchodzi w interakcję z
OverlayView, aby wyświetlić wyjściowe zdjęcie lub film. - OverlayView.kt – implementuje wyświetlanie siatki twarzy dla wykrytych twarzy.
Konfiguracja
W tej sekcji opisujemy najważniejsze kroki konfigurowania środowiska programistycznego i projektów kodu pod kątem korzystania z funkcji Face 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 Face Landmarker 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 Face Landmarker wymaga wytrenowanego pakietu modelu, który jest z nim zgodny. Więcej informacji o dostępnych wytrenowanych modelach do wykrywania punktów charakterystycznych twarzy znajdziesz w sekcji Modele w omówieniu zadania.
Wybierz i pobierz model, a następnie zapisz go w katalogu projektu:
<dev-project-root>/src/main/assets
Określ ścieżkę modelu w parametrze ModelAssetPath. W przykładowym kodzie model jest zdefiniowany w pliku FaceLandmarkerHelper.kt:
baseOptionsBuilder.setModelAssetPath(MP_FACE_LANDMARKER_TASK)
Tworzenie zadania
Zadanie MediaPipe Face Landmarker używa funkcji createFromOptions() do skonfigurowania zadania. Funkcja createFromOptions() akceptuje wartości opcji konfiguracji. Więcej informacji o opcjach konfiguracji znajdziesz w artykule Opcje konfiguracji.
Model Face Landmarker obsługuje te typy danych wejściowych: obrazy statyczne, pliki wideo i strumienie wideo na żywo. Podczas tworzenia zadania musisz określić tryb działania odpowiadający typowi danych wejściowych. Wybierz kartę z typem danych wejściowych, aby dowiedzieć się, jak utworzyć zadanie i przeprowadzić wnioskowanie.
Obraz
val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_FACE_LANDMARKER_TASK)
val baseOptions = baseOptionBuilder.build()
val optionsBuilder =
FaceLandmarker.FaceLandmarkerOptions.builder()
.setBaseOptions(baseOptionsBuilder.build())
.setMinFaceDetectionConfidence(minFaceDetectionConfidence)
.setMinTrackingConfidence(minFaceTrackingConfidence)
.setMinFacePresenceConfidence(minFacePresenceConfidence)
.setNumFaces(maxNumFaces)
.setRunningMode(RunningMode.IMAGE)
val options = optionsBuilder.build()
FaceLandmarker = FaceLandmarker.createFromOptions(context, options)
Wideo
val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_FACE_LANDMARKER_TASK)
val baseOptions = baseOptionBuilder.build()
val optionsBuilder =
FaceLandmarker.FaceLandmarkerOptions.builder()
.setBaseOptions(baseOptionsBuilder.build())
.setMinFaceDetectionConfidence(minFaceDetectionConfidence)
.setMinTrackingConfidence(minFaceTrackingConfidence)
.setMinFacePresenceConfidence(minFacePresenceConfidence)
.setNumFaces(maxNumFaces)
.setRunningMode(RunningMode.VIDEO)
val options = optionsBuilder.build()
FaceLandmarker = FaceLandmarker.createFromOptions(context, options)
Transmisja na żywo
val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_FACE_LANDMARKER_TASK)
val baseOptions = baseOptionBuilder.build()
val optionsBuilder =
FaceLandmarker.FaceLandmarkerOptions.builder()
.setBaseOptions(baseOptionsBuilder.build())
.setMinFaceDetectionConfidence(minFaceDetectionConfidence)
.setMinTrackingConfidence(minFaceTrackingConfidence)
.setMinFacePresenceConfidence(minFacePresenceConfidence)
.setNumFaces(maxNumFaces)
.setResultListener(this::returnLivestreamResult)
.setErrorListener(this::returnLivestreamError)
.setRunningMode(RunningMode.LIVE_STREAM)
val options = optionsBuilder.build()
FaceLandmarker = FaceLandmarker.createFromOptions(context, options)
Przykładowy kod wykrywania punktów charakterystycznych twarzy umożliwia użytkownikowi przełączanie się między trybami przetwarzania. Takie podejście sprawia, że kod tworzenia zadań jest bardziej skomplikowany i może nie być odpowiedni w Twoim przypadku. Ten kod znajdziesz w funkcji setupFaceLandmarker() w pliku FaceLandmarkerHelper.kt.
Opcje konfiguracji
To zadanie ma te opcje konfiguracji w przypadku 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. WIDEO: tryb dla zdekodowanych klatek filmu. LIVE_STREAM: tryb transmisji na żywo danych wejściowych, np. z kamery. W tym trybie należy wywołać funkcję resultListener, aby skonfigurować odbiornik do asynchronicznego odbierania wyników. |
{IMAGE, VIDEO, LIVE_STREAM} |
IMAGE |
numFaces |
Maksymalna liczba twarzy, które mogą być wykrywane przez FaceLandmarker. Wygładzanie jest stosowane tylko wtedy, gdy wartość parametru num_faces wynosi 1.
|
Integer > 0 |
1 |
minFaceDetectionConfidence |
Minimalny poziom ufności, przy którym wykrywanie twarzy jest uznawane za udane. | Float [0.0,1.0] |
0.5 |
minFacePresenceConfidence |
Minimalny poziom ufności wykrycia twarzy. | Float [0.0,1.0] |
0.5 |
minTrackingConfidence |
Minimalny poziom ufności, przy którym śledzenie twarzy jest uznawane za udane. | Float [0.0,1.0] |
0.5 |
outputFaceBlendshapes |
Określa, czy funkcja Face Landmarker ma zwracać kształty twarzy. Kształty twarzy są używane do renderowania modelu twarzy 3D. | Boolean |
False |
outputFacialTransformationMatrixes |
Określa, czy FaceLandmarker ma zwracać macierz przekształceń twarzy. FaceLandmarker używa macierzy do przekształcania punktów orientacyjnych twarzy z kanonicznego modelu twarzy na wykrytą twarz, dzięki czemu użytkownicy mogą stosować efekty do wykrytych punktów orientacyjnych. | Boolean |
False |
resultListener |
Ustawia odbiornik wyników, aby asynchronicznie odbierać wyniki wykrywania punktów charakterystycznych, gdy wykrywacz punktów charakterystycznych twarzy 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
Model Face Landmarker działa w przypadku obrazów, plików wideo i transmisji wideo na żywo. Zadanie obsługuje wstępne przetwarzanie danych wejściowych, w tym zmianę rozmiaru, obracanie i normalizację wartości.
Poniższy kod pokazuje, jak przekazać dane do przetworzenia. Te przykłady zawierają szczegółowe informacje o tym, jak przetwarzać dane z obrazów, plików wideo i transmisji 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 Face Landmarker przygotowanie danych odbywa się w pliku
FaceLandmarkerHelper.kt.
Uruchamianie zadania
W zależności od typu danych, z którymi pracujesz, użyj metody FaceLandmarker.detect...(), która jest odpowiednia dla tego typu danych. Używaj symbolu detect() w przypadku pojedynczych obrazów, symbolu detectForVideo() w przypadku klatek w plikach wideo i symbolu detectAsync() w przypadku strumieni wideo. Podczas wykrywania w strumieniu wideo pamiętaj, aby uruchamiać wykrywanie w osobnym wątku, aby uniknąć blokowania wątku interfejsu użytkownika.
Poniższe przykłady kodu pokazują proste przykłady uruchamiania narzędzia Face Landmarker w tych różnych trybach danych:
Obraz
val result = FaceLandmarker.detect(mpImage)
Wideo
val timestampMs = i * inferenceIntervalMs FaceLandmarker.detectForVideo(mpImage, timestampMs) .let { detectionResult -> resultList.add(detectionResult) }
Transmisja na żywo
val mpImage = BitmapImageBuilder(rotatedBitmap).build()
val frameTime = SystemClock.uptimeMillis()
FaceLandmarker.detectAsync(mpImage, frameTime)
Pamiętaj:
- Podczas działania w trybie wideo lub transmisji na żywo musisz podać sygnaturę czasową ramki wejściowej do zadania Face Landmarker.
- Podczas działania w trybie obrazu lub wideo zadanie Face Landmarker blokuje bieżący wątek do momentu zakończenia przetwarzania obrazu wejściowego lub klatki. Aby uniknąć blokowania interfejsu użytkownika, wykonaj przetwarzanie w wątku w tle.
- W trybie transmisji na żywo zadanie Face Landmarker zwraca wynik natychmiast i nie blokuje bieżącego wątku. Za każdym razem, gdy zakończy przetwarzanie klatki wejściowej, wywoła odbiornik wyniku z wynikiem wykrywania.
W przykładzie kodu Face Landmarker funkcje detect, detectForVideo i detectAsync są zdefiniowane w pliku FaceLandmarkerHelper.kt.
Obsługa i wyświetlanie wyników
Detektor punktów charakterystycznych twarzy zwraca obiekt FaceLandmarkerResult dla każdego wykrycia. Obiekt wyniku zawiera siatkę twarzy dla każdej wykrytej twarzy, z współrzędnymi każdego punktu charakterystycznego twarzy. Opcjonalnie obiekt wyniku może też zawierać kształty mieszane, które oznaczają mimikę twarzy, oraz macierze transformacji twarzy, które umożliwiają stosowanie efektów twarzy do wykrytych punktów orientacyjnych.
Poniżej znajdziesz przykład danych wyjściowych tego zadania:
FaceLandmarkerResult:
face_landmarks:
NormalizedLandmark #0:
x: 0.5971359014511108
y: 0.485361784696579
z: -0.038440968841314316
NormalizedLandmark #1:
x: 0.3302789330482483
y: 0.29289937019348145
z: -0.09489090740680695
... (478 landmarks for each face)
face_blendshapes:
browDownLeft: 0.8296722769737244
browDownRight: 0.8096957206726074
browInnerUp: 0.00035583582939580083
browOuterUpLeft: 0.00035752105759456754
... (52 blendshapes for each face)
facial_transformation_matrixes:
[9.99158978e-01, -1.23036895e-02, 3.91213447e-02, -3.70770246e-01]
[1.66496094e-02, 9.93480563e-01, -1.12779640e-01, 2.27719707e+01]
...
Obraz poniżej przedstawia wizualizację danych wyjściowych zadania:
Przykładowy kod Face Landmarker pokazuje, jak wyświetlać wyniki zwracane przez zadanie. Więcej informacji znajdziesz w klasie OverlayView.