Przewodnik wykrywania punktów orientacyjnych twarzy na Androidzie

Zadanie MediaPipe Face Landmarker umożliwia wykrywanie punktów orientacyjnych twarzy i wyrazów twarzy na zdjęciach i w filmach. Za pomocą tego zadania możesz rozpoznawać ludzkie mimiki, stosować filtry i efekty twarzy oraz tworzyć wirtualnych awatarów. To zadanie korzysta z modeli uczenia maszynowego, które mogą działać z pojedynczymi obrazami lub ciągłym strumieniem obrazów. Zadanie to generuje 3D-wymiarowe punkty orientacyjne twarzy, wartości blendshape (współczynniki reprezentujące mimikę twarzy), aby w czasie rzeczywistym wywnioskować szczegółowe powierzchnie twarzy, oraz macierze przekształceń, aby wykonać przekształcenia wymagane 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 związanych z tym zadaniem znajdziesz w sekcji Omówienie.

Przykładowy kod

Przykładowy kod MediaPipe Tasks to prosta implementacja aplikacji Face Landmarker na Androida. W tym przykładzie do wykrywania twarzy w ciągłym strumieniu wideo użyto kamery na fizycznym urządzeniu z Androidem. 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 stworzenia własnej aplikacji na Androida lub skorzystać z niej podczas modyfikowania istniejącej aplikacji. Przykładowy kod usługi Face 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:

  1. Sklonuj repozytorium Git za pomocą tego polecenia:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. Opcjonalnie skonfiguruj instancję git, aby używać rzadkiego sprawdzania, dzięki czemu będziesz mieć tylko pliki przykładowej aplikacji Face Landmarker:
    cd mediapipe
    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 Android Studio i uruchomić aplikację. Instrukcje znajdziesz w przewodniku konfiguracji Androida.

Kluczowe komponenty

Te pliki zawierają kluczowy kod przykładowej aplikacji do wykrywania punktów charakterystycznych twarzy:

  • FaceLandmarkerHelper.kt – inicjuje punkty orientacyjne twarzy 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 siatki twarzy dla wykrytych twarzy.

Konfiguracja

W tej sekcji opisaliśmy kluczowe kroki konfigurowania środowiska programistycznego i projektów kodu w celu używania narzędzia 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 polegające na wykrywaniu punktów orientacyjnych twarzy 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 pakietu wytrenowanych modeli zgodnego z tym zadaniem. Więcej informacji o dostępnych wytrenowanych modelach usługi Face 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 FaceLandmarkerHelper.kt:

baseOptionsBuilder.setModelAssetPath(MP_FACE_LANDMARKER_TASK)

Tworzenie zadania

Zadanie MediaPipe Face Landmarker używa funkcji createFromOptions() do konfigurowania zadania. Funkcja createFromOptions() akceptuje wartości opcji konfiguracji. Więcej informacji o opcjach konfiguracji znajdziesz w artykule Opcje konfiguracji.

Narzędzie Face 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. Wybierz kartę odpowiadającą typowi 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)
    

Implementacja przykładowego kodu usługi Face 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 setupFaceLandmarker() w pliku FaceLandmarkerHelper.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
numFaces Maksymalna liczba twarzy, którą może wykryć FaceLandmarker. Wygładzanie jest stosowane tylko wtedy, gdy parametr num_faces ma wartość 1. Integer > 0 1
minFaceDetectionConfidence Minimalny wynik ufności dla wykrywania twarzy, aby uznać go za udany. Float [0.0,1.0] 0.5
minFacePresenceConfidence Minimalny wynik ufności wykrywania obecności twarzy w detekcji punktów orientacyjnych twarzy. Float [0.0,1.0] 0.5
minTrackingConfidence Minimalny wynik ufności śledzenia twarzy, aby uznać go za udany. Float [0.0,1.0] 0.5
outputFaceBlendshapes Określa, czy narzędzie Face Landmarker ma generować blendshape’y twarzy. Blendshape’y twarzy są używane do renderowania modelu 3D twarzy. Boolean False
outputFacialTransformationMatrixes Określa, czy FaceLandmarker ma zwrócić macierz przekształceń twarzy. Funkcja FaceLandmarker korzysta z macierzy, aby przekształcać punkty orientacyjne twarzy z kanonicznego modelu twarzy na wykrywaną twarz, dzięki czemu użytkownicy mogą stosować efekty na wykrytych punktach orientacyjnych. Boolean False
resultListener Ustawia odbiornik wyników tak, aby asynchronicznie otrzymywał wyniki wyszukiwania punktów orientacyjnych, gdy usługa FaceLandmarker 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

Narzędzie Face Landmarker działa z obrazami, plikami wideo i transmisjami 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 Face Landmarker przygotowanie danych jest obsługiwane w pliku FaceLandmarkerHelper.kt.

Uruchamianie zadania

W zależności od typu danych, z którymi pracujesz, użyj metody FaceLandmarker.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 strumieniach wideo należy uruchamiać wykrywanie na osobnym wątku, aby nie blokować wątku interfejsu użytkownika.

Poniższe przykłady kodu pokazują proste przykłady uruchamiania usługi Face Landmarker w 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:

  • W trybie wideo lub trybie transmisji na żywo zadanie wyodrębniania punktów orientacyjnych twarzy musi zawierać sygnaturę czasową ramki wejściowej.
  • W trybie obrazu lub filmu zadanie wykrywania punktów orientacyjnych twarzy blokuje bieżący wątek, dopóki nie przetworzy wstępnego obrazu lub ramki. Aby uniknąć blokowania interfejsu użytkownika, przetwarzanie należy wykonać w tle.
  • W trybie transmisji na żywo zadanie wykrywania punktów orientacyjnych twarzy zwraca dane 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 Face Landmarker funkcje detect, detectForVideodetectAsync są zdefiniowane w pliku FaceLandmarkerHelper.kt.

Obsługa i wyświetlanie wyników

Funkcja Face Landmarker zwraca obiekt FaceLandmarkerResult dla każdego przebiegu wykrywania. Obiekt result zawiera siatkę twarzy dla każdej wykrytej twarzy wraz z współrzędnymi każdego punktu odniesienia twarzy. Opcjonalnie obiekt wyniku może też zawierać blendshape’y, które oznaczają mimikę twarzy, oraz macierze transformacji twarzy, aby stosować efekty twarzy na wykrytych punktach orientacyjnych.

Poniżej znajdziesz przykład danych wyjściowych z 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]
    ...

Na ilustracji poniżej widać wynik wykonania zadania:

Mężczyzna z geometrią twarzy, która wskazuje jej kształt i wymiary

Przykładowy kod usługi Face Landmarker pokazuje, jak wyświetlać wyniki zwrócone przez zadanie. Więcej informacji znajdziesz w klasie OverlayView.