1. Wprowadzenie
Czym jest MediaPipe?
MediaPipe Solutions umożliwia stosowanie w aplikacjach rozwiązań wykorzystujących uczenie maszynowe. Zapewnia on platformę do konfigurowania gotowych potoków przetwarzania, które dostarczają użytkownikom natychmiastowe, angażujące i przydatne wyniki. Wiele z tych rozwiązań możesz dostosować za pomocą MediaPipe Model Maker, aby zaktualizować modele domyślne.
Generowanie obrazów z tekstu to jedno z kilku zadań uczenia maszynowego, które oferuje MediaPipe Solutions.
W tym ćwiczeniu zaczniesz od prawie pustej aplikacji na Androida, a potem przejdziesz przez kilka etapów, aż będziesz w stanie generować nowe obrazy bezpośrednio na urządzeniu z Androidem.
Czego się nauczysz
- Jak wdrożyć zamianę tekstu na obraz działającą lokalnie w aplikacji na Androida za pomocą zadań MediaPipe.
Czego potrzebujesz
- Zainstalowana wersja Android Studio (ten codelab został napisany i przetestowany w Android Studio Giraffe).
- Urządzenie z Androidem z co najmniej 8 GB pamięci RAM.
- Podstawowa wiedza na temat programowania na Androida i umiejętność uruchamiania gotowego skryptu w Pythonie.
2. Dodawanie zadań MediaPipe do aplikacji na Androida
Pobieranie aplikacji startowej na Androida
W tym ćwiczeniu w Codelabs zaczniemy od gotowego przykładu składającego się z interfejsu, który będzie używany w podstawowej wersji generowania obrazów. Aplikację startową znajdziesz w oficjalnym repozytorium przykładów MediaPipe tutaj. Sklonuj repozytorium lub pobierz plik ZIP, klikając kolejno Code (Kod) > Download ZIP (Pobierz ZIP).
Importowanie aplikacji do Android Studio
- Otwórz Android Studio.
- Na ekranie Witamy w Android Studio w prawym górnym rogu kliknij Otwórz.

- Przejdź do miejsca, w którym sklonowano lub pobrano repozytorium, i otwórz katalog codelabs/image_generation_basic/android/start.
- Na tym etapie aplikacja nie powinna się kompilować, ponieważ nie uwzględniono jeszcze zależności MediaPipe Tasks.
Aby naprawić aplikację i ją uruchomić, otwórz plik build.gradle i przewiń go do sekcji // Step 1 - Add dependency (Krok 1 – dodaj zależność). Następnie dodaj ten wiersz i kliknij przycisk Synchronizuj teraz, który pojawi się na banerze u góry Androida Studio.
// Step 1 - Add dependency
implementation 'com.google.mediapipe:tasks-vision-image-generator:latest.release'
Po zakończeniu synchronizacji sprawdź, czy wszystko zostało otwarte i zainstalowane prawidłowo. W tym celu kliknij zieloną strzałkę Uruchom (
) w prawym górnym rogu Android Studio. Aplikacja powinna otworzyć się na ekranie z 2 przyciskami opcji i przyciskiem oznaczonym INITIALIZE (INICJALIZUJ). Po kliknięciu tego przycisku powinna się od razu otworzyć osobna sekcja interfejsu z promptem tekstowym i innymi opcjami oraz przyciskiem WYGENERUJ.

