Anleitung zum Einbetten von Bildern für Android

Mit der Aufgabe „MediaPipe Image Embedder“ können Sie Bilddaten in eine numerische Darstellung konvertieren um ML-bezogene Bildverarbeitungsaufgaben zu erledigen, z. B. den Vergleich der Ähnlichkeit von zwei Bildern. In dieser Anleitung erfahren Sie, wie Sie die Bildeinbetter mit Android-Apps

Weitere Informationen zu Funktionen, Modellen und Konfigurationsoptionen Sehen Sie sich die Übersicht an.

Codebeispiel

Der MediaPipe Tasks-Beispielcode ist eine einfache Implementierung eines Image Embedders. für Android. In diesem Beispiel wird die Kamera eines physischen Android-Geräts verwendet, um Bilder kontinuierlich einbetten und die Einbettung auch für gespeicherte Bilddateien ausführen auf dem Gerät.

Du kannst die App als Ausgangspunkt für deine eigene Android-App verwenden oder darauf verweisen wenn Sie eine vorhandene App ändern. Der Beispielcode für das Einbinden von Bildern wird auf GitHub

Code herunterladen

In der folgenden Anleitung erfahren Sie, wie Sie eine lokale Kopie des Beispiels erstellen. mit dem Befehlszeilentool git erstellen.

<ph type="x-smartling-placeholder">

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, damit Sie nur die Dateien für die Beispielanwendung zum Einbinden von Bildern:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_embedder/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 hierzu finden Sie im Einrichtungsleitfaden für Android-Geräte

Schlüsselkomponenten

Die folgenden Dateien enthalten den wichtigen Code für dieses Beispiel für den Bildeinbetter. Anwendung:

  • ImageEmbedderHelper.kt: Initialisiert den Bildeinbetter und verwaltet das Modell und den Bevollmächtigten Auswahl.
  • MainActivity.kt: Implementiert die Anwendung und stellt die Komponenten der Benutzeroberfläche zusammen.

Einrichtung

In diesem Abschnitt werden die wichtigsten Schritte zum Einrichten Ihrer Entwicklungsumgebung und für die Verwendung von Bildeinbetter programmieren. Allgemeine Informationen zum Einrichten der Entwicklungsumgebung für die Verwendung von MediaPipe-Aufgaben, einschließlich Plattformversion finden Sie im Einrichtungsleitfaden für Android-Geräte

<ph type="x-smartling-placeholder">

Abhängigkeiten

Der Bildeinbetter verwendet die com.google.mediapipe:tasks-vision-Bibliothek. Dieses Element hinzufügen Abhängigkeit zur Datei build.gradle Ihres Android-App-Entwicklungsprojekts. 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 Embedder“ ist ein trainiertes Modell erforderlich, . Weitere Informationen zu verfügbaren trainierten Modellen für den Bildeinbetter findest du 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

Geben Sie den Pfad des Modells innerhalb des Parameters ModelAssetPath an. Im Beispielcode haben, wird das Modell in der setupImageEmbedder()-Funktion im ImageEmbedderHelper.kt Datei:

Verwenden Sie die Methode BaseOptions.Builder.setModelAssetPath(), um den Pfad anzugeben. die vom Modell verwendet werden. Diese Methode wird im Codebeispiel in den .

Aufgabe erstellen

Zum Erstellen der Aufgabe können Sie die Funktion createFromOptions verwenden. Die Die Funktion createFromOptions akzeptiert Konfigurationsoptionen, um den Einbettungscode festzulegen Optionen. Weitere Informationen zu Konfigurationsoptionen finden Sie unter Konfiguration Übersicht.

Bei der Aufgabe „Bild einbetten“ werden drei Arten von Eingabedaten unterstützt: Standbilder, Videodateien, und Live-Videostreams. Sie müssen den Laufmodus für beim Erstellen der Aufgabe Ihren Eingabedatentyp. Wählen Sie die Registerkarte für um zu sehen, wie die Aufgabe erstellt und eine Inferenz ausgeführt wird.

Bild

ImageEmbedderOptions options =
  ImageEmbedderOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setQuantize(true)
    .setRunningMode(RunningMode.IMAGE)
    .build();
imageEmbedder = ImageEmbedder.createFromOptions(context, options);
    

Video

ImageEmbedderOptions options =
  ImageEmbedderOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setQuantize(true)
    .setRunningMode(RunningMode.VIDEO)
    .build();
imageEmbedder = ImageEmbedder.createFromOptions(context, options);
    

Livestream

