Mit der MediaPipe-Aufgabe „Bildsegmentierung“ können Sie Bilder basierend auf vordefinierten Kategorien in Regionen unterteilen, um visuelle Effekte wie das Weichzeichnen des Hintergrunds anzuwenden. In dieser Anleitung erfahren Sie, wie Sie den Bildsegmenter mit Android-Apps verwenden. Das in dieser Anleitung beschriebene Codebeispiel ist auf GitHub verfügbar. Weitere Informationen zu den Funktionen, Modellen und Konfigurationsoptionen dieser Aufgabe finden Sie in der Übersicht.
Codebeispiel
Das MediaPipe Tasks-Codebeispiel enthält zwei einfache Implementierungen einer Bildsegmentierungs-App für Android:
In den Beispielen wird die Kamera eines Android-Geräts verwendet, um die Bildsegmentierung in einem Live-Kamerafeed durchzuführen. Sie können aber auch Bilder und Videos aus der Gerätegalerie auswählen. Sie können die Apps als Ausgangspunkt für Ihre eigene Android-App verwenden oder sich an ihnen orientieren, wenn Sie eine vorhandene App ändern. Der Beispielcode für den Bildsegmenter wird auf GitHub gehostet.
Die folgenden Abschnitte beziehen sich auf die App Bildsegmentierung mit einer Kategoriemaske.
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:
- Klonen Sie das Git-Repository mit dem folgenden Befehl:
git clone https://github.com/google-ai-edge/mediapipe-samples
- Optional können Sie Ihre Git-Instanz so konfigurieren, dass eine spärliche Überprüfung verwendet wird, sodass nur die Dateien für die Beispielanwendung „Image Segmenter“ vorhanden sind:
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 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 diese Beispielanwendung zur Bildsegmentierung:
- ImageSegmenterHelper.kt: Hiermit wird die Aufgabe „Bildsegmentierung“ initialisiert und das Modell und die Auswahl des zuständigen Diensts verwaltet.
- CameraFragment.kt: Bietet die Benutzeroberfläche und den Steuercode für eine Kamera.
- GalleryFragment.kt: Bietet die Benutzeroberfläche und den Steuercode zum Auswählen von Bild- und Videodateien.
- OverlayView.kt: Hier werden die Segmentierungsergebnisse verarbeitet und formatiert.
Einrichtung
In diesem Abschnitt werden die wichtigsten Schritte zur Einrichtung Ihrer Entwicklungsumgebung und Codeprojekte für die Verwendung des Bildsegmentierungstools 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
Für den Bildsegmentierungstool wird die com.google.mediapipe:tasks-vision
-Bibliothek verwendet. 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-Aufgabe „Bildsegmentierung“ ist ein trainiertes Modell erforderlich, das mit dieser Aufgabe kompatibel ist. Weitere Informationen zu verfügbaren trainierten Modellen für den Bildsegmenter 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. Auf diese Methode wird im Codebeispiel im nächsten Abschnitt verwiesen.
Im Beispielcode für den Bildsegmenter wird das Modell in der Klasse ImageSegmenterHelper.kt
in der Funktion setupImageSegmenter()
definiert.
Aufgabe erstellen
Sie können die Aufgabe mit der Funktion createFromOptions
erstellen. Die Funktion createFromOptions
akzeptiert Konfigurationsoptionen, einschließlich Maskierungsausgabetypen. Weitere Informationen zur Aufgabenkonfiguration finden Sie unter Konfigurationsoptionen.
Die Aufgabe „Bildsegmentierung“ unterstützt die folgenden Eingabedatentypen: Standbilder, Videodateien und Live-Videostreams. Sie müssen beim Erstellen der Aufgabe den Ausführungsmodus angeben, der dem Eingabedatentyp entspricht. Wählen Sie den Tab für den Datentyp Ihrer Eingabe 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 der Beispielcodeimplementierung des Bildsegmenters 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 Klasse ImageSegmenterHelper
unter der Funktion setupImageSegmenter()
.
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 |
outputCategoryMask |
Wenn dieser Wert auf True festgelegt ist, enthält die Ausgabe eine Segmentierungsmaske als uint8-Bild, bei der jeder Pixelwert den Wert der Gewinnerkategorie angibt. |
{True, False } |
False |
outputConfidenceMasks |
Wenn dieser Parameter auf True festgelegt ist, enthält die Ausgabe eine Segmentierungsmaske als Bild mit Gleitkommawerten. Dabei steht jeder Gleitkommawert für die Konfidenzkarte der Kategorie. |
{True, False } |
True |
displayNamesLocale |
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 |
resultListener |
Legt fest, dass der Ergebnisempfänger die Segmentierungsergebnisse asynchron empfängt, wenn sich der Bildsegmenter im Modus LIVE_STREAM 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
Der Bildsegmentierungstool funktioniert mit Bildern, Videodateien und Livestreams. Die Aufgabe übernimmt die Vorverarbeitung der Dateneingabe, einschließlich Größenänderung, Drehung 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 Bildsegmenter ü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 Bildsegmenter wird die Datenvorbereitung in der Klasse ImageSegmenterHelper
über die Funktion segmentLiveStreamFrame()
ausgeführt.
Aufgabe ausführen
Je nach verwendetem Ausführungsmodus wird eine andere segment
-Funktion aufgerufen.
Die Funktion „Bildsegmentierung“ gibt die erkannten Segmentregionen im Eingabebild oder -frame zurück.
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:
- Wenn Sie den Video- oder Livestream-Modus verwenden, müssen Sie der Aufgabe „Image Segmenter“ auch den Zeitstempel des Eingabeframes angeben.
- Wenn die Ausführung im Bild- oder Videomodus erfolgt, blockiert die Aufgabe „Image Segmenter“ den aktuellen Thread, bis die Verarbeitung des Eingabebilds oder ‑frames abgeschlossen ist. Führen Sie die Verarbeitung in einem Hintergrund-Thread aus, um die Benutzeroberfläche nicht zu blockieren.
- Wenn die Ausführung im Livestream-Modus erfolgt, blockiert die Aufgabe „Bildsegmentierung“ 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
segmentAsync
aufgerufen wird, während die Aufgabe „Bildsegmentierung“ gerade einen anderen Frame verarbeitet, wird der neue Eingabeframe ignoriert.
Im Beispielcode für den Bildsegmenter sind die segment
-Funktionen in der Datei ImageSegmenterHelper.kt
definiert.
Ergebnisse verarbeiten und anzeigen
Nach der Ausführung der Inferenz gibt die Aufgabe „Bildsegmentierung“ ein ImageSegmenterResult
-Objekt zurück, das die Ergebnisse der Segmentierungsaufgabe enthält. Der Inhalt der Ausgabe hängt von der outputType
ab, die Sie beim Konfigurieren der Aufgabe festgelegt haben.
In den folgenden Abschnitten finden Sie Beispiele für die Ausgabedaten dieser Aufgabe:
Kategoriesicherheit
Die folgenden Bilder zeigen eine Visualisierung der Aufgabenausgabe für eine Kategorie-Konfidenzmaske. Die Ausgabe der Konfidenzmaske enthält Gleitkommawerte zwischen [0, 1]
.
Originalbild und Ausgabe der Kategorie-Konfidenzmaske. Quellbild aus dem Pascal VOC 2012-Dataset.
Kategoriewert
Die folgenden Bilder zeigen eine Visualisierung der Aufgabenausgabe für eine Kategoriewertmaske. Der Bereich der Kategoriemaske ist [0, 255]
und jeder Pixelwert entspricht dem Index der Gewinnerkategorie der Modellausgabe. Der Index der Gewinnerkategorie hat die höchste Punktzahl unter den Kategorien, die das Modell erkennen kann.
Originalbild und Kategoriemaskenausgabe. Quellbild aus dem Pascal VOC 2012-Dataset.