Przewodnik po wykrywaniu obiektów w Androidzie

Zadanie detektora obiektów umożliwia wykrywanie obecności i lokalizacji wielu klas obiektów. Na przykład system do wykrywania obiektów może znajdować psy na obrazie. Z tych instrukcji dowiesz się, jak korzystać z zadania Detektor obiektów na Androidzie. Przykładowy kod opisany w tych instrukcjach jest dostępny na GitHub. Aby zobaczyć, jak to zadanie działa w praktyce, obejrzyj to demonstrację w internecie. 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 Object Detector na Androida. Przykład wykorzystuje kamerę na fizycznym urządzeniu z Androidem do ciągłego wykrywania obiektów, ale może też używać zdjęć i filmów z galerii urządzenia do wykrywania obiektów w sposób statyczny.

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 Object 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:

  1. Sklonuj repozytorium Git za pomocą tego polecenia:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. Opcjonalnie skonfiguruj instancję git do korzystania z rzadkiego sprawdzania, aby mieć tylko pliki przykładowej aplikacji Detector obiektów:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/object_detection/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 Wykrywanie obiektów:

Konfiguracja

W tej sekcji opisaliśmy najważniejsze kroki konfigurowania środowiska programistycznego i projektów kodu na potrzeby korzystania z Obiektowego modułu rozpoznawania. 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

Detektor obiektów korzysta z biblioteki com.google.mediapipe:tasks-vision. Dodaj tę zależność do pliku build.gradle w projekcie tworzenia aplikacji na Androida. Zaimportuj wymagane zależności za pomocą tego kodu:

dependencies {
    implementation 'com.google.mediapipe:tasks-vision:latest.release'
}

Model

Zadanie Wykrywanie obiektów MediaPipe wymaga wytrenowanego modelu zgodnego z tym zadaniem. Więcej informacji o dostępnych wytrenowanych modelach usługi Detektor obiektów 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

Użyj metody BaseOptions.Builder.setModelAssetPath(), aby określić ścieżkę używaną przez model. Przykład kodu znajdziesz w następnej sekcji.

Tworzenie zadania

Do utworzenia zadania możesz użyć funkcji createFromOptions. Funkcja createFromOptions przyjmuje opcje konfiguracji, takie jak tryb działania, lokalizacja wyświetlania nazw, maksymalna liczba wyników, próg ufności oraz lista dozwolonych i zabronionych kategorii. Jeśli opcja konfiguracji nie jest określona, zostanie użyta wartość domyślna. Więcej informacji o opcjach konfiguracji znajdziesz w artykule Omówienie konfiguracji.

Zadanie wykrywania obiektów obsługuje 3 typy danych wejściowych: zdjęcia, 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

ObjectDetectorOptions options =
  ObjectDetectorOptions.builder()
    .setBaseOptions(BaseOptions.builder().setModelAssetPath(‘model.tflite’).build())
    .setRunningMode(RunningMode.IMAGE)
    .setMaxResults(5)
    .build();
objectDetector = ObjectDetector.createFromOptions(context, options);
    

Wideo

ObjectDetectorOptions options =
  ObjectDetectorOptions.builder()
    .setBaseOptions(BaseOptions.builder().setModelAssetPath(‘model.tflite’).build())
    .setRunningMode(RunningMode.VIDEO)
    .setMaxResults(5)
    .build();
objectDetector = ObjectDetector.createFromOptions(context, options);
    

Transmisja na żywo

ObjectDetectorOptions options =
  ObjectDetectorOptions.builder()
    .setBaseOptions(BaseOptions.builder().setModelAssetPath(model.tflite).build())
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setMaxResults(5)
    .setResultListener((result, inputImage) -> {
      // Process the detection result here.
    })
    .setErrorListener((result, inputImage) -> {
      // Process the classification errors here.
    })
   .build();
objectDetector = ObjectDetector.createFromOptions(context, options);
    

Implementacja przykładowego kodu usługi Object Detector 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 setupObjectDetector() klasy ObjectDetectorHelper.

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
displayNamesLocales Określa język etykiet, których należy używać do wyświetlanych nazw podanych w metadanych modelu zadania (jeśli są dostępne). Wartość domyślna to en w przypadku języka angielskiego. Możesz dodawać zlokalizowane etykiety do metadanych modelu niestandardowego, korzystając z interfejsu TensorFlow Lite Metadata Writer API. Kod języka en
maxResults Ustawia opcjonalną maksymalną liczbę wyników wykrywania o najwyższym wyniku, które mają zostać zwrócone. dowolne liczby dodatnie. -1 (zwracane są wszystkie wyniki).
scoreThreshold Ustawia próg wyniku prognozy, który zastępuje próg podany w metadanych modelu (jeśli takie istnieją). Wyniki poniżej tej wartości są odrzucane. Dowolna liczba zmiennych typu float Nie ustawiono
categoryAllowlist Ustawia opcjonalną listę dozwolonych nazw kategorii. Jeśli wyniki wykrywania nie są puste, a nazwa kategorii nie znajduje się w tym zbiorze, zostaną odfiltrowane. Powtarzające się lub nieznane nazwy kategorii są ignorowane. Ta opcja jest wzajemnie wykluczająca się z opcją categoryDenylist. Użycie obu spowoduje błąd. dowolne ciągi znaków; Nie ustawiono
categoryDenylist Ustawia opcjonalną listę nazw kategorii, które są niedozwolone. Jeśli nie jest pusty, wyniki wykrywania, których nazwa kategorii znajduje się w tym zbiorze, zostaną odfiltrowane. Powtarzające się lub nieznane nazwy kategorii są ignorowane. Ta opcja jest wzajemnie wykluczająca się z opcją categoryAllowlist, a użycie obu spowoduje błąd. dowolne ciągi znaków; Nie ustawiono
resultListener Gdy detektor obiektów jest w trybie transmisji na żywo, ustawia odbiornik wyników tak, aby otrzymywał wyniki asynchronicznie. Z tej opcji można korzystać tylko wtedy, gdy ustawienie runningMode ma wartość LIVE_STREAM. Nie dotyczy Nie ustawiono

