Guia de geração de imagens para Android

A tarefa MediaPipe Image Generator permite gerar imagens com base em um comando de texto. Essa tarefa usa um modelo de texto para imagem para gerar imagens usando técnicas de difusão.

A tarefa aceita um comando de texto como entrada, além de uma imagem de condição opcional que o modelo pode aumentar e usar como referência para geração. O Gerador de imagens também pode criar imagens com base em conceitos específicos fornecidos ao modelo durante o treinamento ou o re-treinamento. Para mais informações, consulte personalizar com LoRA.

O exemplo de código descrito nestas instruções está disponível no GitHub. Para mais informações sobre os recursos, modelos e opções de configuração dessa tarefa, consulte a Visão geral.

Exemplo de código

O exemplo de código do MediaPipe Tasks é uma implementação básica de um app Image Generator para Android. Você pode usar o app como ponto de partida para seu próprio app Android ou consultá-lo ao modificar um app existente. O código de exemplo do Gerador de imagens está hospedado no GitHub.

Fazer o download do código

As instruções a seguir mostram como criar uma cópia local do código de exemplo usando a ferramenta de linha de comando git.

Para fazer o download do código de exemplo:

  1. Clone o repositório git usando o comando a seguir:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. Se quiser, configure sua instância do git para usar o sparse checkout. Assim, você terá apenas os arquivos do app de exemplo do Gerador de imagens:
    cd mediapipe-samples
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_generation/android
    

Depois de criar uma versão local do código de exemplo, importe o projeto para o Android Studio e execute o app. Para instruções, consulte o Guia de configuração para Android.

Principais componentes

Os arquivos a seguir contêm o código crucial para este aplicativo de exemplo de geração de imagens:

  • ImageGenerationHelper.kt: inicializa a tarefa e processa a geração de imagens.
  • DiffusionActivity.kt: gera imagens quando os plug-ins ou pesos de LoRA não estão ativados.
  • PluginActivity.kt: implementa os modelos de plug-in, permitindo que os usuários forneçam uma imagem de condição como entrada.
  • LoRAWeightActivity.kt: acessa e processa os pesos LoRA, que são usados para personalizar modelos de fundação e permitir que eles gerem imagens de conceitos específicos.

Configuração

Esta seção descreve as principais etapas para configurar seu ambiente de desenvolvimento e projetos de código especificamente para usar o Gerador de imagens. Para informações gerais sobre como configurar seu ambiente de desenvolvimento para usar as tarefas do MediaPipe, incluindo requisitos de versão da plataforma, consulte o Guia de configuração para Android.

Dependências

A tarefa "Gerador de imagens" usa a biblioteca com.google.mediapipe:tasks-vision-image-generator. Adicione esta dependência ao arquivo build.gradle do seu app Android:

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

Para dispositivos com Android 12 (API 31) ou mais recente, adicione a dependência da biblioteca nativa OpenCL. Para mais informações, consulte a documentação sobre a tag uses-native-library.

Adicione as seguintes tags uses-native-library ao arquivo 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

A tarefa do gerador de imagens do MediaPipe exige um modelo de base treinado compatível com ela. Depois de baixar um modelo, instale as dependências necessárias e converta o modelo em um formato adequado. Em seguida, envie o modelo convertido para o dispositivo Android.

Para mais informações sobre os modelos treinados disponíveis para o Gerador de imagens, consulte a seção Modelos na visão geral da tarefa.

Baixar modelo de fundação

O gerador de imagens exige que o modelo de base corresponda ao formato do modelo stable-diffusion-v1-5/stable-diffusion-v1-5 EMA-only, com base no seguinte modelo: stable-diffusion-v1-5/stable-diffusion-v1-5 EMA-only.

Instalar dependências e converter o modelo

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

Execute o script convert.py:

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

Enviar o modelo convertido para o dispositivo

Envie o conteúdo da pasta <output_path> para o 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

Baixar modelos de plug-in e adicionar pesos LoRA (opcional)

Se você pretende usar um modelo de plug-in, verifique se ele precisa ser baixado. Para plug-ins que exigem um modelo adicional, os modelos de plug-in precisam ser agrupados no APK ou baixados sob demanda. Os modelos de plug-in são leves (~23 MB) e podem ser agrupados diretamente no APK. No entanto, recomendamos fazer o download dos modelos de plug-in sob demanda.

Se você personalizou um modelo com LoRA, faça o download deles sob demanda. Para mais informações, consulte o modelo de plug-in de pesos LoRA.

Criar a tarefa

A tarefa do gerador de imagens do MediaPipe usa a função createFromOptions() para configurar a tarefa. A função createFromOptions() aceita valores para as opções de configuração. Para mais informações sobre as opções de configuração, consulte Opções de configuração.

Opções de configuração

Essa tarefa tem as seguintes opções de configuração para apps Android:

Nome da opção Descrição Intervalo de valor
imageGeneratorModelDirectory O diretório do modelo de gerador de imagens que armazena os pesos do modelo. PATH
loraWeightsFilePath Define o caminho para o arquivo de pesos LoRA. Opcional e aplicável somente se o modelo foi personalizado com LoRA. PATH
errorListener Define um listener de erros opcional. N/A

A tarefa também é compatível com modelos de plug-in, que permitem aos usuários incluir imagens de condição na entrada da tarefa. Assim, o modelo de base pode aumentar e usar como referência para geração. Essas imagens de condição podem ser pontos de referência faciais, contornos de borda e estimativas de profundidade, que o modelo usa como contexto e informações adicionais para gerar imagens.

Ao adicionar um modelo de plug-in ao modelo de fundação, também configure as opções do plug-in. O plug-in de pontos de referência faciais usa faceConditionOptions, o plug-in de borda de Canny usa edgeConditionOptions e o plug-in de profundidade usa depthConditionOptions.

