Leitfaden zur Objekterkennung für Android

Mit der Aufgabe „Objekterkennung“ können Sie das Vorhandensein und den Standort mehrerer Klassen von Objekten erkennen. Ein Objektdetektor kann beispielsweise Hunde in einem Bild lokalisieren. In dieser Anleitung erfahren Sie, wie Sie die Aufgabe „Objektdetektor“ unter Android verwenden. Das in dieser Anleitung beschriebene Codebeispiel ist auf GitHub verfügbar. In dieser Webdemo können Sie diese Aufgabe in Aktion sehen. Weitere Informationen zu den Funktionen, Modellen und Konfigurationsoptionen dieser Aufgabe finden Sie in der Übersicht.

Codebeispiel

Der Beispielcode von MediaPipe Tasks ist eine einfache Implementierung einer Objektdetektor-App für Android. In diesem Beispiel wird die Kamera eines physischen Android-Geräts verwendet, um kontinuierlich Objekte zu erkennen. Es können auch Bilder und Videos aus der Gerätegalerie verwendet werden, um Objekte statisch zu erkennen.

Sie können die App als Ausgangspunkt für Ihre eigene Android-App verwenden oder darauf zurückgreifen, wenn Sie eine vorhandene App ändern. Der Beispielcode des Objektdetektors wird auf GitHub gehostet.

Code herunterladen

In der folgenden Anleitung erfahren Sie, wie Sie mit dem git-Befehlszeilentool eine lokale Kopie des Beispielcodes erstellen.

So laden Sie den Beispielcode herunter:

  1. Klonen Sie das Git-Repository mit dem folgenden Befehl:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. Konfigurieren Sie optional die Git-Instanz für die Verwendung von Sparse Checkout, sodass Sie nur die Dateien für die Beispielanwendung „Objekterkennung“ haben:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/object_detection/android
    

Nachdem Sie eine lokale Version des Beispielcodes erstellt haben, können Sie das Projekt in Android Studio importieren und die App ausführen. Eine Anleitung dazu finden Sie im Einrichtungsleitfaden für Android.

Schlüsselkomponenten

Die folgenden Dateien enthalten den wichtigen Code für die Beispielanwendung des Objektdetektors:

  • ObjectDetectorHelper.kt – Initialisiert den Objektdetektor und verarbeitet das Modell und die Delegierauswahl.
  • MainActivity.kt – implementiert die Anwendung und stellt die Komponenten der Benutzeroberfläche zusammen
  • OverlayView.kt: verarbeitet die Ergebnisse und zeigt sie an.

Einrichtung

In diesem Abschnitt werden die wichtigsten Schritte zum Einrichten der Entwicklungsumgebung und Codeprojekte für die Verwendung von Object Detector beschrieben. Allgemeine Informationen zum Einrichten der Entwicklungsumgebung für die Verwendung von MediaPipe-Aufgaben, einschließlich der Anforderungen an die Plattformversion, finden Sie im Einrichtungsleitfaden für Android.

Abhängigkeiten

Der Objektdetektor verwendet die com.google.mediapipe:tasks-vision-Bibliothek. Fügen Sie diese Abhängigkeit der Datei build.gradle Ihres Android-App-Entwicklungsprojekts hinzu. Importieren Sie die erforderlichen Abhängigkeiten mit dem folgenden Code:

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

Modell

Für die Aufgabe des MediaPipe-Objektdetektors ist ein trainiertes Modell erforderlich, das mit dieser Aufgabe kompatibel ist. Weitere Informationen zu verfügbaren trainierten Modellen für Objektdetektor finden Sie in der Aufgabenübersicht im Abschnitt „Modelle“.

Wählen Sie das Modell aus, laden Sie es herunter und speichern Sie es dann in Ihrem Projektverzeichnis:

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

Verwenden Sie die Methode BaseOptions.Builder.setModelAssetPath(), um den vom Modell verwendeten Pfad anzugeben. Ein Codebeispiel finden Sie im nächsten Abschnitt.

Aufgabe erstellen