Przygotuj dane

Przed przekazaniem do usługi Detector obiektów musisz przekonwertować wejściowy obraz lub kadr na obiekt com.google.mediapipe.framework.image.MPImage.

W przypadku każdego z dostępnych typów danych znajdziesz przykłady, które pokazują, jak przygotować dane do przetwarzania:

Obraz

import com.google.mediapipe.framework.image.BitmapImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Load an image on the users device as a Bitmap object using BitmapFactory.

// Convert an Androids Bitmap object to a MediaPipes Image object.
Image mpImage = new BitmapImageBuilder(bitmap).build();
    

Wideo

import com.google.mediapipe.framework.image.BitmapImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Load a video file on the user's device using MediaMetadataRetriever

// From the videos metadata, load the METADATA_KEY_DURATION and
// METADATA_KEY_VIDEO_FRAME_COUNT values. Use these values
// to calculate the timestamp of each frame later.

// Loop through the video and load each frame as a Bitmap object.

// Convert the Androids Bitmap object to a MediaPipes Image object.
Image mpImage = new BitmapImageBuilder(frame).build();
    

Transmisja na żywo

import com.google.mediapipe.framework.image.MediaImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Create a CameraXs ImageAnalysis to continuously receive frames
// from the devices camera. Configure it to output frames in RGBA_8888
// format to match with what is required by the model.

// For each Androids ImageProxy object received from the ImageAnalysis,
// extract the encapsulated Androids Image object and convert it to
// a MediaPipes Image object.
android.media.Image mediaImage = imageProxy.getImage()
MPImage mpImage = new MediaImageBuilder(mediaImage).build();
    

W przykładowym kodzie detektora obiektów przygotowanie danych jest obsługiwane w klasie ObjectDetectorHelper w funkcjach detectImage(), detectVideoFile()detectLivestreamFrame().

Uruchamianie zadania

W zależności od typu danych, z którymi pracujesz, użyj metody ObjectDetector.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 modułu Object Detector w różnych trybach danych:

Obraz

ObjectDetectorResult detectionResult = objectDetector.detect(image);
    

Wideo

// Calculate the timestamp in milliseconds of the current frame.
long frame_timestamp_ms = 1000 * video_duration * frame_index / frame_count;

// Run inference on the frame.
ObjectDetectorResult detectionResult =
    objectDetector.detectForVideo(image, frameTimestampMs);
    

Transmisja na żywo

// Run inference on the frame. The detection results will be available
// via the `resultListener` provided in the `ObjectDetectorOptions` when
// the object detector was created.
objectDetector.detectAsync(image, frameTimestampMs);
    

Przykład kodu detektora obiektów pokazuje szczegółowe implementacje tych trybów: detect(), detectVideoFile() i detectAsync(). Przykładowy kod umożliwia użytkownikowi przełączanie się między trybami przetwarzania, co może nie być wymagane w Twoim przypadku.

Pamiętaj:

  • W trybie wideo lub transmisji na żywo musisz też podać zadaniu detektora obiektów sygnaturę czasową ramki wejściowej.
  • W trybie obrazu lub filmu zadanie wykrywania obiektów blokuje bieżący wątek, dopóki nie zakończy przetwarzania obrazu wejściowego lub klatki. Aby uniknąć blokowania bieżącego wątku, przeprowadź przetwarzanie w wątku tła.
  • W trybie transmisji na żywo zadanie detektora obiektów nie blokuje bieżącego wątku, ale zwraca wynik natychmiast. Za każdym razem, gdy zakończy przetwarzanie ramki wejściowej, wywoła swojego słuchacza z wynikiem wykrywania. Jeśli funkcja wykrywania jest wywoływana, gdy zadanie detektora obiektów jest zajęte przetwarzaniem innego kadru, nowy kadr wejściowy zostanie zignorowany.

Obsługa i wyświetlanie wyników

Po przeprowadzeniu wnioskowania zadanie detektora obiektów zwraca obiekt ObjectDetectorResult, który opisuje obiekty znalezione na wejściowym obrazie.

Poniżej znajdziesz przykład danych wyjściowych z tego zadania:

ObjectDetectorResult:
 Detection #0:
  Box: (x: 355, y: 133, w: 190, h: 206)
  Categories:
   index       : 17
   score       : 0.73828
   class name  : dog
 Detection #1:
  Box: (x: 103, y: 15, w: 138, h: 369)
  Categories:
   index       : 17
   score       : 0.73047
   class name  : dog

Na ilustracji poniżej widać wynik wykonania zadania:

2 psy wyróżnione za pomocą ramek ograniczających

Przykładowy kod detektora obiektów pokazuje, jak wyświetlać wyniki wykrywania zwrócone przez zadanie. Więcej informacji znajdziesz w klasie OverlayView.