Leitfaden zur Bildklassifizierung für Android

Mithilfe der Aufgabe „MediaPipe-Bildklassifikator“ können Sie Bilder klassifizieren. Mit dieser Aufgabe können Sie ermitteln, was ein Bild aus einer Reihe von Kategorien, die zum Zeitpunkt des Trainings definiert wurden, darstellt. In dieser Anleitung erfahren Sie, wie Sie den Bildklassifikator in Android-Apps verwenden. Das in dieser Anleitung beschriebene Codebeispiel ist auf GitHub verfügbar.

Sie können diese Aufgabe in Aktion sehen, indem Sie sich die Web-Demo ansehen. 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 Bildklassifikator-App für Android. In diesem Beispiel wird die Kamera eines Android-Geräts verwendet, um Objekte kontinuierlich zu klassifizieren. Außerdem können Bilder und Videos aus der Gerätegalerie verwendet werden, um Objekte statisch zu klassifizieren.

Du kannst die App als Ausgangspunkt für deine eigene Android-App verwenden oder beim Ändern einer vorhandenen App darauf zurückgreifen. Der Beispielcode für den Bildklassifikator 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 Ihre Git-Instanz für die Verwendung von Sparse Checkout, sodass Sie nur die Dateien für die Beispielanwendung für den Bildklassifikator haben:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_classification/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 diese Beispielanwendung zur Bildklassifizierung:

Einrichtung

In diesem Abschnitt werden die wichtigsten Schritte zum Einrichten der Entwicklungsumgebung und Codeprojekte für die Verwendung des Bildklassifikators 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 Bildklassifikator 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

Die MediaPipe-Bildklassifikatoraufgabe erfordert ein trainiertes Modell, das mit dieser Aufgabe kompatibel ist. Weitere Informationen zu verfügbaren trainierten Modellen für den Bildklassifikator 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. Auf diese Methode wird im Codebeispiel im nächsten Abschnitt verwiesen.

Im Beispielcode für den Bildklassifikator wird das Modell in der Datei ImageClassifierHelper.kt definiert.

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 und eine Liste der zulässigen oder abgelehnten Kategorien. Weitere Informationen zu Konfigurationsoptionen finden Sie unter Konfigurationsübersicht.

Die Aufgabe „Bildklassifikator“ 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

ImageClassifierOptions options =
  ImageClassifierOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.IMAGE)
    .setMaxResults(5)
    .build();
imageClassifier = ImageClassifier.createFromOptions(context, options);
    

Video

ImageClassifierOptions options =
  ImageClassifierOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.VIDEO)
    .setMaxResults(5)
    .build();
imageClassifier = ImageClassifier.createFromOptions(context, options);
    

Livestream

ImageClassifierOptions options =
  ImageClassifierOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setMaxResults(5)
    .setResultListener((result, inputImage) -> {
         // Process the classification result here.
    })
    .setErrorListener((result, inputImage) -> {
         // Process the classification errors here.
    })
    .build()
imageClassifier = ImageClassifier.createFromOptions(context, options)
    

Mit der Beispielcodeimplementierung für den Bildklassifikator 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 Funktion setupImageClassifier() der Datei ImageClassifierHelper.kt.

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
displayNamesLocale 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 Klassifizierungsergebnisse mit den besten Bewertungen fest, die zurückgegeben werden sollen. Wenn < 0, werden alle verfügbaren Ergebnisse zurückgegeben. Beliebige positive Zahlen -1
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 Klassifizierungsergebnisse herausgefiltert, deren Kategoriename nicht in diesem Set 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 Klassifizierungsergebnisse 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 die Klassifizierungsergebnisse asynchron empfangen werden, wenn sich der Bildklassifikator im Livestreammodus befindet. Kann nur verwendet werden, wenn der Laufmodus auf LIVE_STREAM festgelegt ist Nicht festgelegt
errorListener Legt einen optionalen Fehler-Listener fest. Nicht festgelegt

Daten vorbereiten

Der Bildklassifikator funktioniert mit Bildern, Videodateien und Videos per Livestream. Die Aufgabe übernimmt die Vorverarbeitung der Dateneingabe, einschließlich Größenanpassung, Rotation und Wertnormalisierung.

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

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 value. You’ll need them
// 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()
Image mpImage = new MediaImageBuilder(mediaImage).build();
    

Im Beispielcode für den Bildklassifikator wird die Datenvorbereitung in der Datei ImageClassifierHelper.kt ausgeführt.

Task ausführen

Sie können die classify-Funktion für Ihren Ausführungsmodus aufrufen, um Inferenzen auszulösen. Die Image Classifier API gibt die möglichen Kategorien für das Objekt im Eingabebild oder -frame zurück.

Bild

ImageClassifierResult classifierResult = imageClassifier.classify(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.
ImageClassifierResult classifierResult =
    imageClassifier.classifyForVideo(image, frameTimestampMs);
    

Livestream


// Run inference on the frame. The classifications results will be available 
// via the `resultListener` provided in the `ImageClassifierOptions` when 
// the image classifier was created.
imageClassifier.classifyAsync(image, frameTimestampMs);
    

Wichtige Hinweise:

  • Beim Ausführen im Video- oder Livestreammodus müssen Sie auch den Zeitstempel des Eingabeframes in die Aufgabe zur Bildklassifikation bereitstellen.
  • Bei Ausführung im Bild- oder Videomodus blockiert die Aufgabe „Bildklassifikator“ den aktuellen Thread, bis die Verarbeitung des Eingabebilds oder ‐frames abgeschlossen ist. Führen Sie die Verarbeitung in einem Hintergrundthread aus, damit die Benutzeroberfläche nicht blockiert wird.
  • Im Livestreammodus blockiert die Bildklassifikator-Aufgabe 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 classifyAsync aufgerufen wird, während die Bildklassifikatoraufgabe damit beschäftigt ist, einen anderen Frame zu verarbeiten, wird der neue Eingabeframe von der Aufgabe ignoriert.

Im Beispielcode für den Bildklassifikator sind die classify-Funktionen in der Datei ImageClassifierHelper.kt definiert.

Ergebnisse verarbeiten und anzeigen

Beim Ausführen der Inferenz gibt die Aufgabe zur Bildklassifizierung ein ImageClassifierResult-Objekt zurück, das die Liste möglicher Kategorien für die Objekte im Eingabebild oder Frame enthält.

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

ImageClassifierResult:
 Classifications #0 (single classification head):
  head index: 0
  category #0:
   category name: "/m/01bwb9"
   display name: "Passer domesticus"
   score: 0.91406
   index: 671
  category #1:
   category name: "/m/01bwbt"
   display name: "Passer montanus"
   score: 0.00391
   index: 670

Dieses Ergebnis erhalten Sie, indem Sie den Bird Classifier auf folgenden Geräten ausführen:

Im Beispielcode des Bildklassifikators verarbeitet die Klasse ClassificationResultsAdapter in der Datei ClassificationResultsAdapter.kt die Ergebnisse:

fun updateResults(imageClassifierResult: ImageClassifierResult? = null) {
    categories = MutableList(adapterSize) { null }
    if (imageClassifierResult != null) {
        val sortedCategories = imageClassifierResult.classificationResult()
            .classifications()[0].categories().sortedBy { it.index() }
        val min = kotlin.math.min(sortedCategories.size, categories.size)
        for (i in 0 until min) {
            categories[i] = sortedCategories[i]
        }
    }
}