Leitfaden zum Generieren von Bildern für Android

Mit der MediaPipe Image Generator-Aufgabe können Sie Bilder auf Grundlage eines Text-Prompts generieren. Bei dieser Aufgabe wird ein Text-zu-Bild-Modell verwendet, um Bilder mithilfe von Diffusionstechniken zu generieren.

Für die Aufgabe wird ein Text-Prompt als Eingabe akzeptiert, zusammen mit einem optionalen Bedingungsbild, das das Modell erweitern und als Referenz für die Generierung verwenden kann. Mit Image Generator können auch Bilder auf Grundlage bestimmter Konzepte generiert werden, die dem Modell während des Trainings oder erneuten Trainings zur Verfügung gestellt wurden. Weitere Informationen finden Sie unter Mit LoRA anpassen.

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

Der Beispielcode für MediaPipe Tasks ist eine einfache Implementierung einer Image Generator-App für Android. Sie können die App als Ausgangspunkt für Ihre eigene Android-App verwenden oder sich daran orientieren, wenn Sie eine vorhandene App ändern. Der Beispielcode für den Image Generator ist auf GitHub verfügbar.

Code herunterladen

In der folgenden Anleitung wird beschrieben, 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 Ihre Git-Instanz so konfigurieren, dass nur die Dateien für die Beispiel-App „Image Generator“ heruntergeladen werden:
    cd mediapipe-samples
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_generation/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 entscheidenden Code für diese Beispielanwendung zur Bildgenerierung:

  • ImageGenerationHelper.kt: Initialisiert die Aufgabe und verarbeitet die Bildgenerierung.
  • DiffusionActivity.kt: Generiert Bilder, wenn keine Plug-ins oder LoRA-Gewichtungen aktiviert sind.
  • PluginActivity.kt: Implementiert die Plug-in-Modelle, mit denen Nutzer ein Bedingungsbild als Eingabe bereitstellen können.
  • LoRAWeightActivity.kt: Greift auf die LoRA-Gewichtungen zu und verarbeitet sie. Diese werden verwendet, um Foundation-Modelle anzupassen und Bilder mit bestimmten Konzepten zu generieren.

Einrichtung

In diesem Abschnitt werden die wichtigsten Schritte zum Einrichten Ihrer Entwicklungsumgebung und Ihrer Codeprojekte für die Verwendung von Image Generator beschrieben. Allgemeine Informationen zum Einrichten Ihrer Entwicklungsumgebung für die Verwendung von MediaPipe-Aufgaben, einschließlich der Anforderungen an die Plattformversion, finden Sie im Einrichtungshandbuch für Android.

Abhängigkeiten

Für die Aufgabe „Bildgenerator“ wird die com.google.mediapipe:tasks-vision-image-generator-Bibliothek verwendet. Fügen Sie diese Abhängigkeit der Datei build.gradle in Ihrer Android-App hinzu:

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

Fügen Sie für Geräte mit Android 12 (API 31) oder höher die Abhängigkeit der nativen OpenCL-Bibliothek hinzu. Weitere Informationen finden Sie in der Dokumentation zum Tag uses-native-library.

Fügen Sie der Datei AndroidManifest.xml die folgenden uses-native-library-Tags hinzu:

<uses-native-library android:name="libOpenCL.so" android:required="false" />
<uses-native-library android:name="libOpenCL-car.so" android:required="false"/>
<uses-native-library android:name="libOpenCL-pixel.so" android:required="false" />

Modell

Für die MediaPipe Image Generator-Aufgabe ist ein trainiertes Foundation Model erforderlich, das mit dieser Aufgabe kompatibel ist. Nach dem Herunterladen eines Modells müssen Sie die erforderlichen Abhängigkeiten installieren und das Modell in ein geeignetes Format konvertieren. Übertragen Sie das konvertierte Modell dann auf das Android-Gerät.

Weitere Informationen zu den verfügbaren trainierten Modellen für Image Generator finden Sie im Abschnitt „Modelle“ der Aufgabenübersicht.

Basismodell herunterladen

Für den Image Generator muss das Foundation Model dem stable-diffusion-v1-5/stable-diffusion-v1-5 EMA-only-Modellformat entsprechen, basierend auf dem folgenden Modell: stable-diffusion-v1-5/stable-diffusion-v1-5 EMA-only.

Abhängigkeiten installieren und Modell konvertieren

$ pip install torch typing_extensions numpy Pillow requests pytorch_lightning absl-py

Führen Sie das Skript convert.py aus:

$ python3 convert.py --ckpt_path <ckpt_path> --output_path <output_path>

Konvertiertes Modell auf das Gerät übertragen

Übertragen Sie den Inhalt des Ordners <output_path> auf das Android-Gerät.