Opções de detecção de bordas de Canny

Configure as seguintes opções em edgeConditionOptions.

Nome da opção Descrição Intervalo de valor Valor padrão
threshold1 Primeiro limite para o procedimento de histerese. Float 100
threshold2 Segundo limite para o procedimento de histerese. Float 200
apertureSize Tamanho da abertura para o operador de Sobel. O intervalo típico é entre 3 e 7. Integer 3
l2Gradient Se a norma L2 é usada para calcular a magnitude do gradiente da imagem, em vez da norma L1 padrão. BOOLEAN False
EdgePluginModelBaseOptions O objeto BaseOptions que define o caminho para o modelo de plug-in. Objeto BaseOptions N/A

Para mais informações sobre como essas opções de configuração funcionam, consulte Detector de bordas de Canny.

Opções de pontos de referência do rosto

Configure as seguintes opções em faceConditionOptions.

Nome da opção Descrição Intervalo de valor Valor padrão
minFaceDetectionConfidence A pontuação mínima de confiança para que a detecção de rosto seja considerada bem-sucedida. Float [0.0,1.0] 0.5
minFacePresenceConfidence A pontuação mínima de confiança da presença de rosto na detecção de pontos de referência faciais. Float [0.0,1.0] 0.5
faceModelBaseOptions O objeto BaseOptions que define o caminho para o modelo que cria a imagem de condição. Objeto BaseOptions N/A
FacePluginModelBaseOptions O objeto BaseOptions que define o caminho para o modelo de plug-in. Objeto BaseOptions N/A

Para mais informações sobre como essas opções de configuração funcionam, consulte a tarefa de identificador de pontos de referência faciais.

Opções de profundidade

Configure as seguintes opções em depthConditionOptions.

Nome da opção Descrição Intervalo de valor Valor padrão
depthModelBaseOptions O objeto BaseOptions que define o caminho para o modelo que cria a imagem de condição. Objeto BaseOptions N/A
depthPluginModelBaseOptions O objeto BaseOptions que define o caminho para o modelo de plug-in. Objeto BaseOptions N/A

Criar apenas com o modelo de base

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

imageGenerator = ImageGenerator.createFromOptions(context, options)

Criar com plug-ins

Se você estiver aplicando um modelo de plug-in opcional, defina as opções básicas para o modelo de plug-in com setPluginModelBaseOptions. Se o modelo de plug-in exigir um modelo baixado adicional para criar a imagem da condição, especifique o caminho em BaseOptions.

Ponto de referência do rosto

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)
    

Profundidade

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)
    

Criar com pesos de LoRA

Se você estiver incluindo pesos de LoRA, use o parâmetro loraWeightsFilePath para apontar para o local do caminho.

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

imageGenerator = ImageGenerator.createFromOptions(context, options)

Preparar dados

O gerador de imagens aceita as seguintes entradas:

  • comando (obrigatório): o comando de texto que descreve a imagem a ser gerada.
  • iterações (obrigatório): o total de iterações para gerar a imagem. Um bom ponto de partida é 20.
  • seed (obrigatório): a semente aleatória usada durante a geração de imagens.
  • Imagem de condição (opcional): a imagem que o modelo usa como referência para geração. Aplicável apenas ao usar um modelo de plug-in.
  • tipo de condição (opcional): o tipo de modelo de plug-in usado com a tarefa. Aplicável apenas ao usar um modelo de plug-in.

Entradas apenas com o modelo de fundação

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

Entradas com plug-ins

Se você estiver aplicando um modelo de plug-in opcional, use também o parâmetro conditionType para escolher o modelo de plug-in e o parâmetro sourceConditionImage para gerar a imagem de condição.

Nome da opção Descrição Valor
conditionType O modelo de plug-in aplicado ao modelo de base. {"FACE", "EDGE", "DEPTH"}
sourceConditionImage A imagem de origem usada para criar a imagem de condição. Objeto MPImage

Se você estiver usando um modelo de plug-in, use o createConditionImage para criar a imagem de condição:

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

Depois de criar a imagem de condição, inclua-a como uma entrada junto com o comando, a sugestão e o número de iterações.

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

Entradas com pesos LoRA

Se você estiver usando pesos LoRA, verifique se o token está no comando de texto se quiser gerar uma imagem com o conceito específico representado pelos pesos.

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

Executar a tarefa

Use o método generate() para gerar uma imagem usando as entradas fornecidas na seção anterior. Isso produz uma única imagem gerada.

Gerar apenas com o 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
}

Gerar com plug-ins

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
}

Gerar com pesos LoRA

O processo de geração de imagens com um modelo personalizado com pesos LoRA é semelhante ao processo com um modelo de base padrão. Verifique se o token está incluído no comando e execute o mesmo 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
}

Geração iterativa

O Gerador de imagens também pode gerar as imagens intermediárias durante cada iteração, conforme definido no parâmetro de entrada iterations. Para conferir esses resultados intermediários, chame o método setInputs e depois execute() para executar cada etapa. Defina o parâmetro showResult como true para mostrar os resultados intermediários.

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

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

    return bitmap
}

Processar e mostrar resultados

O Gerador de imagens retorna um ImageGeneratorResult, que inclui a imagem gerada, um carimbo de data/hora da conclusão e a imagem condicional, se uma tiver sido fornecida como entrada.

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

A imagem a seguir foi gerada com base nas entradas abaixo, usando apenas um modelo de base.

Entradas:

  • Comando: "um guaxinim colorido de desenho animado usando um chapéu mole de aba larga segurando um graveto caminhando pela floresta, animado, vista de três quartos, pintura"
  • Semente: 312687592
  • Iterações: 20

Imagem gerada:

Imagem gerada de um guaxinim que se alinha ao comando