Sie können die createFromOptions-Funktion verwenden, um die Aufgabe zu erstellen. Die Funktion createFromOptions akzeptiert Konfigurationsoptionen wie den Ausführungsmodus, die Sprache für Anzeigenamen, die maximale Anzahl von Ergebnissen, den Konfidenzgrenzwert, die Zulassungsliste und die Sperrliste für Kategorien. Wenn keine Konfigurationsoption angegeben ist, wird der Standardwert verwendet. Weitere Informationen zu Konfigurationsoptionen finden Sie unter Konfigurationsübersicht.

Die Aufgabe „Objekterkennung“ unterstützt drei Eingabedatentypen: Standbilder, Videodateien und Live-Videostreams. Beim Erstellen der Aufgabe müssen Sie den Ausführungsmodus angeben, der Ihrem Eingabedatentyp entspricht. Wählen Sie den Tab für Ihren Eingabedatentyp aus, um zu sehen, wie Sie die Aufgabe erstellen und die Inferenz ausführen.

Bild

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

Video

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

Livestream

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);
    

Mit der Implementierung des Beispielcodes für die Objekterkennung können Nutzer zwischen den Verarbeitungsmodi wechseln. Dadurch wird der Code zur Aufgabenerstellung komplizierter und ist für Ihren Anwendungsfall möglicherweise nicht geeignet. Sie finden diesen Code in der setupObjectDetector()-Funktion der ObjectDetectorHelper-Klasse.

Konfigurationsoptionen

Diese Aufgabe umfasst die folgenden Konfigurationsoptionen für Android-Apps:

Option Beschreibung Wertebereich Standardwert
runningMode Legt den Ausführungsmodus für die Task fest. Es gibt drei Modi:

IMAGE: Der Modus für Einzelbildeingaben.

VIDEO: Der Modus für decodierte Frames eines Videos.

LIVE_STREAM: Der Modus für einen Livestream der Eingabedaten, z. B. von einer Kamera. In diesem Modus muss resultListener aufgerufen werden, um einen Listener einzurichten, der die Ergebnisse asynchron empfängt.
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
displayNamesLocales Legt die Sprache von Labels fest, die für Anzeigenamen bereitgestellt werden, die in den Metadaten des Aufgabenmodells angegeben sind, sofern verfügbar. Der Standardwert für Englisch ist en. Mit der TensorFlow Lite Metadata Writer API können Sie den Metadaten eines benutzerdefinierten Modells lokalisierte Labels hinzufügen. Sprachcode en
maxResults Legt die optionale maximale Anzahl der Ergebnisse mit den besten Bewertungen fest, die zurückgegeben werden sollen. Beliebige positive Zahlen -1 (alle Ergebnisse werden zurückgegeben)
scoreThreshold Legt den Schwellenwert für den Vorhersagewert fest, der den in den Modellmetadaten angegebenen Grenzwert überschreibt (falls vorhanden). Ergebnisse unter diesem Wert werden abgelehnt. Beliebige Gleitkommazahl Nicht festgelegt
categoryAllowlist Legt die optionale Liste der zulässigen Kategorienamen fest. Wenn das Feld nicht leer ist, werden Erkennungsergebnisse herausgefiltert, deren Kategoriename nicht in diesem Satz enthalten ist. Doppelte oder unbekannte Kategorienamen werden ignoriert. Diese Option und categoryDenylist schließen sich gegenseitig aus und die Verwendung beider Werte führt zu einem Fehler. Beliebige Strings Nicht festgelegt
categoryDenylist Legt die optionale Liste der nicht zulässigen Kategorienamen fest. Wenn das Feld nicht leer ist, werden Erkennungsergebnisse herausgefiltert, deren Kategoriename in diesem Satz enthalten ist. Doppelte oder unbekannte Kategorienamen werden ignoriert. Diese Option und categoryAllowlist schließen sich gegenseitig aus und die Verwendung beider Optionen führt zu einem Fehler. Beliebige Strings Nicht festgelegt
resultListener Legt den Ergebnis-Listener so fest, dass er die Erkennungsergebnisse asynchron empfängt, wenn sich der Objektdetektor im Livestreammodus befindet. Du kannst diese Option nur verwenden, wenn du „runningMode“ auf LIVE_STREAM festgelegt hast. Nicht zutreffend Nicht festgelegt

