Przewodnik po wykrywaniu obiektów w Androidzie

Zadanie Wykrywacz obiektów umożliwia wykrywanie obecności i lokalizacji wielu klas obiektów. Na przykład wykrywacz obiektów może w . Te instrukcje pokazują, jak używać zadania Wykrywacz obiektów na na urządzeniu z Androidem. Przykładowy kod opisany w tych instrukcjach jest dostępny na GitHub Aby zobaczyć, jak działa to zadanie, wyświetl Prezentacja w przeglądarce. Więcej informacji o funkcjach, modelach i opcjach konfiguracji zapoznaj się z Przeglądem.

Przykładowy kod

Przykładowy kod MediaPipe Tasks to prosta implementacja wykrywania obiektów na Androida. W tym przykładzie użyliśmy aparatu w fizycznym urządzeniu z Androidem, stale wykrywają obiekty, a także mogą używać obrazów i filmów do statycznego wykrywania obiektów.

Możesz użyć tej aplikacji jako punktu wyjścia dla własnej aplikacji na Androida lub odnieść się do niej podczas modyfikowania istniejącej aplikacji. Przykładowy kod wykrywania obiektów jest hostowany GitHub

Pobieranie kodu

Poniżej znajdziesz instrukcje tworzenia lokalnej kopii przykładu. 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 tak, aby wykorzystywała rozproszony proces płatności, masz więc tylko pliki przykładowej aplikacji Wykrywacz 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 w Android Studio i uruchom aplikację. Instrukcje znajdziesz w Przewodnik po konfiguracji na Androida

Kluczowe elementy

Poniższe pliki zawierają kluczowy kod wykrywania obiektów przykładowa aplikacja:

Konfiguracja

W tej sekcji opisujemy najważniejsze czynności związane z konfigurowaniem środowiska programistycznego oraz w projektach kodu, w których mają być używane detektor obiektów. Ogólne informacje na temat: skonfigurować środowisko programistyczne do korzystania z zadań MediaPipe, w tym wymagań wersji platformy, patrz Przewodnik po konfiguracji na Androida

Zależności

Wykrywacz obiektów używa biblioteki com.google.mediapipe:tasks-vision. Dodaj to zależności od pliku build.gradle Projekt tworzenia aplikacji na Androida. Zaimportuj wymagane zależności za pomocą: ten kod:

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

Model

Zadanie wykrywania obiektów MediaPipe wymaga wytrenowanego modelu, który jest z nim zgodny zadanie. Więcej informacji o dostępnych wytrenowanych modelach z wykrywaniem obiektów znajdziesz w artykule zapoznaj się z omówieniem zadania sekcją Modele.

Wybierz i pobierz model, a następnie zapisz go w katalogu projektu:

<dev-project-root>/src/main/assets

Użyj metody BaseOptions.Builder.setModelAssetPath(), aby podać ścieżkę używane przez model. Przykładowy kod znajdziesz w następnej sekcji.

Tworzenie zadania

Do utworzenia zadania możesz użyć funkcji createFromOptions. Funkcja createFromOptions akceptuje opcje konfiguracji, w tym uruchomione tryb, język wyświetlanych nazw, maksymalna liczba wyników, próg ufności, listy dozwolonych i zablokowanych kategorii. Jeśli opcja konfiguracji nie jest określona, zostanie użyta wartość domyślna. Więcej informacji o opcjach konfiguracji znajdziesz zobacz Omówienie konfiguracji.

Zadanie Wykrywacz obiektów obsługuje 3 typy danych wejściowych: nieruchome obrazy i pliki wideo i transmisje wideo na żywo. Musisz określić tryb działania odpowiadający parametrowi typ danych wejściowych podczas tworzenia zadania. Wybierz kartę odpowiadającą typ danych wejściowych, aby zobaczyć, jak utworzyć zadanie i uruchomić 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);
    

Przykładowa implementacja kodu Wykrywacza obiektów umożliwia użytkownikowi przełączanie się i przetwarzania danych. Takie podejście sprawia, że kod tworzenia zadań jest bardziej skomplikowany, może nie być odpowiednia w Twoim przypadku użycia. Możesz zobaczyć ten kod w ObjectDetectorHelper funkcji setupObjectDetector() klasy.

Opcje konfiguracji

To zadanie zawiera te opcje konfiguracji aplikacji na Androida:

Nazwa opcji Opis Zakres wartości Wartość domyślna
runningMode Ustawia tryb działania zadania. Są trzy tryby:

IMAGE: tryb wprowadzania pojedynczego obrazu.

WIDEO: tryb zdekodowanych klatek filmu.

