Guida alla generazione di immagini per Android

L'attività Generatore di immagini MediaPipe consente di generare immagini basate su un prompt di testo. Questa attività utilizza un modello da testo a immagine per generare immagini utilizzando le tecniche di diffusione.

L'attività accetta un prompt di testo come input, insieme a un'immagine condizione facoltativa che il modello può aumentare e utilizzare come riferimento per la generazione. Il generatore di immagini può anche generare immagini in base a concetti specifici forniti al modello durante l'addestramento o il riaddestramento. Per ulteriori informazioni, consulta la sezione Personalizzazione con LoRA.

L'esempio di codice descritto in queste istruzioni è disponibile su GitHub. Per ulteriori informazioni sulle funzionalità, sui modelli e sulle opzioni di configurazione di questa attività, consulta la Panoramica.

Esempio di codice

Il codice di esempio di MediaPipe Tasks è un'implementazione di base di un'app di generazione di immagini per Android. Puoi utilizzare l'app come punto di partenza per la tua app per Android o farvi riferimento quando modifichi un'app esistente. Il codice di esempio del generatore di immagini è ospitato su GitHub.

Scarica il codice

Le seguenti istruzioni mostrano come creare una copia locale del codice di esempio utilizzando lo strumento a riga di comando git.

Per scaricare il codice di esempio:

  1. Clona il repository git utilizzando il seguente comando:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. Facoltativamente, configura la tua istanza Git in modo da utilizzare un pagamento sparse, in modo da avere solo i file dell'app di esempio per Image Builder:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_generator/android
    

Dopo aver creato una versione locale del codice di esempio, puoi importare il progetto in Android Studio ed eseguire l'app. Per le istruzioni, consulta la Guida alla configurazione per Android.

Componenti chiave

I seguenti file contengono il codice fondamentale per questa applicazione di esempio per la generazione di immagini:

  • ImageGenerationHelper.kt: inizializza l'attività e gestisce la generazione delle immagini.
  • DiffusionActivity.kt: genera immagini quando i plug-in o le ponderazioni LoRA non sono abilitati.
  • PluginActivity.kt: implementa i modelli di plug-in, che consentono agli utenti di fornire un'immagine condizione come input.
  • LoRAWeightActivity.kt: accede e gestisce i pesi LoRA, che vengono utilizzati per personalizzare i modelli di base e consentire loro di generare immagini di concetti specifici.

Configurazione

Questa sezione descrive i passaggi chiave per configurare l'ambiente di sviluppo e codificare i progetti in modo specifico per l'utilizzo di Image Builder. Per informazioni generali sulla configurazione dell'ambiente di sviluppo per l'utilizzo delle attività di MediaPipe, inclusi i requisiti di versione della piattaforma, consulta la Guida alla configurazione per Android.

Dipendenze

L'attività Generatore di immagini utilizza la libreria com.google.mediapipe:tasks-vision-image-generator. Aggiungi questa dipendenza al file build.gradle della tua app Android:

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

Per i dispositivi con Android 12 (API 31) o versioni successive, aggiungi la dipendenza nativa della libreria OpenCL a AndroidManifest.xml. Per saperne di più, consulta la documentazione relativa al tag uses-native-library.

Alcuni dispositivi Android potrebbero richiedere anche librerie aggiuntive:

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

Modello

L'attività Generatore di immagini MediaPipe richiede un modello di base addestrato compatibile con questa attività. Dopo aver scaricato un modello, installa le dipendenze richieste e converti il modello in un formato adatto. Quindi, invia il modello convertito al dispositivo Android.

Per ulteriori informazioni sui modelli addestrati disponibili per Generatore di immagini, consulta la sezione Modelli della panoramica delle attività.

Scarica modello di base

Il generatore di immagini richiede che il modello di base corrisponda al formato del modello runwayml/stable-diffusion-v1-5 EMA-only, in base al seguente modello: runwayml/stable-diffusion-v1-5.

Installa le dipendenze e converti il modello

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

Esegui lo script convert.py:

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

Esegui il push del modello convertito sul dispositivo

