Przewodnik po generowaniu obrazów w przypadku Androida

.

Zadanie Generatora obrazów MediaPipe pozwala generować obrazy na podstawie promptu tekstowego. Ten korzysta z modelu „tekst na obraz” do generowania obrazów przy użyciu technik dyfuzji.

Zadanie akceptuje prompt tekstowy jako dane wejściowe oraz opcjonalny obraz warunku który model może rozszerzyć i wykorzystać jako wzorzec do generowania. Generator obrazów może też generować obrazy na podstawie określonych koncepcji podanych modelowi i przekształcanie. Więcej informacji znajdziesz w artykule na temat dostosowywania za pomocą: (LoRA).

Przykładowy kod opisany w tych instrukcjach jest dostępny na GitHub Więcej informacji o funkcjach, modelach i opcjach konfiguracji zapoznaj się z Przeglądem.

Przykładowy kod

Przykładowy kod MediaPipe Tasks to podstawowa implementacja generatora obrazów na Androida. Możesz użyć tej aplikacji jako punktu wyjścia dla własnego Androida aplikacji ani odwołania się do niej podczas modyfikowania istniejącej aplikacji. Generator obrazów – przykład na serwerze GitHub

Pobieranie kodu

Poniżej znajdziesz instrukcje tworzenia lokalnej kopii przykładu. za pomocą narzędzia wiersza poleceń git.

Aby pobrać przykładowy kod:

  1. Sklonuj repozytorium git za pomocą tego polecenia:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. Opcjonalnie możesz skonfigurować instancję git tak, aby wykorzystywała rozproszony proces płatności, aby tylko pliki przykładowej aplikacji Generator obrazów:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_generator/android
    

Po utworzeniu lokalnej wersji przykładowego kodu możesz zaimportować projekt w Android Studio i uruchom aplikację. Odpowiednie instrukcje znajdziesz w Przewodniku po konfiguracji na urządzeniu z Androidem.

Kluczowe elementy

Poniższe pliki zawierają kluczowy kod tego przykładowego generowania obrazów aplikacja:

  • ImageGenerationHelper.kt: Inicjuje zadanie i obsługuje generowanie obrazów.
  • DiffusionActivity.kt: Generuje obrazy, gdy wtyczki lub wagi LoRA nie są włączone.
  • PluginActivity.kt: implementuje modele wtyczek, które umożliwiają użytkownikom podawanie warunku obraz jako dane wejściowe.
  • LoRAWeightActivity.kt: Uzyskuje dostęp do wag LoRA i obsługuje je, które służą do dostosowywania podstaw które pozwalają generować obrazy konkretnych koncepcji.

Konfiguracja

W tej sekcji opisujemy najważniejsze czynności związane z konfigurowaniem środowiska programistycznego oraz w projektach kodu, w których używa się Generatora obrazów. Ogólne informacje na temat: skonfigurować środowisko programistyczne do korzystania z zadań MediaPipe, w tym wymagań wersji platformy znajdziesz w przewodniku konfiguracji dla na urządzeniu z Androidem.

Zależności

Zadanie Generator obrazów wykorzystuje Biblioteka com.google.mediapipe:tasks-vision-image-generator. Dodaj tę zależność do pliku build.gradle aplikacji na Androida:

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

W przypadku urządzeń z Androidem 12 (API 31) lub nowszym dodaj natywną bibliotekę OpenCL zależności od funkcji AndroidManifest.xml. Aby dowiedzieć się więcej, zapoznaj się z dokumentacją na uses-native-library .

Niektóre urządzenia z Androidem mogą wymagać dodatkowych bibliotek:

<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" />

Model

Zadanie Generatora obrazów MediaPipe wymaga wytrenowanego modelu podstawowego, który jest zgodny w tym zadaniu. Po pobraniu modelu zainstaluj wymagane zależności i przekonwertować model na odpowiedni format. Następnie przekaż przekonwertowany plik z telefonem z Androidem.

Więcej informacji o dostępnych wytrenowanych modelach na potrzeby Generatora obrazów znajdziesz w zadaniu zapoznaj się z sekcją Modele.

Pobierz model podstawowy

Generator obrazów wymaga, aby model podstawowy pasował do modelu Format modelu runwayml/stable-diffusion-v1-5 EMA-only, na podstawie tego model: runwayml/stable-diffusion-v1-5.

Instalowanie zależności i konwertowanie modelu

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

Użycie convert.py skrypt:

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

Przekaż przekonwertowany model na urządzenie