To niestety wszystko, co oferuje aplikacja startowa, więc czas, aby dowiedzieć się, jak ją dokończyć i zacząć generować nowe obrazy na urządzeniu.
3. Konfigurowanie generatora obrazów
W tym przykładzie większość pracy związanej z generowaniem obrazów będzie wykonywana w pliku ImageGenerationHelper.kt. Po otwarciu tego pliku u góry klasy zobaczysz zmienną o nazwie imageGenerator. Jest to obiekt Task, który wykona najcięższą pracę w aplikacji do generowania obrazów.
Tuż pod tym obiektem zobaczysz funkcję initializeImageGenerator() z tym komentarzem: // Step 2 - initialize the image generator. Jak można się domyślać, to tutaj zainicjujesz obiekt ImageGenerator. Zastąp treść tej funkcji poniższym kodem, aby ustawić ścieżkę modelu generowania obrazów i zainicjować obiekt ImageGenerator:
// Step 2 - initialize the image generator
val options = ImageGeneratorOptions.builder()
.setImageGeneratorModelDirectory(modelPath)
.build()
imageGenerator = ImageGenerator.createFromOptions(context, options)
Poniżej znajduje się kolejna funkcja o nazwie setInput(). Przyjmuje ona 3 parametry: ciąg znaków prompt, który będzie używany do definiowania generowanego obrazu, liczbę iteracji, które zadanie powinno wykonać podczas generowania nowego obrazu, oraz wartość seed, która może być używana do tworzenia nowych wersji obrazu na podstawie tego samego prompta podczas generowania tego samego obrazu, gdy używana jest ta sama wartość seed. Celem tej funkcji jest ustawienie początkowych parametrów generatora obrazów, gdy próbujesz utworzyć obraz, który wyświetla kroki pośrednie.
Zastąp treść funkcji setInput() (w której zobaczysz komentarz // Step 3 - accept inputs) tym wierszem:
// Step 3 - accept inputs
imageGenerator.setInputs(prompt, iteration, seed)
W kolejnych 2 krokach następuje generowanie. Funkcja generate() przyjmuje te same dane wejściowe co setInput, ale tworzy obraz w ramach jednorazowego wywołania, które nie zwraca żadnych obrazów z etapów pośrednich. Możesz zastąpić treść tej funkcji (wraz z komentarzem // Step 4 - generate without showing iterations) tym kodem:
// Step 4 - generate without showing iterations
val result = imageGenerator.generate(prompt, iteration, seed)
val bitmap = BitmapExtractor.extract(result?.generatedImage())
return bitmap
Warto wiedzieć, że to zadanie jest wykonywane synchronicznie, więc musisz wywołać funkcję z wątku w tle. Więcej informacji na ten temat znajdziesz w dalszej części tego ćwiczenia.
Ostatnim krokiem w tym pliku będzie wypełnienie funkcji execute() (oznaczonej jako Krok 5). Funkcja ta przyjmuje parametr, który określa, czy ma zwracać obraz pośredni dla pojedynczego kroku generowania, który zostanie wykonany za pomocą funkcji execute() ImageGenerator. Zastąp treść funkcji tym kodem:
// 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
To wszystko, co musisz wiedzieć o pliku pomocniczym. W następnej sekcji wypełnisz plik ViewModel, który obsługuje logikę tego przykładu.
4. Łączenie aplikacji
Plik MainViewModel będzie obsługiwać stany interfejsu i inną logikę związaną z tą przykładową aplikacją. Otwórz go teraz.
U góry pliku powinien znajdować się komentarz // Step 6 - set model path. W tym miejscu podaj aplikacji ścieżkę do plików modelu niezbędnych do generowania obrazów. W tym przykładzie ustaw wartość na /data/local/tmp/image_generator/bins/.
// Step 6 - set model path
private val MODEL_PATH = "/data/local/tmp/image_generator/bins/"
Następnie przewiń w dół do funkcji generateImage(). U dołu tej funkcji zobaczysz kroki 7 i 8, które służą do generowania obrazów odpowiednio ze zwróconymi iteracjami lub bez nich. Obie te operacje są wykonywane synchronicznie, więc zauważysz, że są one zawarte w współprogramie. Zacznij od zastąpienia wiersza // Step 7 - Generate without showing iterations tym blokiem kodu, aby wywołać funkcję generate() z pliku ImageGenerationHelper, a następnie zaktualizować stan interfejsu.
// Step 7 - Generate without showing iterations
val result = helper?.generate(prompt, iteration, seed)
_uiState.update {
it.copy(outputBitmap = result)
}
Krok 8 jest nieco bardziej skomplikowany. Funkcja execute() wykonuje tylko jeden krok zamiast wszystkich kroków generowania obrazu, więc musisz wywołać każdy krok osobno w pętli. Musisz też określić, czy bieżący krok powinien być widoczny dla użytkownika. Na koniec zaktualizujesz stan interfejsu, jeśli bieżąca iteracja ma być wyświetlana. Wszystko to możesz zrobić już teraz.
// 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)",
)
}
}
}
W tym momencie powinna być możliwość zainstalowania aplikacji, zainicjowania generatora obrazów, a następnie utworzenia nowego obrazu na podstawie prompta tekstowego.
… z tym że teraz aplikacja ulega awarii, gdy próbujesz zainicjować generator obrazów. Dzieje się tak, ponieważ musisz skopiować pliki modelu na urządzenie. Najnowsze informacje o sprawdzonych modelach innych firm, ich konwertowaniu na potrzeby tego zadania MediaPipe i kopiowaniu na urządzenie znajdziesz w tej sekcji oficjalnej dokumentacji.
Oprócz kopiowania plików bezpośrednio na urządzenie deweloperskie możesz też skonfigurować Pamięć Firebase tak, aby pobierał niezbędne pliki bezpośrednio na urządzenie użytkownika w czasie działania aplikacji.
5. Wdrażanie i testowanie aplikacji
Po wykonaniu tych czynności powinna działać aplikacja, która akceptuje prompt tekstowy i generuje nowe obrazy w całości na urządzeniu. Wdróż aplikację na fizycznym urządzeniu z Androidem, aby ją przetestować. Pamiętaj jednak, że warto to zrobić na urządzeniu z co najmniej 8 GB pamięci.
- Aby uruchomić aplikację, na pasku narzędzi Android Studio kliknij Uruchom (
). - Wybierz typ kroków generowania (końcowe lub z iteracjami), a następnie naciśnij przycisk INITIALIZE (INICJALIZUJ).
- Na następnym ekranie ustaw dowolne właściwości i kliknij przycisk WYGENERUJ, aby zobaczyć, co zaproponuje narzędzie.

6. Gratulacje!
Udało się! W tym ćwiczeniu z programowania dowiesz się, jak dodać do aplikacji na Androida funkcję zamiany tekstu na obraz na urządzeniu.
Dalsze kroki
Zadanie generowania obrazów ma więcej funkcji, m.in.:
- używać obrazu bazowego do strukturyzowania generowanych obrazów za pomocą wtyczek lub trenować własne dodatkowe wagi LoRA za pomocą Vertex AI.
- Użyj Pamięci Firebase, aby pobrać pliki modelu na urządzenie bez konieczności korzystania z narzędzia adb.
Z niecierpliwością czekamy na wszystkie ciekawe rzeczy, które stworzysz dzięki temu eksperymentalnemu zadaniu. Wypatruj kolejnych ćwiczeń w Codelabs i treści od zespołu MediaPipe.