Leitfaden zur Bildklassifizierung für Android

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

In unserer 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 Bildklassifikator-App für Android. In diesem Beispiel wird die Kamera eines physischen Android-Geräts verwendet, um kontinuierlich Objekte zu klassifizieren. Es können auch 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 darauf verweisen, wenn du eine vorhandene App änderst. Der Beispielcode für den Bildklassifikator wird auf GitHub gehostet.

Code herunterladen

Die folgende Anleitung zeigt, 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. Optional können Sie die Git-Instanz für die Verwendung der sparsamen Bezahlung konfigurieren, damit Sie nur die Dateien für die Beispielanwendung „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 Ihrer 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

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

Für die Aufgabe „MediaPipe Image Classifier“ ist ein trainiertes Modell erforderlich, 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

Zum Erstellen der Aufgabe können Sie die Funktion createFromOptions verwenden. 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. Sie müssen beim Erstellen der Aufgabe den Ausführungsmodus angeben, der Ihrem Eingabedatentyp entspricht. Wählen Sie den Tab aus, der Ihrem Eingabedatentyp entspricht, um zu sehen, wie Sie die Aufgabe erstellen und eine 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 dem Beispielcode für den Bildklassifikator kann der Nutzer zwischen den Verarbeitungsmodi wechseln. Dieser Ansatz macht den Code zur Aufgabenerstellung komplizierter und ist für Ihren Anwendungsfall möglicherweise nicht geeignet. Sie können diesen Code in der Funktion setupImageClassifier() der Datei ImageClassifierHelper.kt sehen.

Konfigurationsoptionen

Diese Aufgabe bietet 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 mit Eingabedaten, z. B. von einer Kamera. In diesem Modus muss resultListener aufgerufen werden, um einen Listener einzurichten, der Ergebnisse asynchron empfängt.
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
displayNamesLocale Legt die Sprache der Labels fest, die für Anzeigenamen verwendet werden sollen, 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 Gebietsschemacode en
maxResults Legt die optionale maximale Anzahl der am besten bewerteten Klassifizierungsergebnisse 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 die Vorhersagepunktzahl fest, der den in den Modellmetadaten angegebenen Wert überschreibt (falls vorhanden). Ergebnisse unter diesem Wert werden abgelehnt. Beliebiger Gleitkommawert 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 Satz enthalten ist. Doppelte oder unbekannte Kategorienamen werden ignoriert. Diese Option schließt sich mit categoryDenylist gegenseitig aus und die Verwendung beider führt zu einem Fehler. Alle Strings Nicht festgelegt
categoryDenylist Legt die optionale Liste der unzulässigen Kategorienamen fest. Ist dieses Feld nicht leer, werden Klassifizierungsergebnisse herausgefiltert, deren Kategoriename in diesem Satz enthalten ist. Doppelte oder unbekannte Kategorienamen werden ignoriert. Diese Option schließt sich mit categoryAllowlist gegenseitig aus und die Verwendung beider führt zu einem Fehler. Alle Strings Nicht festgelegt
resultListener Legt fest, dass der Ergebnis-Listener die Klassifizierungsergebnisse asynchron empfängt, wenn sich der Bildklassifikator im Livestreammodus befindet. Kann nur verwendet werden, wenn der Ausführungsmodus auf LIVE_STREAM festgelegt ist Nicht festgelegt
errorListener Legt einen optionalen Fehler-Listener fest. Nicht festgelegt

Daten vorbereiten

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

Sie müssen das Eingabebild oder den Eingabeframe vor der Übergabe an den Bildklassifikator in ein com.google.mediapipe.framework.image.MPImage-Objekt konvertieren.

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 Bildklassifikatoren wird die Datenvorbereitung in der Datei ImageClassifierHelper.kt durchgeführt.

Aufgabe ausführen

Sie können die Funktion classify für Ihren Ausführungsmodus aufrufen, um Inferenzen auszulösen. Die Image Classifier API gibt die möglichen Kategorien für das Objekt innerhalb des Eingabebilds oder -frames 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:

  • Im Video- oder Livestreammodus müssen Sie außerdem den Zeitstempel des Eingabeframes an die Aufgabe des Bildklassifikators übergeben.
  • Im Bild- oder Videomodus blockiert die Aufgabe des Bildklassifikators 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 Aufgabe „Bildklassifikator“ nicht den aktuellen Thread, sondern kehrt sofort zurück. Sobald die Verarbeitung eines Eingabeframes abgeschlossen ist, wird der zugehörige Ergebnis-Listener mit dem Erkennungsergebnis aufgerufen. Wenn die Funktion classifyAsync aufgerufen wird, während die Aufgabe des Bildklassifikators mit der Verarbeitung eines anderen Frames beschäftigt ist, ignoriert die Aufgabe den neuen Eingabeframe.

Im Beispielcode für Bildklassifikatoren werden die classify-Funktionen in der Datei ImageClassifierHelper.kt definiert.

Ergebnisse verarbeiten und anzeigen

Beim Ausführen einer Inferenz gibt die Bildklassifikatoraufgabe ein ImageClassifierResult-Objekt zurück, das die Liste der möglichen Kategorien für die Objekte innerhalb des Eingabebilds oder -frames 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 wurde erhalten, indem der Vogelklassifikator auf folgenden Geräten ausgeführt wurde:

Im Beispielcode für Bildklassifikatoren 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]
        }
    }
}