Przewodnik wykrywania punktów orientacyjnych twarzy na Androidzie

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:

  1. Sklonuj repozytorium Git za pomocą tego polecenia:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. 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, detectForVideodetectAsync 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:

Mężczyzna z geometrycznie wyznaczonymi obszarami twarzy, które wskazują jej kształt i wymiary

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