$ adb shell rm -r /data/local/tmp/image_generator/ # Remove any previously loaded weights
$ adb shell mkdir -p /data/local/tmp/image_generator/
$ adb push <output_path>/. /data/local/tmp/image_generator/bins

Plug-in-Modelle herunterladen und LoRA-Gewichtungen hinzufügen (optional)

Wenn Sie ein Plug-in-Modell verwenden möchten, prüfen Sie, ob das Modell heruntergeladen werden muss. Bei Plug-ins, für die ein zusätzliches Modell erforderlich ist, müssen die Plug-in-Modelle entweder im APK gebündelt oder bei Bedarf heruntergeladen werden. Plugin-Modelle sind klein (~23 MB) und können direkt in das APK eingebunden werden. Wir empfehlen jedoch, Plug-in-Modelle bei Bedarf herunterzuladen.

Wenn Sie ein Modell mit LoRA angepasst haben, können Sie es bei Bedarf herunterladen. Weitere Informationen finden Sie unter LoRA-Gewichte.

Aufgabe erstellen

Für die MediaPipe Image Generator-Aufgabe wird die Funktion createFromOptions() verwendet, um die Aufgabe einzurichten. Die Funktion createFromOptions() akzeptiert Werte für die Konfigurationsoptionen. Weitere Informationen zu Konfigurationsoptionen finden Sie unter Konfigurationsoptionen.

Konfigurationsoptionen

Für Android-Apps stehen für diese Aufgabe die folgenden Konfigurationsoptionen zur Verfügung:

Option Beschreibung Wertebereich
imageGeneratorModelDirectory Das Verzeichnis des Bildgenerierungsmodells, in dem die Modellgewichte gespeichert werden. PATH
loraWeightsFilePath Legt den Pfad zur LoRA-Gewichtungsdatei fest. Optional und nur anwendbar, wenn das Modell mit LoRA angepasst wurde. PATH
errorListener Legt einen optionalen Fehler-Listener fest. N/A

Die Aufgabe unterstützt auch Plug-in-Modelle, sodass Nutzer Bedingungsbilder in die Aufgabeneingabe einfügen können, die das Fundamentmodell erweitern und als Referenz für die Generierung verwenden kann. Diese Bedingungsbilder können Gesichtsmerkmale, Kantenkonturen und Tiefenschätzungen sein, die das Modell als zusätzlichen Kontext und zusätzliche Informationen zum Generieren von Bildern verwendet.

Wenn Sie dem Foundation Model ein Plug-in-Modell hinzufügen, konfigurieren Sie auch die Plug-in-Optionen. Das Plug-in „Gesichtsmerkmale“ verwendet faceConditionOptions, das Plug-in „Canny Edge“ edgeConditionOptions und das Plug-in „Tiefe“ depthConditionOptions.

Optionen für Canny Edge

Konfigurieren Sie die folgenden Optionen in edgeConditionOptions.

Option Beschreibung Wertebereich Standardwert
threshold1 Erster Schwellenwert für das Hystereseverfahren. Float 100
threshold2 Zweiter Schwellenwert für das Hystereseverfahren. Float 200
apertureSize Blendenöffnung für den Sobel-Operator. Der typische Bereich liegt zwischen 3 und 7. Integer 3
l2Gradient Gibt an, ob die L2-Norm anstelle der Standard-L1-Norm verwendet wird, um die Bildgradientenmagnitude zu berechnen. BOOLEAN False
EdgePluginModelBaseOptions Das BaseOptions-Objekt, das den Pfad für das Plugin-Modell festlegt. BaseOptions Objekt N/A

Weitere Informationen zur Funktionsweise dieser Konfigurationsoptionen finden Sie unter Canny-Kantendetektor.

Optionen für Gesichts-Landmarks

Konfigurieren Sie die folgenden Optionen in faceConditionOptions.

Option Beschreibung Wertebereich Standardwert
minFaceDetectionConfidence Der Mindestkonfidenzwert, damit die Gesichtserkennung als erfolgreich gilt. Float [0.0,1.0] 0.5
minFacePresenceConfidence Der minimale Konfidenzwert für die Gesichtserkennung bei der Erkennung von Gesichts-Landmarks. Float [0.0,1.0] 0.5
faceModelBaseOptions Das BaseOptions-Objekt, mit dem der Pfad für das Modell festgelegt wird, das das Bedingungsbild erstellt. BaseOptions Objekt N/A
FacePluginModelBaseOptions Das BaseOptions-Objekt, das den Pfad für das Plugin-Modell festlegt. BaseOptions Objekt N/A

Weitere Informationen zur Funktionsweise dieser Konfigurationsoptionen finden Sie unter Face Landmarker-Aufgabe.

Tiefenoptionen

Konfigurieren Sie die folgenden Optionen in depthConditionOptions.