LIVE_STREAM: tryb transmisji danych wejściowych na przykład z kamery. W tym trybie detektor wyników musi mieć wartość wywołano, aby skonfigurować detektor i otrzymywać wyniki asynchronicznie.
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
displayNamesLocales Ustawia język etykiet, które mają być używane w przypadku nazw wyświetlanych w kolumnie metadane modelu zadania, jeśli są dostępne. Wartość domyślna to en dla Angielski. Do metadanych modelu niestandardowego możesz dodać zlokalizowane etykiety za pomocą interfejsu TensorFlow Lite Metadata Writer API. Kod języka en
maxResults Ustawia opcjonalną maksymalną liczbę wyników wykrywania na . Dowolne liczby dodatnie -1 (zostaną zwrócone wszystkie wyniki)
scoreThreshold Ustawia próg wyniku prognozy, który zastępuje próg podany w polu metadane modelu (jeśli występują). Wyniki poniżej tej wartości zostały odrzucone. Dowolna liczba zmiennoprzecinkowa Nie ustawiono
categoryAllowlist Ustawia opcjonalną listę dozwolonych nazw kategorii. Jeśli pole nie jest puste, wyniki wykrywania, których nazwa kategorii nie znajduje się w tym zestawie, zostaną zostały odfiltrowane. Zduplikowane lub nieznane nazwy kategorii są ignorowane. Ta opcja nie działa z usługą categoryDenylist i korzysta z funkcji skutkuje to błędem. Dowolne ciągi Nie ustawiono
categoryDenylist Ustawia opcjonalną listę nazw kategorii, które nie są dozwolone. Jeśli niepuste, wyniki wykrywania, których nazwa kategorii znajduje się w tym zbiorze, zostaną odfiltrowane na zewnątrz. Zduplikowane lub nieznane nazwy kategorii są ignorowane. Ta opcja jest wzajemna tylko w polu categoryAllowlist, co spowoduje błąd. Dowolne ciągi Nie ustawiono
resultListener Konfiguruje detektor wyników, który otrzymuje wyniki wykrywania asynchronicznie, gdy detektor obiektów jest w transmisji na żywo. i trybu uzyskiwania zgody. Tej opcji możesz użyć tylko wtedy, gdy ustawisz runMode na LIVE_STREAM. Nie dotyczy Nie ustawiono

Przygotuj dane

Musisz przekonwertować obraz lub klatkę wejściową do com.google.mediapipe.framework.image.MPImage obiekt przed przekazaniem do Wykrywacz obiektów.

Poniższe przykłady wyjaśniają i pokazują, jak przygotować dane do przetwarzania dla każdego z dostępnych typów danych:

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 Wykrywacza obiektów przygotowanie danych odbywa się w instrukcji ObjectDetectorHelper zajęcia w: detectImage(), detectVideoFile(), detectLivestreamFrame() funkcji.

Uruchamianie zadania

W zależności od typu danych, z którymi pracujesz, skorzystaj z ObjectDetector.detect...(), która jest specyficzna dla tego typu danych. Używaj detect() w przypadku pojedynczych zdjęć, detectForVideo() w przypadku klatek w plikach wideo oraz detectAsync() w przypadku strumieni wideo. Jeśli wykonujesz wykrywanie na wideo, pamiętaj, aby uruchomić wykrywanie w oddzielnym wątku, aby uniknąć blokując wątek interfejsu użytkownika.

Poniżej znajdziesz przykładowy kod pokazujący, jak w prosty sposób uruchomić Wykrywacz obiektów 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ładowy kod wykrywania obiektów pokazuje implementacje każdego z tych elementów bardziej szczegółowo detect() detectVideoFile(), i detectAsync(). Przykładowy kod pozwala użytkownikowi przełączać się między trybami przetwarzania które może nie być wymagane w Twoim przypadku użycia.

Pamiętaj:

  • Gdy pracujesz w trybie wideo lub w trybie transmisji na żywo, musisz też podaj sygnaturę czasową ramki wejściowej do zadania Wykrywacz obiektów.
  • W trybie obrazu lub wideo zadanie Wykrywacz obiektów zablokuj bieżący wątek do czasu zakończenia przetwarzania obrazu wejściowego lub ramki. Aby uniknąć zablokowania bieżącego wątku, wykonaj przetwarzanie w w wątku w tle.
  • W trybie transmisji na żywo zadanie Wykrywacz obiektów nie jest blokowane. w bieżącym wątku, ale wraca natychmiast. Wywoła swój wynik detektor z wynikiem wykrywania za każdym razem, gdy zakończy przetwarzanie ramki wejściowej. Jeśli funkcja wykrywania jest wywoływana, gdy zadanie Wykrywacz obiektów jest zajęty przetwarzaniem kolejnej klatki, nowa ramka wejściowa zostanie zignorowana.

Obsługa i wyświetlanie wyników

Po uruchomieniu wnioskowania zadanie Wykrywacz obiektów zwraca błąd ObjectDetectorResult obiekt opisujący znalezione obiekty obrazu wejściowego.

Poniżej znajdziesz przykładowe dane wyjściowe 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

Ten obraz przedstawia wizualizację danych wyjściowych zadania:

Przykładowy kod wykrywania obiektów pokazuje, jak wyświetlić wykrywanie wyników zwróconych przez zadanie, patrz OverlayView klasy, by dowiedzieć się więcej.