Leitfaden zur Bildsegmentierung unter Android

Mit der Aufgabe MediaPipe Image Segmenter können Sie Bilder basierend auf vordefinierten Kategorien für visuelle Effekte wie das Weichzeichnen des Hintergrunds. Diese Anleitung zur Verwendung des Bildsegmenters mit Android-Apps. Der Code das in dieser Anleitung beschriebene Beispiel GitHub Weitere Informationen zu Funktionen, Modellen und Konfigurationsoptionen Sehen Sie sich die Übersicht an.

Codebeispiel

Das Codebeispiel von MediaPipe Tasks enthält zwei einfache Implementierungen eines Bildsegmentierungs-App für Android:

In den Beispielen wird die Kamera eines physischen Android-Geräts verwendet, um in einem Live-Kamerafeed eine Bildsegmentierung durchführen. Alternativ können Sie auch Bilder auswählen und Videos aus der Gerätegalerie. Sie können die Apps als Ausgangspunkt für Ihre eigene Android-App verwenden oder auf sie verweisen, wenn Sie eine bestehende App ändern. Die Der Beispielcode für die Bildsegmentierung wird auf GitHub

Die folgenden Abschnitte beziehen sich auf die Bildsegmenter mit einer Kategoriemaske

Code herunterladen

In der folgenden Anleitung erfahren Sie, wie Sie eine lokale Kopie des Beispiels erstellen. mit dem Befehlszeilentool git 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 den Sparse-Checkout. Sie haben also nur die Dateien für die Beispiel-App "Bildsegmentierung":
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_segmentation/android
    

Nachdem Sie eine lokale Version des Beispielcodes erstellt haben, können Sie das Projekt importieren in Android Studio ein und führen die App aus. Anweisungen finden Sie in der Einrichtungsleitfaden für Android

Schlüsselkomponenten

Die folgenden Dateien enthalten den wichtigen Code für dieses Bild. Beispielanwendung für Segmentierung:

  • ImageSegmenterHelper.kt Initialisiert die Image Segmenter-Aufgabe und verarbeitet das Modell und delegieren Auswahl.
  • CameraFragment.kt Stellt die Benutzeroberfläche und den Steuercode für eine Kamera bereit.
  • GalleryFragment.kt Stellt die Benutzeroberfläche und den Steuercode für die Auswahl von Bildern und Videos bereit Dateien.
  • OverlayView.kt Verarbeitet und formatiert die Segmentierungsergebnisse.

Einrichtung

In diesem Abschnitt werden die wichtigsten Schritte zum Einrichten Ihrer Entwicklungsumgebung und Codeprojekte für die Verwendung des Image-Segmenters. Allgemeine Informationen zu Einrichten Ihrer Entwicklungsumgebung für die Verwendung von MediaPipe-Aufgaben, einschließlich Plattformversionsanforderungen finden Sie in der Einrichtungsleitfaden für Android

Abhängigkeiten

Die Bildsegmentierung verwendet die com.google.mediapipe:tasks-vision-Bibliothek. Dieses Element hinzufügen Abhängigkeit zur build.gradle-Datei Ihres Android-App-Entwicklungsprojekt Importieren Sie die erforderlichen Abhängigkeiten mit den folgenden Code:

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

Modell

Für die Aufgabe „MediaPipe Image Segmenter“ ist ein trainiertes Modell erforderlich, . Weitere Informationen zu verfügbaren trainierten Modellen für den Bildsegmentator finden Sie unter 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 Pfad anzugeben. die vom Modell verwendet werden. Diese Methode wird im Codebeispiel in den .

Im Bildsegmentierer Beispielcode Das Modell ist in ImageSegmenterHelper.kt definiert. in der Funktion setupImageSegmenter().

Aufgabe erstellen

Zum Erstellen der Aufgabe können Sie die Funktion createFromOptions verwenden. Die Die Funktion createFromOptions akzeptiert Konfigurationsoptionen, einschließlich Maskenausgabe Typen. Weitere Informationen zur Aufgabenkonfiguration finden Sie unter Konfigurationsoptionen.

Die Aufgabe "Bildsegmentierung" unterstützt folgende Eingabedatentypen: Standbilder, Videodateien und Live-Videostreams. Du musst den Laufmodus angeben die dem Eingabedatentyp entsprechen. Tab auswählen für Ihren Eingabedatentyp aus, um zu sehen, wie Sie diese Aufgabe erstellen.

Bild

ImageSegmenterOptions options =
  ImageSegmenterOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.IMAGE)
    .setOutputCategoryMask(true)
    .setOutputConfidenceMasks(false)
    .build();
imagesegmenter = ImageSegmenter.createFromOptions(context, options);
    

Video

ImageSegmenterOptions options =
  ImageSegmenterOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.VIDEO)
    .setOutputCategoryMask(true)
    .setOutputConfidenceMasks(false)
    .build();
imagesegmenter = ImageSegmenter.createFromOptions(context, options);
    

Livestream

ImageSegmenterOptions options =
  ImageSegmenterOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setOutputCategoryMask(true)
    .setOutputConfidenceMasks(false)
    .setResultListener((result, inputImage) -> {
         // Process the segmentation result here.
    })
    .setErrorListener((result, inputImage) -> {
         // Process the segmentation errors here.
    })
    .build()
