Leitfaden zur Objekterkennung für Android

Mit der Aufgabe „Objekterkennung“ können Sie das Vorhandensein und die Position mehrerer Objektklassen erkennen. Ein Objekterkennungssystem kann beispielsweise Hunde in einem Bild finden. In dieser Anleitung erfahren Sie, wie Sie die Aufgabe „Object Detection“ auf Android-Geräten verwenden. Der in dieser Anleitung beschriebene Code ist auf GitHub verfügbar. In dieser Webdemo können Sie sich diese Aufgabe in Aktion ansehen. Weitere Informationen zu den Funktionen, Modellen und Konfigurationsoptionen dieser Aufgabe finden Sie in der Übersicht.

Codebeispiel

Der Beispielcode für MediaPipe Tasks ist eine einfache Implementierung einer Objekterkennungs-App für Android. Im Beispiel wird die Kamera eines physischen Android-Geräts verwendet, um Objekte kontinuierlich zu erkennen. Außerdem können 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 sich an ihr orientieren, wenn Sie eine vorhandene App ändern. Der Beispielcode für den Objektdetektor wird auf GitHub gehostet.

Code herunterladen

In der folgenden Anleitung wird beschrieben, wie Sie mit dem Befehlszeilentool git 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. Optional können Sie Ihre Git-Instanz so konfigurieren, dass eine spärliche Überprüfung verwendet wird, sodass nur die Dateien für die Beispiel-App „Object Detector“ vorhanden sind:
    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 wichtigsten Code für die Beispielanwendung der Objekterkennung:

  • ObjectDetectorHelper.kt: Initialisiert den Objektdetektor und verarbeitet das Modell und die Auswahl des Delegaten.
  • MainActivity.kt: Implementiert die Anwendung und stellt die Komponenten der Benutzeroberfläche zusammen.
  • OverlayView.kt: Verarbeitet und zeigt die Ergebnisse an

Einrichtung

In diesem Abschnitt werden die wichtigsten Schritte zum Einrichten Ihrer Entwicklungsumgebung und zum Erstellen von Codeprojekten für die Verwendung des Objekterkennungstools beschrieben. Allgemeine Informationen zum Einrichten Ihrer Entwicklungsumgebung für die Verwendung von MediaPipe-Aufgaben, einschließlich 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 MediaPipe Object Detection-Aufgabe ist ein trainiertes Modell erforderlich, das mit dieser Aufgabe kompatibel ist. Weitere Informationen zu verfügbaren trainierten Modellen für den Objektdetektor finden Sie in der Aufgabenübersicht im Abschnitt „Modelle“.

Wählen Sie das Modell aus, laden Sie es herunter und speichern Sie es 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 Aufgabe mit der Funktion createFromOptions erstellen. Die Funktion createFromOptions akzeptiert Konfigurationsoptionen wie den Ausführungsmodus, die Sprache für die Anzeige von Namen, die maximale Anzahl von Ergebnissen, den Konfidenzgrenzwert sowie die Zulassungs- und Sperrlisten 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. Sie müssen beim Erstellen der Aufgabe den Ausführungsmodus angeben, der dem Datentyp der Eingabe entspricht. Wählen Sie den Tab für den Datentyp Ihrer Eingabedaten aus, um zu erfahren, 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 Beispielcodeimplementierung des Objekterkennungstools kann der Nutzer zwischen den Verarbeitungsmodi wechseln. Dieser Ansatz macht den Code zum Erstellen von Aufgaben komplizierter und ist möglicherweise nicht für Ihren Anwendungsfall geeignet. Sie finden diesen Code in der Funktion setupObjectDetector() der Klasse ObjectDetectorHelper.

Konfigurationsoptionen

Für diese Aufgabe sind die folgenden Konfigurationsoptionen für Android-Apps verfügbar:

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

IMAGE: Der Modus für Eingaben mit einem einzelnen Bild.

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