Option Beschreibung Wertebereich Standardwert
depthModelBaseOptions Das BaseOptions-Objekt, mit dem der Pfad für das Modell festgelegt wird, das das Bedingungsbild erstellt. BaseOptions Objekt N/A
depthPluginModelBaseOptions Das BaseOptions-Objekt, das den Pfad für das Plugin-Modell festlegt. BaseOptions Objekt N/A

Nur mit dem Basismodell erstellen

val options = ImageGeneratorOptions.builder()
    .setImageGeneratorModelDirectory(modelPath)
    .build()

imageGenerator = ImageGenerator.createFromOptions(context, options)

Plug‑ins verwenden

Wenn Sie ein optionales Plug‑in-Modell anwenden, legen Sie die Basisoptionen für das Plug‑in-Modell mit setPluginModelBaseOptions fest. Wenn für das Plug-in-Modell ein zusätzlich heruntergeladenes Modell zum Erstellen des Bedingungsbilds erforderlich ist, geben Sie den Pfad in BaseOptions an.

Gesichts-Landmark

val options = ImageGeneratorOptions.builder()
    .setImageGeneratorModelDirectory(modelPath)
    .build()

val faceModelBaseOptions = BaseOptions.builder()
    .setModelAssetPath("face_landmarker.task")
    .build()

val facePluginModelBaseOptions = BaseOptions.builder()
    .setModelAssetPath("face_landmark_plugin.tflite")
    .build()

val faceConditionOptions = FaceConditionOptions.builder()
    .setFaceModelBaseOptions(faceModelBaseOptions)
    .setPluginModelBaseOptions(facePluginModelBaseOptions)
    .setMinFaceDetectionConfidence(0.3f)
    .setMinFacePresenceConfidence(0.3f)
    .build()

val conditionOptions = ConditionOptions.builder()
    .setFaceConditionOptions(faceConditionOptions)
    .build()

imageGenerator =
    ImageGenerator.createFromOptions(context, options, conditionOptions)
    

Canny Edge

val options = ImageGeneratorOptions.builder()
    .setImageGeneratorModelDirectory(modelPath)
    .build()

val edgePluginModelBaseOptions = BaseOptions.builder()
    .setModelAssetPath("canny_edge_plugin.tflite")
    .build()

val edgeConditionOptions = EdgeConditionOptions.builder()
    .setThreshold1(100.0f)
    .setThreshold2(100.0f)
    .setApertureSize(3)
    .setL2Gradient(false)
    .setPluginModelBaseOptions(edgePluginModelBaseOptions)
    .build()

val conditionOptions = ConditionOptions.builder()
    .setEdgeConditionOptions(edgeConditionOptions)
    .build()

imageGenerator =
    ImageGenerator.createFromOptions(context, options, conditionOptions)
    

Tiefe

val options = ImageGeneratorOptions.builder()
    .setImageGeneratorModelDirectory(modelPath)
    .build()

val depthModelBaseOptions = BaseOptions.builder()
    .setModelAssetPath("depth_model.tflite")
    .build()

val depthPluginModelBaseOptions = BaseOptions.builder()
    .setModelAssetPath("depth_plugin.tflite")
    .build()

val depthConditionOptions =
    ConditionOptions.DepthConditionOptions.builder()
        .setDepthModelBaseOptions(depthModelBaseOptions)
        .setPluginModelBaseOptions(depthPluginModelBaseOptions)
        .build()

val conditionOptions = ConditionOptions.builder()
    .setDepthConditionOptions(depthConditionOptions)
    .build()

imageGenerator =
    ImageGenerator.createFromOptions(context, options, conditionOptions)
    

Inhalte mit LoRA-Gewichten erstellen

Wenn Sie LoRA-Gewichtungen einbeziehen, verwenden Sie den Parameter loraWeightsFilePath, um auf den Pfad zu verweisen.

val options = ImageGeneratorOptions.builder()
    .setLoraWeightsFilePath(weightsPath)
    .setImageGeneratorModelDirectory(modelPath)
    .build()

imageGenerator = ImageGenerator.createFromOptions(context, options)

Daten vorbereiten

Der Bildgenerator akzeptiert die folgenden Eingaben:

  • prompt (erforderlich): Der Text-Prompt, der das zu generierende Bild beschreibt.
  • iterations (erforderlich): Die Gesamtzahl der Iterationen zum Generieren des Bildes. Ein guter Ausgangspunkt ist 20.
  • seed (erforderlich): Der zufällige Startwert, der bei der Bildgenerierung verwendet wird.
  • condition image (optional): Das Bild, das das Modell als Referenz für die Generierung verwendet. Gilt nur, wenn ein Plug-in-Modell verwendet wird.
  • condition type (optional): Der Typ des mit der Aufgabe verwendeten Plug-in-Modells. Gilt nur, wenn ein Plug-in-Modell verwendet wird.