Esegui il push dei contenuti della cartella <output_path> sul 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

(Facoltativo) Scarica i modelli di plug-in e aggiungi i pesi LoRA

Se intendi utilizzare un modello plug-in, verifica se è necessario scaricarlo. Per i plug-in che richiedono un modello aggiuntivo, i modelli dei plug-in devono essere raggruppati nell'APK o scaricati on demand. I modelli di plug-in sono leggeri (circa 23 MB) e possono essere raggruppati direttamente nell'APK. Tuttavia, ti consigliamo di scaricare i modelli di plug-in on demand.

Se hai personalizzato un modello con LoRA, scaricalo on demand. Per ulteriori informazioni, consulta il modello di plug-in ponderazioni LoRA.

Creare l'attività

L'attività Generatore di immagini MediaPipe utilizza la funzione createFromOptions() per configurarla. La funzione createFromOptions() accetta i valori per le opzioni di configurazione. Per maggiori informazioni sulle opzioni di configurazione, consulta Opzioni di configurazione.

Opzioni di configurazione

Questa attività prevede le seguenti opzioni di configurazione per le app per Android:

Nome opzione Descrizione Intervallo di valori
imageGeneratorModelDirectory La directory del modello del generatore di immagini in cui sono memorizzati i pesi del modello. PATH
loraWeightsFilePath Imposta il percorso del file pesi LoRA. Facoltativo e applicabile solo se il modello è stato personalizzato con LoRA. PATH
errorListener Imposta un listener di errori facoltativo. N/A

L'attività supporta anche i modelli di plug-in, che consentono agli utenti di includere immagini di condizione nell'input dell'attività, che il modello di base può aumentare e utilizzare come riferimento per la generazione. Queste immagini delle condizioni possono essere punti di riferimento del volto, contorni dei bordi e stime di profondità, che il modello utilizza come contesto e informazioni aggiuntivi per generare immagini.

Quando aggiungi un modello di plug-in al modello di base, configura anche le opzioni dei plug-in. Il plug-in Punto di riferimento Volto utilizza faceConditionOptions, il plug-in Canny edge utilizza edgeConditionOptions e il plug-in Profondità usa depthConditionOptions.

Opzioni bordo Canny

Configura le seguenti opzioni in edgeConditionOptions.

Nome opzione Descrizione Intervallo di valori Valore predefinito
threshold1 Prima soglia per la procedura di isteresi. Float 100
threshold2 Seconda soglia per la procedura di isteresi. Float 200
apertureSize Dimensione dell'apertura per l'operatore Sobel. L'intervallo tipico è compreso tra 3 e 7. Integer 3
l2Gradient Indica se viene utilizzata la norma L2 per calcolare la grandezza del gradiente dell'immagine, anziché la norma L1 predefinita. BOOLEAN False
EdgePluginModelBaseOptions L'oggetto BaseOptions che imposta il percorso per il modello di plug-in. BaseOptions oggetto N/A

Per ulteriori informazioni su come funzionano queste opzioni di configurazione, consulta Rivelatore di perimetro Canny.

Opzioni punto di riferimento per i volti

Configura le seguenti opzioni in faceConditionOptions.

Nome opzione Descrizione Intervallo di valori Valore predefinito
minFaceDetectionConfidence Il punteggio di affidabilità minimo affinché il rilevamento dei volti venga considerato efficace. Float [0.0,1.0] 0.5
minFacePresenceConfidence Il punteggio di affidabilità minimo del punteggio della presenza di un volto nel rilevamento dei punti di riferimento del volto. Float [0.0,1.0] 0.5
faceModelBaseOptions L'oggetto BaseOptions che imposta il percorso per il modello che crea l'immagine della condizione. BaseOptions oggetto N/A
FacePluginModelBaseOptions L'oggetto BaseOptions che imposta il percorso per il modello di plug-in. BaseOptions oggetto N/A

Per ulteriori informazioni sul funzionamento di queste opzioni di configurazione, vedi l'attività Indicatore di riferimento dei volti.

Opzioni di profondità

Configura le seguenti opzioni in depthConditionOptions.

