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.

Die Aufgabe akzeptiert einen Text-Prompt als Eingabe sowie ein optionales Bedingungsbild, das das Modell erweitern und als Referenz für die Generierung verwenden kann. Image Generator kann auch Bilder auf Grundlage bestimmter Konzepte generieren, die dem Modell während des Trainings oder des erneuten Trainings zur Verfügung gestellt wurden. Weitere Informationen finden Sie unter Mit LoRA anpassen.

Der in dieser Anleitung beschriebene Beispielcode 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 sie als Referenz nutzen, wenn Sie eine vorhandene App ändern. Der Beispiel Code für Image Generator wird auf GitHub gehostet.

Code herunterladen

In der folgenden Anleitung wird beschrieben, wie Sie mit dem Befehlszeilentool „git“ eine lokale Kopie des Beispiel codes 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 sie Sparse Checkout verwendet, damit Sie nur die Dateien für die Image Generator-Beispiel-App haben:
    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 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 Plug‑ins oder LoRA-Gewichtungen nicht aktiviert sind.
  • PluginActivity.kt: Implementiert die Plug‑in-Modelle, mit denen Nutzer ein Bedingungs bild als Eingabe bereitstellen können.
  • LoRAWeightActivity.kt: Greift auf die LoRA-Gewichtungen zu und verarbeitet sie. Diese werden verwendet, um Basismodelle anzupassen und Bilder bestimmter Konzepte zu generieren.

Einrichtung

In diesem Abschnitt werden die wichtigsten Schritte zum Einrichten Ihrer Entwicklungsumgebung und Ihrer Codeprojekte speziell 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 Einrichtungsleitfaden für Android.

Abhängigkeiten

Für die Image Generator-Aufgabe wird die Bibliothek com.google.mediapipe:tasks-vision-image-generator 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 uses-native-library Tag.

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 Basismodell erforderlich, das mit dieser Aufgabe kompatibel ist. Nachdem Sie ein Modell heruntergeladen haben, installieren Sie die erforderlichen Abhängigkeiten und konvertieren Sie das Modell in ein geeignetes Format. Ü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 in der Aufgaben übersicht.

Basismodell herunterladen

Für Image Generator muss das Basismodell dem stable-diffusion-v1-5/stable-diffusion-v1-5 EMA-only Modellformat entsprechen, das auf dem folgenden Modell basiert: 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 convert.py Skript 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. Für Plug‑ins, die ein zusätzliches Modell erfordern, müssen die Plug‑in-Modelle entweder im APK gebündelt oder bei Bedarf heruntergeladen werden. Plug‑in-Modelle sind ressourcenarm (~23 MB) und können direkt im APK gebündelt werden. Wir empfehlen jedoch, Plug‑in-Modelle bei Bedarf herunterzuladen.

Wenn Sie ein Modell mit LoRA angepasst haben, laden Sie es bei Bedarf herunter. Weitere Informationen finden Sie unter Plug‑in-Modell für LoRA-Gewichtungen.

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 den Konfigurationsoptionen finden Sie unter Konfigurations optionen.

Konfigurationsoptionen

Für diese Aufgabe sind die folgenden Konfigurationsoptionen für Android-Apps verfügbar:

Option Beschreibung Wertebereich
imageGeneratorModelDirectory Das Verzeichnis des Image Generator-Modells, in dem die Modellgewichtungen gespeichert sind. PATH
loraWeightsFilePath Legt den Pfad zur Datei mit den LoRA-Gewichtungen fest. Optional und nur anwendbar, wenn das Modell mit LoRA angepasst wurde. PATH
errorListener Legt einen optionalen Fehlerlistener fest. N/A

Die Aufgabe unterstützt auch Plug‑in-Modelle, mit denen Nutzer Bedingungsbilder in die Aufgabeneingabe einbeziehen können. Das Basismodell kann diese erweitern und als Referenz für die Generierung verwenden. Diese Bedingungsbilder können Gesichts-Landmarks, Kantenumrisse und Tiefenschätzungen sein, die das Modell als zusätzlichen Kontext und Informationen zum Generieren von Bildern verwendet.

Wenn Sie dem Basismodell ein Plug‑in-Modell hinzufügen, konfigurieren Sie auch die Plug‑in-Optionen. Das Plug‑in für Gesichts-Landmarks verwendet faceConditionOptions, das Plug‑in für Canny-Kanten edgeConditionOptions und das Plug‑in für die Tiefe depthConditionOptions.

Optionen für Canny-Kanten

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 zur Berechnung der Bildgradientengröße anstelle der Standard-L1-Norm verwendet wird. BOOLEAN False
EdgePluginModelBaseOptions Das -Objekt, das den Pfad für das Plug‑in-Modell festlegt.BaseOptions 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 für die Gesichtserkennung, damit sie als erfolgreich gilt. Float [0.0,1.0] 0.5
minFacePresenceConfidence Der Mindestkonfidenzwert für die Gesichtserkennung bei der Erkennung von Gesichts-Landmarks. Float [0.0,1.0] 0.5
faceModelBaseOptions Das -Objekt, das den Pfad für das Modell festlegt, mit dem das Bedingungsbild erstellt wird.BaseOptions BaseOptions-Objekt N/A
FacePluginModelBaseOptions Das -Objekt, das den Pfad für das Plug‑in-Modell festlegt.BaseOptions BaseOptions-Objekt N/A

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

Optionen für die Tiefe

Konfigurieren Sie die folgenden Optionen in depthConditionOptions.

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

Nur mit dem Basismodell erstellen

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

imageGenerator = ImageGenerator.createFromOptions(context, options)

Mit Plug‑ins erstellen

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ätzliches heruntergeladenes Modell erforderlich ist, um das Bedingungsbild zu erstellen, geben Sie den Pfad in BaseOptions an.

Gesichts-Landmarks

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-Kanten

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)
    

Mit LoRA-Gewichtungen 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

Image Generator 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 sind 20.
  • seed (erforderlich): Der Zufalls-Seed, der bei der Bildgenerierung verwendet wird.
  • condition image (optional): Das Bild, das das Modell als Referenz für die Generierung verwendet. Nur anwendbar, wenn ein Plug‑in-Modell verwendet wird.
  • condition type (optional): Der Typ des Plug‑in-Modells, das mit der Aufgabe verwendet wird. Nur anwendbar, wenn ein Plug‑in-Modell verwendet wird.

Eingaben nur mit dem Basismodell

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 Plug‑in-Modell, das auf das Basismodell angewendet wird. {"FACE", "EDGE", "DEPTH"}
sourceConditionImage Das Quellbild, das zum Erstellen des Bedingungsbildes verwendet wird. 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-Gewichtungen

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. So wird ein einzelnes generiertes Bild erstellt.

Nur mit dem Basismodell erstellen

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 erstellen

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-Gewichtungen erstellen

Der Prozess zum Generieren von Bildern mit einem Modell, das mit LoRA-Gewichtungen angepasst wurde, ähnelt dem Prozess mit einem Standard-Basismodell. 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

Image Generator kann auch die generierten Zwischenbilder während jeder Iteration ausgeben, wie im Eingabeparameter iterations definiert. Rufen Sie die Methode setInputs auf, um diese Zwischenergebnisse anzuzeigen, und rufen Sie 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

Image Generator gibt ein ImageGeneratorResult zurück, das das generierte Bild, einen Zeitstempel des Abschlusszeitpunkts und das Bedingungsbild enthält, falls eines als Eingabe bereitgestellt wurde.

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

Das folgende Bild wurde aus den folgenden Eingaben generiert, wobei nur ein Basismodell verwendet wurde.

Eingaben :

  • Prompt: „Ein bunter Cartoon-Waschbär mit einem schlaffen Hut mit breiter Krempe der mit einem Stock durch den Wald geht, animiert, Dreiviertelansicht, Gemälde“
  • Seed: 312687592
  • Iterations: 20

Generiertes Bild :

Generiertes Bild eines Waschbären, das dem Prompt entspricht