Eingaben nur mit dem Foundation Model

fun setInput(prompt: String, iteration: Int, seed: Int) {
    imageGenerator.setInputs(prompt, iteration, seed)
}

Eingaben mit Plug‑ins

Wenn Sie ein optionales Plug‑in-Modell anwenden, verwenden Sie auch den Parameter conditionType, um das Plug‑in-Modell auszuwählen, und den Parameter sourceConditionImage, um das Bedingungsbild zu generieren.

Option Beschreibung Wert
conditionType Das auf das Fundamentmodell angewendete Plug-in-Modell. {"FACE", "EDGE", "DEPTH"}
sourceConditionImage Das Quellbild, das zum Erstellen des Bedingungsbildes verwendet wurde. MPImage Objekt

Wenn Sie ein Plug-in-Modell verwenden, erstellen Sie das Bedingungsbild mit createConditionImage:

fun createConditionImage(
    inputImage: MPImage,
    conditionType: ConditionType
): Bitmap {
    val result =
        imageGenerator.createConditionImage(inputImage, conditionType)
    return BitmapExtractor.extract(result)
}

Nachdem Sie das Bedingungsbild erstellt haben, fügen Sie es zusammen mit dem Prompt, dem Seed und der Anzahl der Iterationen als Eingabe hinzu.

imageGenerator.setInputs(
    prompt,
    conditionalImage,
    conditionType,
    iteration,
    seed
)

Eingaben mit LoRA-Gewichten

Wenn Sie LoRA-Gewichtungen verwenden, muss das Token im Text-Prompt enthalten sein, wenn Sie ein Bild mit dem spezifischen Konzept generieren möchten, das durch die Gewichtungen dargestellt wird.

fun setInput(prompt: String, iteration: Int, seed: Int) {
    imageGenerator.setInputs(prompt, iteration, seed)
}

Aufgabe ausführen

Verwenden Sie die Methode generate(), um ein Bild mit den im vorherigen Abschnitt angegebenen Eingaben zu generieren. Dadurch wird ein einzelnes generiertes Bild erstellt.

Nur mit dem Foundation Model generieren

fun generate(prompt: String, iteration: Int, seed: Int): Bitmap {
    val result = imageGenerator.generate(prompt, iteration, seed)
    val bitmap = BitmapExtractor.extract(result?.generatedImage())
    return bitmap
}

Mit Plug‑ins generieren

fun generate(
    prompt: String,
    inputImage: MPImage,
    conditionType: ConditionType,
    iteration: Int,
    seed: Int
): Bitmap {
    val result = imageGenerator.generate(
        prompt,
        inputImage,
        conditionType,
        iteration,
        seed
    )
    val bitmap = BitmapExtractor.extract(result?.generatedImage())
    return bitmap
}

Mit LoRA-Gewichten generieren

Das Generieren von Bildern mit einem Modell, das mit LoRA-Gewichten angepasst wurde, ähnelt dem Prozess mit einem Standard-Fundamentmodell. Achten Sie darauf, dass das Token im Prompt enthalten ist, und führen Sie denselben Code aus.

fun generate(prompt: String, iteration: Int, seed: Int): Bitmap {
    val result = imageGenerator.generate(prompt, iteration, seed)
    val bitmap = BitmapExtractor.extract(result?.generatedImage())
    return bitmap
}

Iterative Generierung

Der Image Generator kann auch die generierten Zwischenbilder während jeder Iteration ausgeben, wie im Eingabeparameter iterations definiert. Wenn Sie diese Zwischenergebnisse aufrufen möchten, rufen Sie die Methode setInputs und dann execute() auf, um jeden Schritt auszuführen. Setzen Sie den Parameter showResult auf true, um die Zwischenergebnisse anzuzeigen.

fun execute(showResult: Boolean): Bitmap {
    val result = imageGenerator.execute(showResult)

    val bitmap =
        BitmapExtractor.extract(result.generatedImage())

    return bitmap
}

Ergebnisse verarbeiten und anzeigen

Der Image Generator gibt ein ImageGeneratorResult zurück, das das generierte Bild, einen Zeitstempel für den Zeitpunkt des Abschlusses und das bedingte Bild enthält, sofern es als Eingabe bereitgestellt wurde.

val bitmap = BitmapExtractor.extract(result.generatedImage())

Das folgende Bild wurde mit den folgenden Eingaben und nur einem Fundierungsmodell generiert.

Eingaben:

  • Prompt: „Ein bunter Cartoon-Waschbär mit einem Schlapphut mit breiter Krempe, der einen Stock hält und durch den Wald geht, animiert, Dreiviertelansicht, Gemälde“
  • Seed: 312687592
  • Iterationen: 20

Generiertes Bild:

Generiertes Bild eines Waschbären, das dem Prompt entspricht