Daten vorbereiten

Sie müssen das Eingabebild oder den Eingabeframe in ein com.google.mediapipe.framework.image.MPImage-Objekt konvertieren, bevor Sie es an den Objektdetektor übergeben.

Die folgenden Beispiele erklären und zeigen, wie Daten für die Verarbeitung für jeden der verfügbaren Datentypen vorbereitet werden:

Bild

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

// Load an image on the user’s device as a Bitmap object using BitmapFactory.

// Convert an Android’s Bitmap object to a MediaPipe’s Image object.
Image mpImage = new BitmapImageBuilder(bitmap).build();
    

Video

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 video’s 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 Android’s Bitmap object to a MediaPipe’s Image object.
Image mpImage = new BitmapImageBuilder(frame).build();
    

Livestream

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

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

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

Im Beispielcode des Objektdetektors wird die Datenvorbereitung in der Klasse ObjectDetectorHelper innerhalb der Funktionen detectImage(), detectVideoFile() und detectLivestreamFrame() ausgeführt.

Task ausführen

Verwenden Sie je nach Datentyp, mit dem Sie arbeiten, die Methode ObjectDetector.detect...() für diesen Datentyp. Verwenden Sie detect() für einzelne Bilder, detectForVideo() für Frames in Videodateien und detectAsync() für Videostreams. Wenn Sie Erkennungsvorgänge in einem Videostream durchführen, sollten Sie die Erkennung in einem separaten Thread ausführen, damit der Thread der Benutzeroberfläche nicht blockiert wird.

Die folgenden Codebeispiele enthalten einfache Beispiele dafür, wie der Objektdetektor in diesen verschiedenen Datenmodi ausgeführt wird:

Bild

ObjectDetectorResult detectionResult = objectDetector.detect(image);
    

Video

// 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);
    

Livestream

// 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);
    

Das Codebeispiel für die Objekterkennung zeigt die Implementierungen dieser Modi genauer: detect(), detectVideoFile() und detectAsync(). Mit dem Beispielcode kann der Nutzer zwischen den Verarbeitungsmodi wechseln, die für Ihren Anwendungsfall möglicherweise nicht erforderlich sind.

Wichtige Hinweise:

  • Im Video- oder Livestreammodus müssen Sie außerdem der Objekterkennungsaufgabe den Zeitstempel des Eingabeframes zur Verfügung stellen.
  • Bei Ausführung im Bild- oder Videomodus blockiert die Objekterkennungsaufgabe den aktuellen Thread, bis die Verarbeitung des Eingabebilds oder ‐frames abgeschlossen ist. Damit der aktuelle Thread nicht blockiert wird, führen Sie die Verarbeitung in einem Hintergrundthread aus.
  • Im Livestreammodus blockiert die Objekterkennungsaufgabe den aktuellen Thread nicht, sondern wird sofort zurückgegeben. Jedes Mal, wenn ein Eingabeframe verarbeitet wurde, ruft er seinen Ergebnis-Listener mit dem Erkennungsergebnis auf. Wenn die Funktion „Detect“ aufgerufen wird, während die Aufgabe „Objekterkennung“ mit der Verarbeitung eines weiteren Frames beschäftigt ist, wird der neue Eingabeframe ignoriert.

Ergebnisse verarbeiten und anzeigen

Beim Ausführen der Inferenz gibt die Objekterkennungsaufgabe ein ObjectDetectorResult-Objekt zurück, das die im Eingabebild gefundenen Objekte beschreibt.

Im Folgenden sehen Sie ein Beispiel für die Ausgabedaten dieser Aufgabe:

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

Die folgende Abbildung zeigt eine Visualisierung der Aufgabenausgabe:

Der Beispielcode des Objektdetektors zeigt, wie die von der Aufgabe zurückgegebenen Erkennungsergebnisse angezeigt werden. Weitere Informationen finden Sie in der Klasse OverlayView.