LIVE_STREAM: Der Modus für einen Livestream von Eingabedaten, z. B. von einer Kamera. In diesem Modus muss resultListener aufgerufen werden, um einen Listener für den asynchronen Empfang von Ergebnissen einzurichten.
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
displayNamesLocales Legt die Sprache der Labels fest, die für die Anzeigenamen verwendet werden, die in den Metadaten des Modells der Aufgabe angegeben sind, sofern verfügbar. Der Standardwert ist en für Englisch. Mit der TensorFlow Lite Metadata Writer API können Sie den Metadaten eines benutzerdefinierten Modells lokalisierte Labels hinzufügen. Gebietscode de
maxResults Legt die optionale maximale Anzahl der Ergebnisse mit der höchsten Punktzahl fest, die zurückgegeben werden sollen. Beliebige positive Zahlen -1 (alle Ergebnisse werden zurückgegeben)
scoreThreshold Legt den Schwellenwert für die Vorhersagebewertung fest, der den in den Modellmetadaten angegebenen Wert (falls vorhanden) überschreibt. Ergebnisse unter diesem Wert werden abgelehnt. Beliebiger Float Nicht festgelegt
categoryAllowlist Legt die optionale Liste der zulässigen Kategorienamen fest. Wenn die Liste nicht leer ist, werden Erkennungsergebnisse herausgefiltert, deren Kategoriename nicht in dieser Liste enthalten ist. Doppelte oder unbekannte Kategorienamen werden ignoriert. Diese Option schließt categoryDenylist aus. Die Verwendung beider Optionen führt zu einem Fehler. Beliebige Strings Nicht festgelegt
categoryDenylist Hiermit wird eine optionale Liste der nicht zulässigen Kategorienamen festgelegt. Wenn der String nicht leer ist, werden Erkennungsergebnisse herausgefiltert, deren Kategoriename in diesem String enthalten ist. Doppelte oder unbekannte Kategorienamen werden ignoriert. Diese Option schließt categoryAllowlist aus. Die Verwendung beider Optionen führt zu einem Fehler. Beliebige Strings Nicht festgelegt
resultListener Legt fest, dass der Ergebnisempfänger die Erkennungsergebnisse asynchron empfängt, wenn sich der Objektdetektor im Livestream-Modus befindet. Sie können diese Option nur verwenden, wenn Sie „runningMode“ auf „LIVE_STREAM“ setzen. 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.

In den folgenden Beispielen wird für jeden der verfügbaren Datentypen erläutert und gezeigt, wie Daten für die Verarbeitung vorbereitet werden:

Bild

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

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

Livestream

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

Im Beispielcode für den Objektdetektor wird die Datenvorbereitung in der Klasse ObjectDetectorHelper in den Funktionen detectImage(), detectVideoFile() und detectLivestreamFrame() ausgeführt.

Aufgabe ausführen

Verwenden Sie je nach Datentyp die für diesen Datentyp spezifische ObjectDetector.detect...()-Methode. Verwenden Sie detect() für einzelne Bilder, detectForVideo() für Frames in Videodateien und detectAsync() für Videostreams. Wenn du Erkennungen in einem Videostream durchführst, solltest du sie in einem separaten Thread ausführen, um den UI-Thread nicht zu blockieren.

Die folgenden Codebeispiele zeigen einfache Beispiele für die Ausführung des Objekterkennungstools in diesen verschiedenen Datenmodi:

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

Im Codebeispiel für den Objekterkennungs-Detektor werden die Implementierungen der einzelnen Modi detect(), detectVideoFile() und detectAsync() genauer erläutert. Im Beispielcode kann der Nutzer zwischen Verarbeitungsmodi wechseln, was für Ihren Anwendungsfall möglicherweise nicht erforderlich ist.

Wichtige Hinweise:

  • Wenn Sie die Funktion im Video- oder Livestream-Modus ausführen, müssen Sie der Objekterkennungsaufgabe auch den Zeitstempel des Eingabeframes angeben.
  • Wenn die Ausführung im Bild- oder Videomodus erfolgt, blockiert die Aufgabe „Object Detector“ den aktuellen Thread, bis die Verarbeitung des Eingabebilds oder ‑frames abgeschlossen ist. Führen Sie die Verarbeitung in einem Hintergrund-Thread aus, um den aktuellen Thread nicht zu blockieren.
  • Wenn die Ausführung im Livestream-Modus erfolgt, blockiert die Aufgabe „Object Detector“ den aktuellen Thread nicht, sondern gibt sofort eine Rückgabe zurück. Jedes Mal, wenn die Verarbeitung eines Eingabeframes abgeschlossen ist, wird der Ergebnis-Listener mit dem Erkennungsergebnis aufgerufen. Wenn die Funktion „detect“ aufgerufen wird, während die Aufgabe „Object Detector“ gerade einen anderen Frame verarbeitet, wird der neue Eingabeframe ignoriert.

Ergebnisse verarbeiten und anzeigen

Nach der Ausführung der Inferenz gibt die Aufgabe „Object Detector“ ein ObjectDetectorResult-Objekt zurück, das die im Eingabebild gefundenen Objekte beschreibt.

Im Folgenden finden 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:

Zwei Hunde, die mit Begrenzungsrahmen hervorgehoben sind

Im Beispielcode für den Objektdetektor wird gezeigt, wie die von der Aufgabe zurückgegebenen Erkennungsergebnisse angezeigt werden. Weitere Informationen finden Sie in der Klasse OverlayView.