Roześlij zawartość folderu <output_path> na urządzenie z Androidem.

$ 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

Pobierz modele wtyczek i dodaj wagi LoRA (opcjonalnie)

Jeśli zamierzasz używać modelu wtyczki, sprawdź, czy model musi zostać pobrany. W przypadku wtyczek, które wymagają dodatkowego modelu, wtyczka modele muszą być połączone w pliku APK lub pobierane na żądanie. Modele wtyczek są niewielkie (ok. 23 MB) i można je połączyć bezpośrednio w pliku APK. Możemy jednak zalecamy pobieranie modeli wtyczek na żądanie.

Jeśli dostosowałeś model za pomocą LoRA, pobierać je na żądanie. Więcej więcej informacji znajdziesz w artykule o wagach modelu wtyczki LoRA.

Tworzenie zadania

Zadanie Generator obrazów MediaPipe używa funkcji createFromOptions() do skonfigurowania zadanie. Funkcja createFromOptions() akceptuje wartości konfiguracji . Więcej informacji o opcjach konfiguracji znajdziesz w sekcji Konfiguracja .

Opcje konfiguracji

To zadanie zawiera te opcje konfiguracji aplikacji na Androida:

Nazwa opcji Opis Zakres wartości
imageGeneratorModelDirectory Katalog modeli generatora obrazów, w którym są przechowywane wagi modelu. PATH
loraWeightsFilePath Ustawia ścieżkę do pliku z wagami LoRA. Opcjonalny i ma zastosowanie tylko wtedy, model został dostosowany przy użyciu LoRA. PATH
errorListener Ustawia opcjonalny detektor błędów. N/A

Zadanie obsługuje też modele wtyczek, które pozwalają użytkownikom dołączać obrazy warunków w danych wejściowych zadania, które model podstawowy może rozszerzać i wykorzystywać jako odwołanie. z pokolenia na pokolenie. Mogą to być punkty orientacyjne, kontury krawędzi szczegółowe oszacowania, które model wykorzystuje jako dodatkowy kontekst i informacje w celu do generowania obrazów.

Podczas dodawania modelu wtyczki do modelu podstawowego skonfiguruj też wtyczkę . Wtyczka do punktów orientacyjnych twarzy korzysta z krawędzi Canny (faceConditionOptions) Wtyczka używa edgeConditionOptions, a wtyczka Depth – depthConditionOptions

Opcje Canny Edge

Skonfiguruj następujące opcje na stronie edgeConditionOptions.

Nazwa opcji Opis Zakres wartości Wartość domyślna
threshold1 Pierwszy próg procedury histerezy. Float 100
threshold2 Drugi próg procedury histerezy. Float 200
apertureSize Rozmiar przysłony operatora Sobela. Typowy zakres to 3–7. Integer 3
l2Gradient Czy norma L2 jest używana do obliczania wielkości gradientu obrazu, zamiast domyślnej normy L1. BOOLEAN False
EdgePluginModelBaseOptions Obiekt BaseOptions, który ustawia ścieżkę dla modelu wtyczki. BaseOptions obiekt N/A

Więcej informacji o tym, jak działają te opcje konfiguracji, znajdziesz w artykule Detektor krawędzi Canny.

Opcje punktu orientacyjnego twarzy

Skonfiguruj następujące opcje na stronie faceConditionOptions.

Nazwa opcji Opis Zakres wartości Wartość domyślna
minFaceDetectionConfidence Minimalny poziom ufności wymagany do wykrywania twarzy została uznana za udaną. Float [0.0,1.0] 0.5
minFacePresenceConfidence Minimalny wskaźnik ufności obecności twarzy punkty w wykrywaniu punktów orientacyjnych twarzy. Float [0.0,1.0] 0.5
faceModelBaseOptions Obiekt BaseOptions, który ustawia ścieżkę dla modelu, który tworzy obraz warunku. BaseOptions obiekt N/A
FacePluginModelBaseOptions Obiekt BaseOptions, który ustawia ścieżkę dla modelu wtyczki. BaseOptions obiekt N/A

Więcej informacji o działaniu tych opcji konfiguracji znajdziesz tutaj: Zadanie oznaczenia twarzy.

Opcje głębi

Skonfiguruj następujące opcje na stronie depthConditionOptions.

Nazwa opcji Opis Zakres wartości Wartość domyślna
depthModelBaseOptions Obiekt BaseOptions, który ustawia ścieżkę dla modelu, który tworzy obraz warunku. BaseOptions obiekt N/A
depthPluginModelBaseOptions Obiekt BaseOptions, który ustawia ścieżkę dla modelu wtyczki. BaseOptions obiekt N/A

Utwórz tylko z modelem podstawowym

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

imageGenerator = ImageGenerator.createFromOptions(context, options)

Twórz za pomocą wtyczek

Jeśli stosujesz opcjonalny model wtyczki, ustaw opcje podstawowe dla modelu model wtyczki z parametrem setPluginModelBaseOptions. Jeśli model wtyczki wymaga parametru dodatkowo pobrany model, aby utworzyć obraz warunku, podaj ścieżkę w BaseOptions

Punkt orientacyjny twarzy

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)
    

Głębokość

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)
    

Utwórz z wagami LoRA

Jeśli uwzględniasz wagi LoRA, użyj parametru loraWeightsFilePath, aby: wskaż lokalizację ścieżki.

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

imageGenerator = ImageGenerator.createFromOptions(context, options)

Przygotuj dane

Generator obrazów akceptuje te dane wejściowe:

  • prompt (wymagany): prompt tekstowy opisujący obraz do wygenerowania.
  • iteracje (wymagane): łączna liczba iteracji użytych do wygenerowania obrazu. O dobry punkt wyjścia to 20.
  • seed (wymagany): losowe dane wyjściowe używane podczas generowania obrazu.
  • condition image [obraz warunku] (opcjonalny): obraz używany przez model jako odniesienie. i generowanie treści. Ma zastosowanie tylko wtedy, gdy korzystasz z modelu wtyczki.
  • condition type (typ warunku) (opcjonalny): typ modelu wtyczki używany w zadaniu. Ma zastosowanie tylko wtedy, gdy korzystasz z modelu wtyczki.

Dane wejściowe tylko z modelem podstawowym

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

Wejścia z wtyczkami

Jeśli stosujesz opcjonalny model wtyczki, użyj też conditionType i parametru sourceConditionImage, aby wybrać model wtyczki aby wygenerować obraz warunku.

Nazwa opcji Opis Wartość
conditionType Model wtyczki został zastosowany do modelu podstawowego. {"FACE", "EDGE", "DEPTH"}
sourceConditionImage Obraz źródłowy użyty do utworzenia obrazu warunku. MPImage obiekt

Jeśli korzystasz z modelu wtyczki, użyj zasady createConditionImage, aby utworzyć model obraz warunku:

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

Po utworzeniu obrazu warunku dodaj go jako dane wejściowe razem z promptów, wartości wyjściowej i liczby iteracji.

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

Dane wejściowe z wagami LoRA

Jeśli używasz wag LoRA, sprawdź, czy token znajduje się w prompcie tekstowym, jeśli Generowanie obrazu przedstawiającego konkretną koncepcję przedstawianą przez ciężary.

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

Uruchamianie zadania

Wygeneruj obraz za pomocą metody generate(), korzystając z danych wejściowych poprzedniej sekcji. Powoduje to wygenerowanie pojedynczego obrazu.

Generuj tylko na podstawie modelu podstawowego

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

Generowanie za pomocą wtyczek

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
}

Wygeneruj z wagami LoRA

Proces generowania obrazów za pomocą modelu dostosowanego za pomocą wagi LoRA jest podobnie jak w przypadku standardowego modelu podstawowego. Sprawdź, czy token są uwzględnione w prompcie i uruchamiać ten sam kod.

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

Generowanie iteracyjne

Generator obrazów może też wyświetlić wygenerowane obrazy pośrednie podczas każdego zgodnie z definicją w parametrze wejściowym iterations. Aby je wyświetlić wyników pośrednich, wywołaj metodę setInputs, a następnie wywołaj execute(), aby uruchomić każdego kroku. Ustaw parametr showResult na true, aby wyświetlić średni wyników.

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

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

    return bitmap
}

Obsługa i wyświetlanie wyników

Generator obrazów zwraca pole ImageGeneratorResult, które zawiera wygenerowany obraz, sygnaturę czasową ukończenia oraz obraz warunkowy, jeśli zostanie została podana.

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

Następujący obraz został wygenerowany na podstawie poniższych danych wejściowych przy użyciu tylko model podstawowy.

Dane wejściowe:

  • Prompt: „kolorowy kreskówkowy szop w kapeluszu z szerokim rondem i obcisłym rondem. z kijem idącym przez las, animowany obraz w trzech czwartych, obraz”
  • Materiał wyjściowy: 312687592
  • Iteracje: 20

Wygenerowany obraz: