La tarea del generador de imágenes de MediaPipe te permite generar imágenes a partir de una instrucción de texto. En esta tarea, se usa un modelo de texto a imagen para generar imágenes con técnicas de difusión.
La tarea acepta una instrucción de texto como entrada, junto con una imagen de condición opcional que el modelo puede mejorar y usar como referencia para la generación. El generador de imágenes también puede generar imágenes basadas en conceptos específicos que se proporcionan al modelo durante el entrenamiento o la nueva capacitación. Para obtener más información, consulta Cómo personalizar con LoRa.
La muestra de código que se describe en estas instrucciones está disponible en GitHub. Para obtener más información sobre las funciones, los modelos y las opciones de configuración de esta tarea, consulta la descripción general.
Ejemplo de código
El código de ejemplo de MediaPipe Tasks es una implementación básica de una app de generador de imágenes para Android. Puedes usar la app como punto de partida para tu propia app para Android o consultarla cuando modifiques una app existente. El código de ejemplo del generador de imágenes se aloja en GitHub.
Descarga el código
En las siguientes instrucciones, se muestra cómo crear una copia local del código de ejemplo con la herramienta de línea de comandos git.
Para descargar el código de ejemplo, sigue estos pasos:
- Clona el repositorio de git con el siguiente comando:
git clone https://github.com/google-ai-edge/mediapipe-samples
- De manera opcional, configura tu instancia de git para usar el control de revisión disperso, de modo que tengas solo los archivos de la app de ejemplo de Image Generator:
cd mediapipe git sparse-checkout init --cone git sparse-checkout set examples/image_generation/android
Después de crear una versión local del código de ejemplo, puedes importar el proyecto a Android Studio y ejecutar la app. Para obtener instrucciones, consulta la Guía de configuración para Android.
Componentes clave
Los siguientes archivos contienen el código fundamental de esta aplicación de ejemplo de generación de imágenes:
- ImageGenerationHelper.kt: Inicia la tarea y controla la generación de imágenes.
- DiffusionActivity.kt: Genera imágenes cuando no están habilitados los complementos ni las ponderaciones de LoRA.
- PluginActivity.kt: Implementa los modelos de complementos, lo que permite a los usuarios proporcionar una imagen de condición como entrada.
- LoRAWeightActivity.kt: Accede a los pesos de LoRA y los controla, que se usan para personalizar los modelos de base y permitirles generar imágenes de conceptos específicos.
Configuración
En esta sección, se describen los pasos clave para configurar tu entorno de desarrollo y proyectos de código específicamente para usar Image Generator. Si deseas obtener información general sobre cómo configurar tu entorno de desarrollo para usar tareas de MediaPipe, incluidos los requisitos de la versión de la plataforma, consulta la Guía de configuración para Android.
Dependencias
La tarea del generador de imágenes usa la biblioteca com.google.mediapipe:tasks-vision-image-generator
. Agrega esta dependencia al archivo build.gradle
de tu app para Android:
dependencies {
implementation 'com.google.mediapipe:tasks-vision-image-generator:latest.release'
}
En el caso de los dispositivos con Android 12 (nivel de API 31) o versiones posteriores, agrega la dependencia de la biblioteca nativa de OpenCL. Para obtener más información, consulta la documentación sobre la etiqueta uses-native-library
.
Agrega las siguientes etiquetas uses-native-library
al archivo 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" />
Modelo
La tarea del generador de imágenes de MediaPipe requiere un modelo de base entrenado que sea compatible con esta tarea. Después de descargar un modelo, instala las dependencias requeridas y conviértelo en un formato adecuado. Luego, envía el modelo convertido al dispositivo Android.
Para obtener más información sobre los modelos entrenados disponibles para Image Generator, consulta la sección Modelos de la descripción general de la tarea.
Descarga el modelo de base
El generador de imágenes requiere que el modelo de base coincida con el formato del modelo runwayml/stable-diffusion-v1-5 EMA-only
, según el siguiente modelo: runwayml/stable-diffusion-v1-5.
Instala las dependencias y convierte el modelo
$ pip install torch typing_extensions numpy Pillow requests pytorch_lightning absl-py
Ejecuta la secuencia de comandos convert.py
:
$ python3 convert.py --ckpt_path <ckpt_path> --output_path <output_path>
Envía el modelo convertido al dispositivo
Envía el contenido de la carpeta <output_path>
al dispositivo 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
Descarga modelos de complementos y agrega pesos de LoRA (opcional)
Si deseas usar un modelo de complemento, verifica si se debe descargar. En el caso de los complementos que requieren un modelo adicional, los modelos de complementos deben estar empaquetados en el APK o descargarse a pedido. Los modelos de complementos son ligeros (~23 MB) y se pueden agrupar directamente en el APK. Sin embargo, te recomendamos que descargues modelos de complementos a pedido.
Si personalizaste un modelo con LoRA, descárgalos a pedido. Para obtener más información, consulta el modelo de complemento de pesos de LoRA.
Crea la tarea
La tarea del generador de imágenes de MediaPipe usa la función createFromOptions()
para configurar la tarea. La función createFromOptions()
acepta valores para las opciones de configuración. Para obtener más información sobre las opciones de configuración, consulta Opciones de configuración.
Opciones de configuración
Esta tarea tiene las siguientes opciones de configuración para apps para Android:
Nombre de la opción | Descripción | Rango de valores |
---|---|---|
imageGeneratorModelDirectory |
Es el directorio del modelo del generador de imágenes que almacena los pesos del modelo. | PATH |
loraWeightsFilePath |
Establece la ruta de acceso al archivo de pesos de LoRA. Es opcional y solo se aplica si el modelo se personalizó con LoRA. | PATH |
errorListener |
Establece un objeto de escucha de errores opcional. | N/A |
La tarea también admite modelos de complementos, lo que permite a los usuarios incluir imágenes de condiciones en la entrada de la tarea, que el modelo de base puede aumentar y usar como referencia para la generación. Estas imágenes de condiciones pueden ser puntos de referencia faciales, contornos de bordes y estimaciones de profundidad, que el modelo usa como contexto y como información adicional para generar imágenes.
Cuando agregues un modelo de complemento al modelo de base, también configura las opciones del
complemento. El complemento de punto de referencia de rostro usa faceConditionOptions
, el complemento de borde Canny usa edgeConditionOptions
y el complemento de profundidad usa depthConditionOptions
.
Opciones de bordes definidos
Configura las siguientes opciones en edgeConditionOptions
.
Nombre de la opción | Descripción | Rango de valores | Valor predeterminado |
---|---|---|---|
threshold1 |
Primer umbral para el procedimiento de histéresis. | Float |
100 |
threshold2 |
Segundo umbral para el procedimiento de histéresis. | Float |
200 |
apertureSize |
Es el tamaño de la apertura para el operador Sobel. El rango típico es de 3 a 7. | Integer |
3 |
l2Gradient |
Indica si se usa la norma L2 para calcular la magnitud del gradiente de la imagen, en lugar de la norma L1 predeterminada. | BOOLEAN |
False |
EdgePluginModelBaseOptions |
El objeto BaseOptions que establece la ruta de acceso para el modelo del complemento |
Objeto BaseOptions |
N/A |
Para obtener más información sobre el funcionamiento de estas opciones de configuración, consulta Detector de bordes de Canny.
Opciones de puntos de referencia faciales
Configura las siguientes opciones en faceConditionOptions
.
Nombre de la opción | Descripción | Rango de valores | Valor predeterminado |
---|---|---|---|
minFaceDetectionConfidence |
La puntuación de confianza mínima para que la detección de rostros se considere exitosa. | Float [0.0,1.0] |
0.5 |
minFacePresenceConfidence |
Es la puntuación de confianza mínima de la puntuación de presencia de rostro en la detección de puntos de referencia del rostro. | Float [0.0,1.0] |
0.5 |
faceModelBaseOptions |
El objeto BaseOptions que establece la ruta de acceso para el modelo que crea la imagen de la condición |
Objeto BaseOptions |
N/A |
FacePluginModelBaseOptions |
El objeto BaseOptions que establece la ruta de acceso para el modelo del complemento |
Objeto BaseOptions |
N/A |
Para obtener más información sobre el funcionamiento de estas opciones de configuración, consulta la tarea de Face Landmarker.
Opciones de profundidad
Configura las siguientes opciones en depthConditionOptions
.
Nombre de la opción | Descripción | Rango de valores | Valor predeterminado |
---|---|---|---|
depthModelBaseOptions |
El objeto BaseOptions que establece la ruta de acceso para el modelo que crea la imagen de la condición |
Objeto BaseOptions |
N/A |
depthPluginModelBaseOptions |
El objeto BaseOptions que establece la ruta de acceso para el modelo del complemento |
Objeto BaseOptions |
N/A |
Crea solo con el modelo de base
val options = ImageGeneratorOptions.builder()
.setImageGeneratorModelDirectory(modelPath)
.build()
imageGenerator = ImageGenerator.createFromOptions(context, options)
Crea con complementos
Si aplicas un modelo de complemento opcional, configura las opciones básicas del
modelo de complemento con setPluginModelBaseOptions
. Si el modelo del complemento requiere un
modelo descargado adicional para crear la imagen de la condición, especifica la ruta de acceso en
BaseOptions
.
Punto de referencia facial
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)
Borde Canny
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)
Profundidad
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)
Crea con pesos de LoRA
Si incluyes pesos de LoRA, usa el parámetro loraWeightsFilePath
para apuntar a la ubicación de la ruta.
val options = ImageGeneratorOptions.builder()
.setLoraWeightsFilePath(weightsPath)
.setImageGeneratorModelDirectory(modelPath)
.build()
imageGenerator = ImageGenerator.createFromOptions(context, options)
Preparar los datos
El generador de imágenes acepta las siguientes entradas:
- prompt (obligatorio): Es la instrucción de texto que describe la imagen que se generará.
- iterations (obligatorio): Es la cantidad total de iteraciones para generar la imagen. Un buen punto de partida es 20.
- seed (obligatorio): Es el valor inicial aleatorio que se usa durante la generación de imágenes.
- imagen de condición (opcional): Es la imagen que el modelo usa como referencia para la generación. Solo se aplica cuando se usa un modelo de complemento.
- type of condition (opcional): Es el tipo de modelo de complemento que se usa con la tarea. Solo se aplica cuando se usa un modelo de complemento.
Entradas con solo el modelo de base
fun setInput(prompt: String, iteration: Int, seed: Int) {
imageGenerator.setInputs(prompt, iteration, seed)
}
Entradas con complementos
Si aplicas un modelo de complemento opcional, usa también el parámetro conditionType
para elegir el modelo de complemento y el parámetro sourceConditionImage
para generar la imagen de la condición.
Nombre de la opción | Descripción | Valor |
---|---|---|
conditionType |
Es el modelo del complemento aplicado al modelo de base. | {"FACE", "EDGE", "DEPTH"} |
sourceConditionImage |
Es la imagen de origen que se usa para crear la imagen de condición. | Objeto MPImage |
Si usas un modelo de complemento, usa createConditionImage
para crear la imagen de condición:
fun createConditionImage(
inputImage: MPImage,
conditionType: ConditionType
): Bitmap {
val result =
imageGenerator.createConditionImage(inputImage, conditionType)
return BitmapExtractor.extract(result)
}
Después de crear la imagen de condición, inclúyela como entrada junto con la instrucción, la inicialización y la cantidad de iteraciones.
imageGenerator.setInputs(
prompt,
conditionalImage,
conditionType,
iteration,
seed
)
Entradas con pesos de LoRA
Si usas pesos de LoRA, asegúrate de que el token esté en la instrucción de texto si deseas generar una imagen con el concepto específico que representan los pesos.
fun setInput(prompt: String, iteration: Int, seed: Int) {
imageGenerator.setInputs(prompt, iteration, seed)
}
Ejecuta la tarea
Usa el método generate()
para generar una imagen con las entradas proporcionadas en la sección anterior. Esto produce una sola imagen generada.
Genera solo con el modelo de base
fun generate(prompt: String, iteration: Int, seed: Int): Bitmap {
val result = imageGenerator.generate(prompt, iteration, seed)
val bitmap = BitmapExtractor.extract(result?.generatedImage())
return bitmap
}
Generar con complementos
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
}
Genera con pesos de LoRA
El proceso de generar imágenes con un modelo personalizado con pesos de LoRA es similar al proceso con un modelo de base estándar. Asegúrate de que el token se incluya en la instrucción y ejecuta el mismo código.
fun generate(prompt: String, iteration: Int, seed: Int): Bitmap {
val result = imageGenerator.generate(prompt, iteration, seed)
val bitmap = BitmapExtractor.extract(result?.generatedImage())
return bitmap
}
Generación iterativa
El generador de imágenes también puede generar las imágenes intermedias generadas durante cada
iteración, como se define en el parámetro de entrada iterations
. Para ver estos
resultados intermedios, llama al método setInputs
y, luego, llama a execute()
para ejecutar
cada paso. Establece el parámetro showResult
en true
para mostrar los resultados
intermedios.
fun execute(showResult: Boolean): Bitmap {
val result = imageGenerator.execute(showResult)
val bitmap =
BitmapExtractor.extract(result.generatedImage())
return bitmap
}
Cómo controlar y mostrar los resultados
El generador de imágenes muestra un ImageGeneratorResult
, que incluye la imagen generada, una marca de tiempo del momento de la finalización y la imagen condicional si se proporcionó una como entrada.
val bitmap = BitmapExtractor.extract(result.generatedImage())
La siguiente imagen se generó a partir de las siguientes entradas, con solo un modelo de base.
Entradas:
- Consigna: “Un mapache de caricatura colorido que lleva un sombrero de ala ancha y floja y camina por el bosque, animado, vista en tres cuartos, pintura”
- Valor inicial: 312687592
- Iteraciones: 20
Imagen generada: