Zadanie MediaPipe Face Detector umożliwia wykrywanie twarzy na obrazie lub w filmie. Za pomocą tego zadania możesz zlokalizować twarze i cechy twarzy w ramce. W tym zadaniu używamy modelu uczenia maszynowego, który działa z pojedynczymi obrazami lub ciągłym strumieniem obrazów. Zadanie zwraca położenie twarzy oraz następujące punkty kluczowe twarzy: lewe oko, prawe oko, czubek nosa, usta, lewy kąt oka i prawy kąt oka.
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 wykrywającej twarz 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 utworzenia własnej aplikacji na Androida lub skorzystać z niej podczas modyfikowania istniejącej aplikacji. Przykładowy kod usługi Face Detector 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 korzystania z funkcji Sparse Checkout, aby mieć tylko pliki przykładowej aplikacji Face Detector:
cd mediapipe git sparse-checkout init --cone git sparse-checkout set examples/face_detector/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 tej przykładowej aplikacji do wykrywania twarzy:
- FaceDetectorHelper.kt – inicjuje detektor twarzy i obsługuje model oraz wybór delegata.
- CameraFragment.kt – obsługuje kamerę urządzenia i przetwarza dane wejściowe dotyczące obrazu i wideo.
- GalleryFragment.kt – współpracuje z
OverlayView
, aby wyświetlić obraz lub film wyjściowy. - OverlayView.kt – implementuje wyświetlanie z ramkami dla wykrytych twarzy.
Konfiguracja
W tej sekcji opisaliśmy kluczowe kroki konfigurowania środowiska programistycznego i projektów kodu w celu używania usługi Face Detector. 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 Wykrywanie 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 Detector wymaga pakietu wytrenowanych modeli, który jest zgodny z tym zadaniem. Więcej informacji o dostępnych wytrenowanych modelach usługi Face Detector 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 FaceDetectorHelper.kt
:
val modelName = "face_detection_short_range.tflite"
baseOptionsBuilder.setModelAssetPath(modelName)
Tworzenie zadania
Do konfiguracji zadania MediaPipe Face Detector służy funkcja createFromOptions()
. Funkcja createFromOptions()
akceptuje wartości opcji konfiguracji. Więcej informacji o opcjach konfiguracji znajdziesz w artykule Opcje konfiguracji.
Detektor twarzy obsługuje te typy danych wejściowych: obrazy, pliki wideo i strumienie wideo na żywo. Podczas tworzenia zadania musisz określić tryb działania odpowiadający typowi danych wejściowych. Wybierz kartę odpowiadającą Twojemu typowi danych wejściowych, aby dowiedzieć się, jak utworzyć zadanie i przeprowadzić wnioskowanie.
Obraz
val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(modelName) val baseOptions = baseOptionBuilder.build() val optionsBuilder = FaceDetector.FaceDetectorOptions.builder() .setBaseOptions(baseOptionsBuilder.build()) .setMinDetectionConfidence(threshold) .setRunningMode(RunningMode.IMAGE) val options = optionsBuilder.build() FaceDetector = FaceDetector.createFromOptions(context, options)
Wideo
val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(modelName) val baseOptions = baseOptionBuilder.build() val optionsBuilder = FaceDetector.FaceDetectorOptions.builder() .setBaseOptions(baseOptionsBuilder.build()) .setMinDetectionConfidence(threshold) .setRunningMode(RunningMode.VIDEO) val options = optionsBuilder.build() FaceDetector = FaceDetector.createFromOptions(context, options)
Transmisja na żywo
val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(modelName) val baseOptions = baseOptionBuilder.build() val optionsBuilder = FaceDetector.FaceDetectorOptions.builder() .setBaseOptions(baseOptionsBuilder.build()) .setMinDetectionConfidence(threshold) .setResultListener(this::returnLivestreamResult) .setErrorListener(this::returnLivestreamError) .setRunningMode(RunningMode.LIVE_STREAM) val options = optionsBuilder.build() FaceDetector = FaceDetector.createFromOptions(context, options)
Implementacja przykładowego kodu wykrywacza twarzy 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 setupFaceDetector()
w pliku FaceDetectorHelper.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 |
minDetectionConfidence |
Minimalny wynik ufności, który pozwala uznać wykrywanie twarzy za skuteczne. | Float [0,1] |
0.5 |
minSuppressionThreshold |
Minimalny próg wygaszania niemaksymalizowanego wykrywania twarzy, który ma być traktowany jako nakładanie się. | Float [0,1] |
0.3 |
resultListener |
Gdy detektor twarzy jest w trybie transmisji na żywo, ustawia odbiornik wyników tak, aby otrzymywał wyniki asynchronicznie. Można go używać tylko wtedy, gdy tryb działania ma wartość LIVE_STREAM . |
N/A |
Not set |
errorListener |
Ustawia opcjonalny odbiornik błędów. | N/A |
Not set |
Przygotuj dane
Funkcja wykrywacza twarzy działa w przypadku obrazów, plików wideo i transmisji 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 Face Detector przygotowanie danych jest obsługiwane w pliku FaceDetectorHelper.kt
.
Uruchamianie zadania
W zależności od typu danych, z którymi pracujesz, użyj metody faceDetector.detect...()
odpowiedniej dla tego typu danych. Używaj:
detect()
do pojedynczych obrazów,
detectForVideo()
do klatek w plikach wideo, detectAsync()
do 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 Detector w różnych trybach danych:
Obraz
val result = faceDetector.detect(mpImage)
Wideo
val timestampMs = i * inferenceIntervalMs faceDetector.detectForVideo(mpImage, timestampMs) .let { detectionResult -> resultList.add(detectionResult) }
Transmisja na żywo
val mpImage = BitmapImageBuilder(rotatedBitmap).build() val frameTime = SystemClock.uptimeMillis() faceDetector.detectAsync(mpImage, frameTime)
Pamiętaj:
- W trybie wideo lub trybie transmisji na żywo zadanie wykrywacza twarzy musi zawierać sygnaturę czasową ramki wejściowej.
- W trybie obrazu lub filmu zadanie wykrywacza twarzy 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 wątku w tle.
- W trybie transmisji na żywo zadanie wykrywania 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. Jeśli funkcja wykrywania jest wywoływana, gdy zadanie wykrywacza twarzy jest zajęte przetwarzaniem innego kadru, zadanie zignoruje nowy element wejściowy.
W pliku kodu przykładowego wykrywacza twarzy funkcje detect
, detectForVideo
i detectAsync
są zdefiniowane w pliku FaceDetectorHelper.kt
.
Obsługa i wyświetlanie wyników
Detektor twarzy zwraca obiekt FaceDetectorResult
dla każdego przetworzenia wykrywania. Obiekt result zawiera ramki ograniczające wykryte twarze oraz wskaźnik ufności dla każdej z nich.
Poniżej znajdziesz przykład danych wyjściowych z tego zadania:
FaceDetectionResult:
Detections:
Detection #0:
BoundingBox:
origin_x: 126
origin_y: 100
width: 463
height: 463
Categories:
Category #0:
index: 0
score: 0.9729152917861938
NormalizedKeypoints:
NormalizedKeypoint #0:
x: 0.18298381567001343
y: 0.2961040139198303
NormalizedKeypoint #1:
x: 0.3302789330482483
y: 0.29289937019348145
... (6 keypoints for each face)
Detection #1:
BoundingBox:
origin_x: 616
origin_y: 193
width: 430
height: 430
Categories:
Category #0:
index: 0
score: 0.9251380562782288
NormalizedKeypoints:
NormalizedKeypoint #0:
x: 0.6151331663131714
y: 0.3713381886482239
NormalizedKeypoint #1:
x: 0.7460576295852661
y: 0.38825345039367676
... (6 keypoints for each face)
Na ilustracji poniżej widać wynik wykonania zadania:
Obraz bez ramek ograniczających znajdziesz w oryginalnym pliku graficznym.
Przykładowy kod usługi wykrywania twarzy pokazuje, jak wyświetlać wyniki zwrócone przez zadanie. Więcej informacji znajdziesz w klasie OverlayView
.