Zadanie Wykrywacz twarzy MediaPipe umożliwia wykrywanie twarzy na zdjęciu lub filmie. Dzięki temu możesz zlokalizować twarze w kadrze. To zadanie wykorzystuje model systemów uczących się (ML), który działa z pojedynczymi obrazami lub ciągłym strumieniem obrazów. Zadanie określa lokalizacje twarzy i uwzględnia te najważniejsze punkty: lewe i prawe oko, opuszka nosa, usta, tragie dla lewego oka oraz tragie w prawym oku.
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 artykule Omówienie.
Przykładowy kod
Przykładowy kod aplikacji MediaPipe Tasks to prosta implementacja aplikacji do wykrywania twarzy na Androida. W tym przykładzie użyto kamery w 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ć aplikacji jako punktu wyjścia dla własnej aplikacji na Androida lub skorzystać z niej podczas jej modyfikowania. Przykładowy kod wykrywacza twarzy 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 do wykrywania twarzy:
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 na Androida.
Kluczowe elementy
Te pliki zawierają kluczowy kod tej przykładowej aplikacji do wykrywania twarzy:
- FaceDetectorHelper.kt – inicjuje wykrywanie twarzy 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 – w interakcji z interfejsem
OverlayView
wyświetla obraz wyjściowy lub film. - OverlayView.kt – implementuje ekran z ramkami ograniczającymi w przypadku wykrytych twarzy.
Konfiguracja
W tej sekcji opisujemy najważniejsze czynności, jakie należy wykonać, aby skonfigurować środowisko programistyczne i projekty kodu na potrzeby wykrywania twarzy. 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 Wykrywacz 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 wytrenowanego pakietu modeli, który jest z nim zgodny. Więcej informacji o dostępnych wytrenowanych modelach służących do wykrywania twarzy znajdziesz w sekcji poświęconej modelom zadania.
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 FaceDetectorHelper.kt
:
val modelName = "face_detection_short_range.tflite"
baseOptionsBuilder.setModelAssetPath(modelName)
Tworzenie zadania
Wykrywacz twarzy MediaPipe używa funkcji createFromOptions()
do skonfigurowania tego zadania. Funkcja createFromOptions()
akceptuje wartości opcji konfiguracji. Więcej informacji o opcjach konfiguracji znajdziesz w artykule Opcje konfiguracji.
Wykrywacz 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ą typowi danych wejściowych, aby zobaczyć, jak utworzyć zadanie i uruchomić 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)
Przykładowa implementacja kodu do wykrywania twarzy umożliwia użytkownikowi przełączanie trybów 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 setupFaceDetector()
w pliku FaceDetectorHelper.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 |
minDetectionConfidence |
Minimalny stopień pewności, że wykrywanie twarzy zostanie uznane za udane. | Float [0,1] |
0.5 |
minSuppressionThreshold |
Minimalny próg niemaksymalnego ograniczenia wykrywania twarzy, który ma być uznawany za nakładający się. | Float [0,1] |
0.3 |
resultListener |
Powoduje, że detektor wyników będzie asynchronicznie otrzymywać wyniki wykrywania, gdy czytnik twarzy działa w trybie transmisji na żywo. Tej opcji można używać tylko wtedy, gdy tryb biegowy jest ustawiony na LIVE_STREAM . |
N/A |
Not set |
errorListener |
Ustawia opcjonalny detektor błędów. | N/A |
Not set |
Przygotuj dane
Wykrywanie twarzy obsługuje obrazy, pliki wideo i transmisje 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 Wykrywacz twarzy przygotowanie danych odbywa się 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żyj detect()
w przypadku pojedynczych obrazów, detectForVideo()
– klatek w plikach wideo i detectAsync()
w przypadku strumieni wideo. Podczas wykrywania strumienia wideo pamiętaj o uruchamianiu wykrywania w osobnym wątku, aby uniknąć zablokowania wątku interfejsu.
Na tych przykładach kodu widać proste przykłady uruchamiania funkcji wykrywania twarzy 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)
Uwaga:
- Gdy urządzenie działa w trybie wideo lub transmisji na żywo, musisz podać sygnaturę czasową klatki wejściowej, aby umożliwić wykrywanie twarzy.
- W trybie obrazu lub filmu zadanie Wykrywacz twarzy blokuje bieżący wątek, dopóki nie zakończy przetwarzania obrazu wejściowego lub klatki. Aby uniknąć zablokowania interfejsu, przetwarzanie odbywa się w wątku w tle.
- W trybie transmisji na żywo zadanie Wykrywanie twarzy jest natychmiast zwracane 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. Jeśli funkcja wykrywania zostanie wywołana, gdy zadanie Wykrywacz twarzy jest zajęte przetwarzaniem kolejnej klatki, zignoruje nową ramkę wejściową.
W przykładowym kodzie Wykrywacza twarzy funkcje detect
, detectForVideo
i detectAsync
są zdefiniowane w pliku FaceDetectorHelper.kt
.
Obsługa i wyświetlanie wyników
Czujnik twarzy przy każdym uruchomieniu zwraca obiekt FaceDetectorResult
. Wynikowy obiekt zawiera ramki ograniczające dla wykrytych twarzy oraz wskaźnik ufności dla każdej wykrytej twarzy.
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)
Poniższy obraz przedstawia wizualizację wyników zadania:
W przypadku obrazu bez ramek ograniczających wyświetl oryginalny obraz.
Przykładowy kod Wykrywacza twarzy pokazuje, jak wyświetlić wyniki zwrócone z zadania. Więcej informacji znajdziesz w klasie OverlayView
.