imagesegmenter = ImageSegmenter.createFromOptions(context, options)
    

Mit dem Beispielcode für die Bildsegmentierung können Nutzer zwischen Verarbeitungsmodi. Dieser Ansatz macht den Code zur Aufgabenerstellung komplizierter und ist möglicherweise für Ihren Anwendungsfall ungeeignet. Sie sehen diesen Code in der ImageSegmenterHelper -Klasse durch die Funktion setupImageSegmenter().

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 Eingabe zum Beispiel von einer Kamera. In diesem Modus muss der resultListener wird aufgerufen, um einen Listener für den Empfang von Ergebnissen einzurichten asynchron programmiert.
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
outputCategoryMask Wenn True festgelegt ist, enthält die Ausgabe eine Segmentierungsmaske als Uint8-Bild, wobei jeder Pixelwert die Gewinnerkategorie angibt Wert. {True, False} False
outputConfidenceMasks Wenn True festgelegt ist, enthält die Ausgabe eine Segmentierungsmaske als Gleitkommawert, wobei jeder Gleitkommawert den Konfidenzwert darstellt Kurzübersicht der Kategorie. {True, False} True
displayNamesLocale Legt die Sprache der Labels fest, die für Anzeigenamen in der Metadaten des Aufgabenmodells, falls verfügbar. Standardwert ist en für Englisch. Sie können den Metadaten eines benutzerdefinierten Modells lokalisierte Labels hinzufügen mit der TensorFlow Lite Metadata Writer API Gebietsschemacode de
resultListener Legt den Ergebnis-Listener fest, der die Segmentierungsergebnisse empfangen soll asynchron, wenn sich der Bildsegmentierer im LIVE_STREAM-Modus befindet. Kann nur verwendet werden, wenn der Ausführungsmodus auf LIVE_STREAM festgelegt ist
errorListener Legt einen optionalen Fehler-Listener fest. Nicht festgelegt

Daten vorbereiten

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

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

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 die Bildsegmentierung wird die Datenvorbereitung in der ImageSegmenterHelper Klasse durch die Funktion segmentLiveStreamFrame().

Aufgabe ausführen

Sie rufen je nach verwendetem Ausführungsmodus eine andere segment-Funktion auf. Die Bildsegmentierungsfunktion gibt die identifizierten Segmentbereiche innerhalb der ein Bild oder einen Frame ein.

Bild

ImageSegmenterResult segmenterResult = imagesegmenter.segment(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.
ImageSegmenterResult segmenterResult =
    imagesegmenter.segmentForVideo(image, frameTimestampMs);
    

Livestream

// Run inference on the frame. The segmentations results will be available via
// the `resultListener` provided in the `ImageSegmenterOptions` when the image
// segmenter was created.
imagesegmenter.segmentAsync(image, frameTimestampMs);
    

Wichtige Hinweise:

  • Im Video- oder Livestreammodus musst du außerdem den Zeitstempel des Eingabe-Frames für die Bildsegmentierungs-Aufgabe angeben.
  • Bei der Ausführung im Bild- oder Videomodus kann die Aufgabe blockiert den aktuellen Thread, bis die Verarbeitung des Eingabebildes Frame. Damit die Benutzeroberfläche nicht blockiert wird, führen Sie die Verarbeitung in einem im Hintergrund.
  • Im Livestreammodus blockiert die Aufgabe „Bildsegmentierung“ nicht aktuellen Thread angelehnt, aber sofort wieder zurück. Das Ergebnis wird aufgerufen. Listener mit dem Erkennungsergebnis, sobald er die Verarbeitung eines Eingabe-Frame. Wenn die Funktion segmentAsync aufgerufen wird, wenn der die Aufgabe mit der Verarbeitung eines anderen Frames beschäftigt ist, ignoriert die Aufgabe den neuen Eingabeframe.

Im Beispielcode für die Bildsegmentierung sind die segment-Funktionen im ImageSegmenterHelper.kt -Datei.

Ergebnisse verarbeiten und anzeigen

Beim Ausführen einer Inferenz gibt die Image-Segmenter-Aufgabe eine ImageSegmenterResult zurück. -Objekt, das die Ergebnisse der Segmentierungsaufgabe enthält. Der Inhalt der die Ausgabe hängt von der outputType ab, die Sie bei der konfiguriert.

In den folgenden Abschnitten finden Sie Beispiele für die Ausgabedaten dieser Aufgabe:

Kategorie-Konfidenz

Die folgenden Bilder zeigen eine Visualisierung der Aufgabenausgabe für eine Kategorie Konfidenzmaske. Die Ausgabe der Konfidenzmaske enthält Gleitkommawerte zwischen [0, 1]

Ausgabe der Konfidenzmaske des Originalbilds und der Kategorie. Quell-Image von Pascal VOC 2012 Dataset.

Kategoriewert

Die folgenden Bilder zeigen eine Visualisierung der Aufgabenausgabe für eine Kategorie Wertmaske. Der Bereich der Kategoriemaske ist [0, 255] und jeder Pixelwert stellt den erfolgreichen Kategorieindex der Modellausgabe dar. Die Gewinnerkategorie Index die höchste Punktzahl unter den Kategorien hat, die das Modell erkennen kann.

Ausgabe des Originalbilds und der Kategoriemaske. Quell-Image von Pascal VOC 2012 Dataset.