Nome opzione Descrizione Intervallo di valori Valore predefinito
depthModelBaseOptions L'oggetto BaseOptions che imposta il percorso per il modello che crea l'immagine della condizione. BaseOptions oggetto N/A
depthPluginModelBaseOptions L'oggetto BaseOptions che imposta il percorso per il modello di plug-in. BaseOptions oggetto N/A

Crea solo con il modello di base

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

imageGenerator = ImageGenerator.createFromOptions(context, options)

Crea con i plug-in

Se applichi un modello di plug-in facoltativo, imposta le opzioni di base per il modello con setPluginModelBaseOptions. Se il modello di plug-in richiede un modello aggiuntivo scaricato per creare l'immagine della condizione, specifica il percorso in BaseOptions.

Punto di riferimento volto

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)
    

Bordo 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)
    

Profondità

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 pesi LoRA

Se intendi includere le ponderazioni LoRA, utilizza il parametro loraWeightsFilePath per puntare alla posizione del percorso.

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

imageGenerator = ImageGenerator.createFromOptions(context, options)

Preparazione dei dati

Il generatore di immagini accetta i seguenti input:

  • prompt (obbligatorio): il prompt di testo che descrive l'immagine da generare.
  • iterazioni (obbligatorio): il totale delle iterazioni per generare l'immagine. Un buon punto di partenza è 20.
  • seed (obbligatorio): il seme casuale utilizzato durante la generazione dell'immagine.
  • image_condition (facoltativa): l'immagine che il modello utilizza come riferimento per la generazione. Applicabile solo quando si utilizza un modello di plug-in.
  • condition type (facoltativo): il tipo di modello di plug-in utilizzato nell'attività. Applicabile solo quando si utilizza un modello di plug-in.

Input con solo il modello di base

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

Input con plug-in

Se applichi un modello di plug-in facoltativo, utilizza anche il parametro conditionType per scegliere il modello e il parametro sourceConditionImage per generare l'immagine della condizione.

Nome opzione Descrizione Valore
conditionType Il modello di plug-in applicato al modello di base. {"FACE", "EDGE", "DEPTH"}
sourceConditionImage L'immagine di origine utilizzata per creare l'immagine della condizione. MPImage oggetto

Se utilizzi un modello di plug-in, usa createConditionImage per creare l'immagine della condizione:

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

Dopo aver creato l'immagine della condizione, includi in come input insieme a prompt, seed e numero di iterazioni.

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

Input con pesi LoRA

Se utilizzi le ponderazioni LoRA, assicurati che il token sia nel prompt di testo se intendi generare un'immagine con il concetto specifico rappresentato dalle ponderazioni.

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

Esegui l'attività

Utilizza il metodo generate() per generare un'immagine utilizzando gli input forniti nella sezione precedente. In questo modo viene generata una singola immagine generata.

Genera solo con il modello di 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
}

Genera con plug-in

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 pesi LoRA

Il processo per generare immagini con un modello personalizzato con i pesi LoRA è simile a quello con un modello di base standard. Assicurati che il token sia incluso nel prompt ed esegui lo stesso codice.

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

Generazione iterativa

Il generatore di immagini può anche restituire le immagini intermedie generate durante ogni iterazione, come definito nel parametro di input iterations. Per visualizzare questi risultati intermedi, chiama il metodo setInputs, quindi chiama execute() per eseguire ogni passaggio. Imposta il parametro showResult su true per visualizzare i risultati intermedi.

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

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

    return bitmap
}

Gestire e visualizzare i risultati

Il generatore di immagini restituisce un elemento ImageGeneratorResult che include l'immagine generata, un timestamp del momento di completamento e l'immagine condizionale, se ne è stata fornita una come input.

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

L'immagine seguente è stata generata dai seguenti input, utilizzando solo un modello di base.

Input:

  • Prompt: "un procione colorato dai colori vivaci che indossa un cappello a tesa larga floppy che tiene in mano un bastoncino che cammina nella foresta, vista animata da tre quarti, dipinto"
  • Seme: 312687592
  • Iterazioni: 20

Immagine generata: