Руководство по созданию изображений для Android

Задача MediaPipe Image Generator позволяет создавать изображения на основе текстового запроса. В этой задаче используется модель преобразования текста в изображение для генерации изображений с применением методов диффузии.

Задача принимает на вход текстовую подсказку, а также необязательное изображение состояния, которое модель может дополнить и использовать в качестве эталона для генерации. Генератор изображений также может генерировать изображения на основе конкретных концепций, предоставленных модели во время обучения или переобучения. Для получения дополнительной информации см. раздел «Настройка с помощью LoRA» .

Пример кода, описанный в этих инструкциях, доступен на GitHub . Более подробную информацию о возможностях, моделях и параметрах конфигурации этой задачи см. в разделе «Обзор» .

Пример кода

Пример кода MediaPipe Tasks представляет собой базовую реализацию приложения для генерации изображений для Android. Вы можете использовать это приложение в качестве отправной точки для своего собственного приложения Android или ссылаться на него при модификации существующего приложения. Пример кода для генерации изображений размещен на GitHub .

Скачать код

Следующие инструкции показывают, как создать локальную копию примера кода с помощью инструмента командной строки git .

Чтобы скачать пример кода:

  1. Клонируйте репозиторий Git, используя следующую команду:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. При желании настройте свой экземпляр Git на использование разреженного извлечения (sparse checkout), чтобы у вас были только файлы для примера приложения «Генератор изображений»:
    cd mediapipe-samples
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_generation/android
    

После создания локальной версии примера кода вы можете импортировать проект в Android Studio и запустить приложение. Инструкции см. в Руководстве по настройке для Android .

Ключевые компоненты

Следующие файлы содержат важнейший код для данного примера приложения по генерации изображений:

  • ImageGenerationHelper.kt : Инициализирует задачу и обрабатывает генерацию изображений.
  • DiffusionActivity.kt : Генерирует изображения, когда плагины или веса LoRA не включены.
  • PluginActivity.kt : Реализует модели плагинов, позволяющие пользователям указывать изображение состояния в качестве входных данных.
  • LoRAWeightActivity.kt : Обеспечивает доступ к весам LoRA и управляет ими, используя их для настройки базовых моделей и генерации изображений конкретных концепций.

Настраивать

В этом разделе описаны ключевые шаги по настройке среды разработки и проектов кода специально для использования Image Generator. Общую информацию о настройке среды разработки для использования задач MediaPipe, включая требования к версии платформы, см. в руководстве по настройке для Android .

Зависимости

Задача «Генератор изображений» использует библиотеку com.google.mediapipe:tasks-vision-image-generator . Добавьте эту зависимость в файл build.gradle вашего Android-приложения:

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

Для устройств с Android 12 (API 31) или выше добавьте зависимость от нативной библиотеки OpenCL. Для получения дополнительной информации см. документацию по тегу uses-native-library .

Добавьте следующие теги uses-native-library в файл AndroidManifest.xml :

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

Модель

Для выполнения задачи MediaPipe Image Generator требуется обученная базовая модель, совместимая с данной задачей. После загрузки модели установите необходимые зависимости и преобразуйте модель в подходящий формат. Затем загрузите преобразованную модель на устройство Android.

Для получения более подробной информации о доступных обученных моделях для генератора изображений см. раздел «Модели» в обзоре задачи.

Скачать базовую модель

Генератор изображений требует, чтобы базовая модель соответствовала формату модели stable-diffusion-v1-5/stable-diffusion-v1-5 EMA-only , основанному на следующей модели: stable-diffusion-v1-5/stable-diffusion-v1-5 EMA-only .

Установите зависимости и преобразуйте модель.

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

Запустите скрипт convert.py :

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

Передайте преобразованную модель на устройство.

Загрузите содержимое папки <output_path> на устройство Android.

$ 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

Загрузите модели плагина и добавьте веса LoRA (необязательно).

Если вы планируете использовать модель плагина , проверьте, нужно ли её скачивать. Для плагинов, требующих дополнительной модели, модели плагинов должны быть либо включены в APK-файл, либо загружены по запросу. Модели плагинов имеют небольшой размер (~23 МБ) и могут быть включены непосредственно в APK-файл. Однако мы рекомендуем загружать модели плагинов по запросу.

Если вы настроили модель с помощью LoRA , загрузите их по запросу. Для получения дополнительной информации см. раздел «Модель плагина весов LoRA».

Создайте задачу

Задача MediaPipe Image Generator использует функцию createFromOptions() для настройки задачи. Функция createFromOptions() принимает значения для параметров конфигурации. Дополнительную информацию о параметрах конфигурации см. в разделе «Параметры конфигурации» .

Параметры конфигурации

Данная задача имеет следующие параметры конфигурации для приложений Android:

Название варианта Описание Диапазон значений
imageGeneratorModelDirectory Каталог модели генератора изображений, в котором хранятся веса модели. PATH
loraWeightsFilePath Задает путь к файлу весов LoRA. Необязательный параметр, применим только в том случае, если модель была настроена с использованием LoRA. PATH
errorListener Устанавливает необязательный обработчик ошибок. N/A

Задача также поддерживает модели-плагины, что позволяет пользователям включать изображения состояния в качестве входных данных задачи, которые базовая модель может дополнять и использовать в качестве эталона для генерации. Эти изображения состояния могут представлять собой лицевые ориентиры, контуры краев и оценки глубины, которые модель использует в качестве дополнительного контекста и информации для генерации изображений.

При добавлении модели плагина к базовой модели также необходимо настроить параметры плагина. Плагин Face landmark использует faceConditionOptions , плагин Canny edge использует edgeConditionOptions , а плагин Depth использует depthConditionOptions .

Умные варианты с выгодными предложениями

Настройте следующие параметры в edgeConditionOptions .

Название варианта Описание Диапазон значений Значение по умолчанию
threshold1 Первый пороговый уровень для процедуры гистерезиса. Float 100
threshold2 Второй пороговый уровень для процедуры гистерезиса. Float 200
apertureSize Размер диафрагмы для оператора Собеля. Типичный диапазон — от 3 до 7. Integer 3
l2Gradient Используется ли норма L2 для вычисления величины градиента изображения вместо нормы L1 по умолчанию. BOOLEAN False
EdgePluginModelBaseOptions Объект BaseOptions , задающий путь к модели плагина. Объект BaseOptions N/A

Для получения более подробной информации о работе этих параметров конфигурации см. раздел «Детектор границ Кэнни» .

Варианты расположения лицевых ориентиров

Настройте следующие параметры в faceConditionOptions .

Название варианта Описание Диапазон значений Значение по умолчанию
minFaceDetectionConfidence Минимальный показатель достоверности, при котором распознавание лица считается успешным. Float [0.0,1.0] 0.5
minFacePresenceConfidence Минимальный показатель достоверности наличия лица при определении лицевых ориентиров. Float [0.0,1.0] 0.5
faceModelBaseOptions Объект BaseOptions задает путь к модели, создающей изображение состояния. Объект BaseOptions N/A
FacePluginModelBaseOptions Объект BaseOptions , задающий путь к модели плагина. Объект BaseOptions N/A

Для получения более подробной информации о работе этих параметров конфигурации см. задачу «Ориентир на лице» .

Варианты глубины

Настройте следующие параметры в файле depthConditionOptions .

Название варианта Описание Диапазон значений Значение по умолчанию
depthModelBaseOptions Объект BaseOptions задает путь к модели, создающей изображение состояния. Объект BaseOptions N/A
depthPluginModelBaseOptions Объект BaseOptions , задающий путь к модели плагина. Объект BaseOptions N/A

Создать, используя только базовую модель.

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

imageGenerator = ImageGenerator.createFromOptions(context, options)

Создание с помощью плагинов

Если вы используете необязательную модель плагина, задайте базовые параметры для модели плагина с помощью setPluginModelBaseOptions . Если для создания образа условия модели плагина требуется дополнительная загруженная модель, укажите путь в BaseOptions .

Ориентир на лице

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)
    

Кэнни Эдж

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)
    

Глубина

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)
    

Создание с использованием весов LoRA

Если вы используете весовые коэффициенты LoRA, укажите путь к файлу с данными в формате loraWeightsFilePath .

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

imageGenerator = ImageGenerator.createFromOptions(context, options)

Подготовка данных

Генератор изображений принимает следующие входные данные:

  • Подсказка (обязательно): Текстовая подсказка, описывающая изображение, которое необходимо сгенерировать.
  • Количество итераций (обязательно): Общее количество итераций для генерации изображения. Хорошей отправной точкой является 20.
  • Начальное значение генератора случайных чисел (обязательно): начальное значение генератора случайных чисел, используемое при генерации изображения.
  • Изображение условия (необязательно): Изображение, которое модель использует в качестве эталона для генерации. Применимо только при использовании модели-плагина.
  • Тип условия (необязательно): Тип модели плагина, используемой для задачи. Применимо только при использовании модели плагина.

Входные данные, содержащие только базовую модель.

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

Входные данные с плагинами

Если вы используете необязательную модель плагина, также используйте параметр conditionType для выбора модели плагина и параметр sourceConditionImage для генерации изображения состояния.

Название варианта Описание Ценить
conditionType Модель плагина, примененная к базовой модели. {"FACE", "EDGE", "DEPTH"}
sourceConditionImage Исходное изображение, использованное для создания изображения состояния. Объект MPImage

Если вы используете модель плагина, воспользуйтесь функцией createConditionImage для создания изображения состояния:

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

После создания изображения условия, включите его в качестве входных данных вместе с подсказкой, начальным значением и количеством итераций.

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

Входные данные с весами LoRA

Если вы используете веса LoRA, убедитесь, что токен присутствует в текстовом поле, если вы намереваетесь сгенерировать изображение с конкретной концепцией, представленной этими весами.

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

Запустите задачу

Используйте метод generate() для генерации изображения, используя входные данные, предоставленные в предыдущем разделе. В результате будет сгенерировано одно изображение.

Сгенерировать, используя только базовую модель.

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

Генерировать с помощью плагинов

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
}

Генерация с использованием весов LoRA

Процесс генерации изображений с помощью модели, настроенной с использованием весов LoRA, аналогичен процессу с использованием стандартной базовой модели. Убедитесь, что токен указан в подсказке, и запустите тот же код.

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

Итеративная генерация

Генератор изображений также может выводить сгенерированные промежуточные изображения на каждой итерации, как определено в параметре ввода iterations . Чтобы просмотреть эти промежуточные результаты, вызовите метод setInputs , а затем вызовите execute() для выполнения каждого шага. Установите параметр showResult в true , чтобы отобразить промежуточные результаты.

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

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

    return bitmap
}

Обработка и отображение результатов

Генератор изображений возвращает объект ImageGeneratorResult , который включает в себя сгенерированное изображение, метку времени завершения и условное изображение, если оно было предоставлено в качестве входных данных.

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

Представленное ниже изображение было сгенерировано на основе следующих входных данных с использованием только базовой модели.

Входные данные:

  • Задание : «Красочный мультяшный енот в широкополой шляпе с мягкими полями, держащий палку, идёт по лесу, анимированный, вид в три четверти, картина»
  • Семя : 312687592
  • Количество итераций : 20

Сгенерированное изображение:

Сгенерированное изображение енота, соответствующее заданию.