1. Einführung
Was ist MediaPipe?
Mit MediaPipe Solutions können Sie Lösungen für maschinelles Lernen (ML) auf Ihre Anwendungen anwenden. Er bietet ein Framework für die Konfiguration vorgefertigter Verarbeitungspipelines, die den Nutzern eine sofortige, ansprechende und nützliche Ausgabe liefern. Viele dieser Lösungen lassen sich sogar mit dem MediaPipe Model Maker anpassen, um die Standardmodelle zu aktualisieren.
Die Text-zu-Bild-Generierung ist eine von mehreren ML-Aufgaben, die MediaPipe Solutions zu bieten hat.
In diesem Codelab beginnen Sie mit einer überwiegend der reinen Android-App und durchlaufen dann mehrere Schritte, bis Sie neue Bilder direkt auf Ihrem Android-Gerät generieren können.
Lerninhalte
- Implementieren von Text-zu-Bild-Generierung, die lokal in einer Android-App ausgeführt wird, mithilfe von MediaPipe Tasks implementieren
Voraussetzungen
- Eine installierte Version von Android Studio. Dieses Codelab wurde mit Android Studio Giraffe geschrieben und getestet.
- Ein Android-Gerät mit mindestens 8 GB RAM.
- Grundkenntnisse der Android-Entwicklung und die Fähigkeit, vorgefertigte Python-Skripts auszuführen.
2. MediaPipe Tasks zur Android-App hinzufügen
Android-Starter-App herunterladen
Dieses Codelab beginnt mit einem vorgefertigten Beispiel, das aus der UI besteht, die für eine grundlegende Version der Bildgenerierung verwendet wird. Eine Start-App findest du im offiziellen MediaPipe Samples-Repository. Klonen Sie das Repository oder laden Sie die ZIP-Datei herunter, indem Sie auf „Code“ klicken. ZIP herunterladen.
App in Android Studio importieren
- Öffnen Sie Android Studio.
- Wählen Sie auf dem Bildschirm Willkommen bei Android Studio oben rechts Öffnen aus.
- Gehen Sie zum Speicherort, an dem Sie das Repository geklont oder heruntergeladen haben, und öffnen Sie das Verzeichnis codelabs/image_generation_basic/android/start.
- Zu diesem Zeitpunkt sollte die App nicht kompiliert werden, da die MediaPipe Tasks-Abhängigkeit noch nicht enthalten ist.
Sie reparieren die App und bringen sie zum Laufen, indem Sie die Datei build.gradle aufrufen und nach unten zu // Step 1 - Add Abhängigkeit scrollen. Füge dann die folgende Zeile ein und klicke dann auf die Schaltfläche Jetzt synchronisieren, die im Banner oben in Android Studio erscheint.
// Step 1 - Add dependency
implementation 'com.google.mediapipe:tasks-vision-image-generator:latest.release'
Überprüfe nach Abschluss der Synchronisierung, ob alles korrekt geöffnet und installiert wurde, indem du oben rechts in Android Studio auf den grünen Pfeil Ausführen ( ) klickst. Die App sollte auf einem Bildschirm mit zwei Optionsfeldern und der Schaltfläche INITIALIZE angezeigt werden. Wenn Sie auf diese Schaltfläche klicken, sollten Sie sofort zu einer separaten Benutzeroberfläche weitergeleitet werden, die aus einem Text-Prompt und anderen Optionen neben der Schaltfläche GENERIEREN besteht.
Leider ist das ungefähr der Umfang der Starter-App. Sehen wir uns nun an, wie du diese App fertigstellen und neue Bilder auf deinem Gerät generieren kannst.
3. Image Generator einrichten
In diesem Beispiel erfolgt der Großteil der Bildgenerierung in der Datei ImageGenerationHelper.kt. Wenn Sie diese Datei öffnen, sehen Sie oben in der Klasse eine Variable namens imageGenerator. Dies ist das Task-Objekt, das die schwierigen Aufgaben in Ihrer App zur Bildgenerierung übernimmt.
Direkt unter diesem Objekt sehen Sie eine Funktion namens initialImageGenerator() mit dem folgenden Kommentar: // Step 2 - Initialisieren des Image-Generators. Hier initialisieren Sie das ImageGenerator-Objekt. Ersetzen Sie den Funktionstext durch den folgenden Code, um den Pfad des Bildgenerierungsmodells festzulegen und das ImageGenerator-Objekt zu initialisieren:
// Step 2 - initialize the image generator
val options = ImageGeneratorOptions.builder()
.setImageGeneratorModelDirectory(modelPath)
.build()
imageGenerator = ImageGenerator.createFromOptions(context, options)
Darunter sehen Sie eine weitere Funktion namens setInput(). Dafür sind drei Parameter zulässig: ein prompt-String, der zur Definition des generierten Bildes verwendet wird, die Anzahl der Iterationen, die die Aufgabe durchlaufen soll, während das neue Bild generiert wird, und ein seed-Wert, mit dem neue Versionen eines Bildes basierend auf demselben Prompt erstellt werden können. Dabei wird dasselbe Bild generiert, wenn derselbe Seed verwendet wird. Der Zweck dieser Funktion besteht darin, diese Anfangsparameter für den Bildgenerator festzulegen, wenn Sie versuchen, ein Bild zu erstellen, das Zwischenschritte anzeigt.
Ersetzen Sie nun den Text von „setInput()“ (wo Sie den Kommentar sehen // Step 3 - Eingaben akzeptieren) durch folgende Zeile:
// Step 3 - accept inputs
imageGenerator.setInputs(prompt, iteration, seed)
In den nächsten beiden Schritten findet die Generierung statt. Die Funktion „generate()“ akzeptiert dieselben Eingaben wie „setInput“, erstellt aber ein Bild als One-Shot-Aufruf, der keine Bilder von Zwischenschritten zurückgibt. Sie können den Hauptteil dieser Funktion (mit dem Kommentar // Step 4 -generate without show without shows iterations) durch Folgendes ersetzen:
// Step 4 - generate without showing iterations
val result = imageGenerator.generate(prompt, iteration, seed)
val bitmap = BitmapExtractor.extract(result?.generatedImage())
return bitmap
Beachten Sie, dass diese Aufgabe synchron ausgeführt wird. Daher müssen Sie die Funktion von einem Hintergrundthread aus aufrufen. Etwas später in diesem Codelab erfahren Sie mehr darüber.
Der letzte Schritt in dieser Datei ist das Ausfüllen der Funktionexecute() (bezeichnet als Schritt 5). Dabei wird ein Parameter akzeptiert, der angibt, ob für den einzelnen Schritt der Generierung, der mit der Funktion ImageGeneratorexecute() ausgeführt wird, ein Zwischenbild zurückgegeben werden soll. Ersetzen Sie den Funktionstext durch diesen Code:
// Step 5 - generate with iterations
val result = imageGenerator.execute(showResult)
if (result == null || result.generatedImage() == null) {
return Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888)
.apply {
val canvas = Canvas(this)
val paint = Paint()
paint.color = Color.WHITE
canvas.drawPaint(paint)
}
}
val bitmap =
BitmapExtractor.extract(result.generatedImage())
return bitmap
Das war's mit der Hilfsdatei. Im nächsten Abschnitt füllen Sie die ViewModel-Datei aus, die die Logik für dieses Beispiel verarbeitet.
4. Die App an einem Ort
Die Datei MainViewModel verarbeitet UI-Status und andere Logik für diese Beispiel-App. Bitte öffne sie jetzt.
Am Anfang der Datei sollten Sie den Kommentar sehen // Step 6 - set model path. Hier teilen Sie Ihrer App mit, wo sie die Modelldateien findet, die für die Bildgenerierung erforderlich sind. In diesem Beispiel legen Sie den Wert auf /data/local/tmp/image_generator/bins/ fest.
// Step 6 - set model path
private val MODEL_PATH = "/data/local/tmp/image_generator/bins/"
Scrollen Sie von dort nach unten zur Funktion „generateImage()“. Am Ende dieser Funktion sehen Sie sowohl Schritt 7 als auch Schritt 8. Anhand dieses Schritts werden Bilder mit einer oder keiner zurückgegebenen Iteration generiert. Da diese beiden Vorgänge synchron ausgeführt werden, sind sie in einer Koroutine zusammengefasst. Ersetzen Sie zuerst // Schritt 7 - Generieren ohne Anzeige von Iterationen durch diesen Codeblock, um „generate()“ aus der Datei ImageGenerationHelper aufzurufen und dann den UI-Status zu aktualisieren.
// Step 7 - Generate without showing iterations
val result = helper?.generate(prompt, iteration, seed)
_uiState.update {
it.copy(outputBitmap = result)
}
Schritt 8 wird etwas kniffliger. Da die Funktion run() nur einen Schritt anstelle aller Schritte für die Bildgenerierung ausführt, müssen Sie jeden Schritt einzeln über eine Schleife aufrufen. Außerdem müssen Sie festlegen, ob der aktuelle Schritt für den Nutzer angezeigt werden soll. Schließlich aktualisieren Sie den Status der Benutzeroberfläche, wenn die aktuelle Iteration angezeigt werden soll. All das ist jetzt möglich.
// Step 8 - Generate with showing iterations
helper?.setInput(prompt, iteration, seed)
for (step in 0 until iteration) {
isDisplayStep =
(displayIteration > 0 && ((step + 1) % displayIteration == 0))
val result = helper?.execute(isDisplayStep)
if (isDisplayStep) {
_uiState.update {
it.copy(
outputBitmap = result,
generatingMessage = "Generating... (${step + 1}/$iteration)",
)
}
}
}
Jetzt sollten Sie in der Lage sein, Ihre App zu installieren, den Bildgenerator zu initialisieren und dann mithilfe eines Text-Prompts ein neues Bild zu erstellen.
... aber jetzt stürzt die App ab, wenn Sie versuchen, den Bildgenerator zu initialisieren. Der Grund dafür ist, dass Sie Ihre Modelldateien auf Ihr Gerät kopieren müssen. In diesem Abschnitt der offiziellen Dokumentation finden Sie aktuelle Informationen zu funktionstüchtigen Drittanbietermodellen, die Sie für diese MediaPipe-Aufgabe konvertieren und auf Ihr Gerät kopieren.
Sie können nicht nur Dateien direkt auf Ihr Entwicklungsgerät kopieren, sondern auch Firebase Storage so einrichten, dass die erforderlichen Dateien zur Laufzeit direkt auf das Gerät des Nutzers heruntergeladen werden.
5. Anwendung bereitstellen und testen
Danach sollten Sie eine funktionierende App haben, die Text-Prompts akzeptieren und neue Bilder vollständig auf dem Gerät generieren kann. Stellen Sie die App nun auf einem physischen Android-Gerät bereit, um sie zu testen. Denken Sie jedoch daran, dass Sie dies mit einem Gerät mit mindestens 8 GB Arbeitsspeicher versuchen sollten.
- Klicken Sie in der Android Studio-Symbolleiste auf „Ausführen“ (
), um die App auszuführen.
- Wählen Sie die Art der Generierungsschritte aus (endgültig oder mit Iterationen) und klicken Sie dann auf die Schaltfläche INITIALIZE.
- Legen Sie auf dem nächsten Bildschirm die gewünschten Eigenschaften fest und klicken Sie auf die Schaltfläche GENERIEREN, um zu sehen, was das Tool bietet.
6. Glückwunsch!
Geschafft! In diesem Codelab haben Sie gelernt, wie Sie einer Android-App die On-Device-Text-zu-Bild-Generierung hinzufügen.
Nächste Schritte
Die Aufgabe zur Bildgenerierung hat noch mehr Möglichkeiten:
- Sie können ein Basisbild verwenden, um generierte Bilder mithilfe von Plug-ins zu strukturieren, oder Ihre eigenen zusätzlichen LoRA-Gewichtungen mit Vertex AI trainieren.
- Verwende Firebase Storage, um Modelldateien auf deinem Gerät abzurufen, ohne das ADB-Tool verwenden zu müssen.
Wir freuen uns schon darauf, all die coolen Dinge zu sehen, die du mit dieser experimentellen Aufgabe machst, und halten Ausschau nach weiteren Codelabs und Inhalten des MediaPipe-Teams!