ImageEmbedderOptions options =
  ImageEmbedderOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setQuantize(true)
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setResultListener((result, inputImage) -> {
         // Process the embedding result here.
    })
    .build();
imageEmbedder = ImageEmbedder.createFromOptions(context, options);
    

Die Beispielcode-Implementierung ermöglicht es dem Nutzer, zwischen den Verarbeitungsvorgängen Modi. Dieser Ansatz macht den Code zur Aufgabenerstellung komplizierter und ist möglicherweise nicht für Ihren Anwendungsfall geeignet. Sie sehen diesen Code in der setupImageEmbedder() in der Spalte ImageEmbedderHelper.kt -Datei.

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
l2_normalize Gibt an, ob der zurückgegebene Featurevektor mit der L2-Norm normalisiert werden soll. Verwenden Sie diese Option nur, wenn das Modell noch keine native L2_NORMALIZATION TFLite Op. In den meisten Fällen ist dies bereits der Fall und Die L2-Normalisierung wird somit über TFLite-Inferenz ohne Notwendigkeit erreicht. für diese Option. Boolean False
quantize Ob die zurückgegebene Einbettung in Byte quantisiert werden soll mithilfe von eine skalare Quantisierung. Bei Einbettungen wird implizit angenommen, Daher hat jede Dimension garantiert einen Wert in [-1,0; 1,0]. Verwenden Sie die Option „l2_normalize“ verwenden, wenn dies nicht der Fall ist. Boolean False
resultListener Legt den Ergebnis-Listener fest, der die Einbettungsergebnisse empfangen soll asynchron, wenn sich der Bildeinbetter im Livestream 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 Bildeinbetter 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 Aufgabe „Bild einbetten“.

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 wird die Datenvorbereitung in der ImageEmbedderHelper.kt -Datei.

Aufgabe ausführen

Sie können die Funktion embed für Ihren Laufmodus aufrufen, um Rückschlüsse. Die Image Embedder API gibt die Einbettungsvektoren für die Eingabe zurück. Bild oder Rahmen.

Bild

ImageEmbedderResult embedderResult = imageEmbedder.embed(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.
ImageEmbedderResult embedderResult =
    imageEmbedder.embedForVideo(image, frameTimestampMs);
    

Livestream


// Run inference on the frame. The embedding results will be available
// via the `resultListener` provided in the `ImageEmbedderOptions` when
// the image embedder was created.
imageEmbedder.embedAsync(image, frameTimestampMs);
    

Wichtige Hinweise:

  • Im Video- oder Livestreammodus musst du außerdem den Zeitstempel des Eingabe-Frames für die Aufgabe „Bildeinbetter“ angeben.
  • Im Bild- oder Videomodus wird die Aufgabe „Bild einbetten“ den aktuellen Thread blockieren, bis die Verarbeitung des Eingabebildes abgeschlossen ist, Frame. Um das Blockieren des aktuellen Threads zu vermeiden, führen Sie die Verarbeitung in einem im Hintergrund.
  • Im Livestreammodus blockiert die Aufgabe „Bild einbetten“ nicht im aktuellen Thread zu lesen, aber sofort wieder zurück. Das Ergebnis wird aufgerufen. Listener mit dem Erkennungsergebnis, sobald er die Verarbeitung eines Eingabe-Frame. Ob die Funktion embedAsync aufgerufen wird, wenn der Bildeinbetter die Aufgabe mit der Verarbeitung eines anderen Frames beschäftigt ist, ignoriert die Aufgabe den neuen Eingabeframe.

Im Beispielcode wird die Funktion embed im ImageEmbedderHelper.kt -Datei.

Ergebnisse verarbeiten und anzeigen

Beim Ausführen einer Inferenz gibt die Aufgabe zum Einbinden von Bildern ein ImageEmbedderResult zurück. das eine Liste von Einbettungen (entweder Gleitkomma- oder skalar quantisiert) für das Eingabebild.

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

ImageEmbedderResult:
  Embedding #0 (sole embedding head):
    float_embedding: {0.0, 0.0, ..., 0.0, 1.0, 0.0, 0.0, 2.0}
    head_index: 0

Dieses Ergebnis wurde durch Einbetten des folgenden Bildes erhalten:

Sie können die Ähnlichkeit von zwei Einbettungen mithilfe der Funktion ImageEmbedder.cosineSimilarity. Im folgenden Code finden Sie eine Beispiel.

// Compute cosine similarity.
double similarity = ImageEmbedder.cosineSimilarity(
  result.embeddingResult().embeddings().get(0),
  otherResult.embeddingResult().embeddings().get(0));