Guide de génération d'images pour Android

La tâche MediaPipe Image Generator vous permet de générer des images à partir d'une requête textuelle. Cette tâche utilise un modèle texte-vers-image pour générer des images à l'aide de techniques de diffusion.

La tâche accepte une invite textuelle en entrée, ainsi qu'une image de condition facultative que le modèle peut augmenter et utiliser comme référence pour la génération. Le générateur d'images peut également générer des images en fonction de concepts spécifiques fournis au modèle lors de l'entraînement ou du réentraînement. Pour en savoir plus, consultez la section Personnaliser avec LoRA.

L'exemple de code décrit dans ces instructions est disponible sur GitHub. Pour en savoir plus sur les fonctionnalités, les modèles et les options de configuration de cette tâche, consultez la présentation.

Exemple de code

L'exemple de code MediaPipe Tasks est une implémentation de base d'une application de génération d'images pour Android. Vous pouvez utiliser l'application comme point de départ pour votre propre application Android ou vous y référer lorsque vous modifiez une application existante. L'exemple de code du générateur d'images est hébergé sur GitHub.

Télécharger le code

Les instructions suivantes vous expliquent comment créer une copie locale de l'exemple de code à l'aide de l'outil de ligne de commande git.

Pour télécharger l'exemple de code, procédez comme suit:

  1. Clonez le dépôt git à l'aide de la commande suivante :
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. Vous pouvez éventuellement configurer votre instance Git pour utiliser le paiement creux afin de n'avoir que les fichiers de l'exemple d'application Image Generator :
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_generator/android
    

Après avoir créé une version locale de l'exemple de code, vous pouvez importer le projet dans Android Studio et exécuter l'application. Pour obtenir des instructions, consultez le guide de configuration pour Android.

Composants clés

Les fichiers suivants contiennent le code crucial pour cet exemple d'application de génération d'images:

  • ImageGenerationHelper.kt : initialise la tâche et gère la génération d'image.
  • DiffusionActivity.kt : génère des images lorsque les plug-ins ou les pondérations LoRA ne sont pas activés.
  • PluginActivity.kt : met en œuvre les modèles de plug-in, ce qui permet aux utilisateurs de fournir une image de condition en tant qu'entrée.
  • LoRAWeightActivity.kt : accède aux pondérations LoRA, qui sont utilisées pour personnaliser les modèles de fondation et leur permettre de générer des images de concepts spécifiques.

Préparation

Cette section décrit les étapes clés de la configuration de votre environnement de développement et de vos projets de code spécifiquement pour l'utilisation du générateur d'images. Pour obtenir des informations générales sur la configuration de votre environnement de développement pour l'utilisation des tâches MediaPipe, y compris sur les exigences de version de la plate-forme, consultez le guide de configuration pour Android.

Dépendances

La tâche du générateur d'images utilise la bibliothèque com.google.mediapipe:tasks-vision-image-generator. Ajoutez cette dépendance au fichier build.gradle de votre application Android:

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

Pour les appareils équipés d'Android 12 (API 31) ou version ultérieure, ajoutez la dépendance de bibliothèque OpenCL native à AndroidManifest.xml. Pour en savoir plus, consultez la documentation sur la balise uses-native-library.

Certains appareils Android peuvent également nécessiter des bibliothèques supplémentaires:

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

Modèle

La tâche du générateur d'images MediaPipe nécessite un modèle de fondation entraîné compatible avec cette tâche. Après avoir téléchargé un modèle, installez les dépendances requises et convertissez-le dans un format approprié. Transférez ensuite le modèle converti vers l'appareil Android.

Pour en savoir plus sur les modèles entraînés disponibles pour le générateur d'images, consultez la section Modèles de la présentation des tâches.

Télécharger le modèle de fondation

Le générateur d'images nécessite que le modèle de fondation corresponde au format de modèle runwayml/stable-diffusion-v1-5 EMA-only, sur la base du modèle suivant : runwayml/stable-diffusion-v1-5.

Installer les dépendances et convertir le modèle

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

Exécutez le script convert.py:

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

Transférer le modèle converti vers l'appareil

Transférez le contenu du dossier <output_path> vers l'appareil 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

Télécharger des modèles de plug-ins et ajouter des pondérations LoRA (facultatif)

Si vous avez l'intention d'utiliser un modèle de plug-in, vérifiez s'il doit être téléchargé. Pour les plug-ins nécessitant un modèle supplémentaire, les modèles de plug-ins doivent être soit regroupés dans l'APK, soit téléchargés à la demande. Les modèles de plug-ins sont légers (environ 23 Mo) et peuvent être regroupés directement dans l'APK. Toutefois, nous vous recommandons de télécharger les modèles de plug-in à la demande.

Si vous avez personnalisé un modèle avec LoRA, téléchargez-le à la demande. Pour en savoir plus, consultez la section sur les pondérations LoRA concernant le modèle de plug-in.

Créer la tâche

La tâche du générateur d'images MediaPipe utilise la fonction createFromOptions() pour configurer la tâche. La fonction createFromOptions() accepte des valeurs pour les options de configuration. Pour en savoir plus sur les options de configuration, consultez la section Options de configuration.

Options de configuration

Cette tâche dispose des options de configuration suivantes pour les applications Android:

Nom de l'option Description Plage de valeurs
imageGeneratorModelDirectory Répertoire de modèles du générateur d'images qui stocke les pondérations du modèle. PATH
loraWeightsFilePath Définit le chemin d'accès au fichier de pondérations LoRA. Facultatif et applicable uniquement si le modèle a été personnalisé avec LoRA. PATH
errorListener Définit un écouteur d'erreurs facultatif. N/A

La tâche est également compatible avec les modèles de plug-in, ce qui permet aux utilisateurs d'inclure des images de conditions dans l'entrée de la tâche, que le modèle de fondation peut enrichir et utiliser comme référence pour la génération. Ces images de conditions peuvent être des points de repère de visage, des contours d'arêtes et des estimations de profondeur, que le modèle utilise comme contexte et informations supplémentaires pour générer des images.

Lorsque vous ajoutez un modèle de plug-in au modèle de fondation, configurez également les options de plug-in. Le plug-in des points de repère de visage utilise faceConditionOptions, le plug-in Canny Edge utilise edgeConditionOptions et le plug-in Depth utilise depthConditionOptions.

Options d'angles simples

Configurez les options suivantes dans edgeConditionOptions.

Nom de l'option Description Plage de valeurs Valeur par défaut
threshold1 Premier seuil pour la procédure d'hystérèse. Float 100
threshold2 Deuxième seuil pour la procédure d'hystérèse. Float 200
apertureSize Taille d'ouverture pour l'opérateur Sobel. La plage habituelle est comprise entre 3 et 7. Integer 3
l2Gradient Indique si la norme L2 est utilisée pour calculer l'amplitude du gradient de l'image, plutôt que la norme L1 par défaut. BOOLEAN False
EdgePluginModelBaseOptions L'objet BaseOptions qui définit le chemin d'accès au modèle de plug-in. Objet BaseOptions N/A

Pour en savoir plus sur le fonctionnement de ces options de configuration, consultez la page Détecteur de périphérie Canny.

Options des points de repère de visage

Configurez les options suivantes dans faceConditionOptions.

Nom de l'option Description Plage de valeurs Valeur par défaut
minFaceDetectionConfidence Score de confiance minimal pour que la détection de visages soit considérée comme réussie. Float [0.0,1.0] 0.5
minFacePresenceConfidence Score de confiance minimal du score de présence de visage dans la détection des points de repère de visage. Float [0.0,1.0] 0.5
faceModelBaseOptions L'objet BaseOptions qui définit le chemin d'accès au modèle qui crée l'image de condition. Objet BaseOptions N/A
FacePluginModelBaseOptions L'objet BaseOptions qui définit le chemin d'accès au modèle de plug-in. Objet BaseOptions N/A

Pour en savoir plus sur le fonctionnement de ces options de configuration, consultez la section Tâche d'ajout de points de repère de visages.

Options de profondeur

Configurez les options suivantes dans depthConditionOptions.

Nom de l'option Description Plage de valeurs Valeur par défaut
depthModelBaseOptions L'objet BaseOptions qui définit le chemin d'accès au modèle qui crée l'image de condition. Objet BaseOptions N/A
depthPluginModelBaseOptions L'objet BaseOptions qui définit le chemin d'accès au modèle de plug-in. Objet BaseOptions N/A

Créer uniquement avec le modèle de fondation

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

imageGenerator = ImageGenerator.createFromOptions(context, options)

Créer avec des plug-ins

Si vous appliquez un modèle de plug-in facultatif, définissez les options de base du modèle de plug-in avec setPluginModelBaseOptions. Si le modèle de plug-in nécessite un modèle téléchargé supplémentaire pour créer l'image de condition, spécifiez le chemin d'accès dans BaseOptions.

Repère de visage

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)
    

Précision

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)
    

Créer avec des pondérations LoRA

Si vous incluez des pondérations LoRA, utilisez le paramètre loraWeightsFilePath pour pointer vers l'emplacement du chemin.

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

imageGenerator = ImageGenerator.createFromOptions(context, options)

Préparation des données

Le générateur d'images accepte les entrées suivantes:

  • prompt (obligatoire): invite textuelle décrivant l'image à générer.
  • iterations (obligatoire): nombre total d'itérations nécessaires à la génération de l'image. Un bon point de départ est 20.
  • seed (obligatoire): source aléatoire utilisée lors de la génération d'image.
  • image de condition (facultatif): image que le modèle utilise comme référence pour la génération. S'applique uniquement lors de l'utilisation d'un modèle de plug-in.
  • condition type (type de condition) (facultatif): type de modèle de plug-in utilisé avec la tâche. S'applique uniquement lors de l'utilisation d'un modèle de plug-in.

Entrées ne contenant que le modèle de fondation

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

Entrées avec plug-ins

Si vous appliquez un modèle de plug-in facultatif, utilisez également le paramètre conditionType pour choisir le modèle de plug-in et le paramètre sourceConditionImage pour générer l'image de condition.

Nom de l'option Description Valeur
conditionType Modèle de plug-in appliqué au modèle de fondation. {"FACE", "EDGE", "DEPTH"}
sourceConditionImage Image source utilisée pour créer l'image de condition. Objet MPImage

Si vous utilisez un modèle de plug-in, créez l'image de condition à l'aide de createConditionImage:

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

Après avoir créé l'image de condition, incluez-la en tant qu'entrée avec l'invite, la valeur initiale et le nombre d'itérations.

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

Entrées avec pondérations LoRA

Si vous utilisez des pondérations LoRA, assurez-vous que le jeton se trouve dans l'invite textuelle si vous avez l'intention de générer une image avec le concept spécifique représenté par les pondérations.

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

Exécuter la tâche

Utilisez la méthode generate() pour générer une image à l'aide des entrées fournies dans la section précédente. Cette opération produit une seule image générée.

Générer uniquement avec le modèle de fondation

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

Générer avec des 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
}

Générer avec des pondérations LoRA

Le processus de génération d'images avec un modèle personnalisé avec des pondérations LoRA est semblable à celui avec un modèle de fondation standard. Assurez-vous que le jeton est inclus dans l'invite et exécutez le même code.

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

Génération itérative

Le générateur d'images peut également générer les images intermédiaires générées lors de chaque itération, comme défini dans le paramètre d'entrée iterations. Pour afficher ces résultats intermédiaires, appelez la méthode setInputs, puis execute() pour exécuter chaque étape. Définissez le paramètre showResult sur true pour afficher les résultats intermédiaires.

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

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

    return bitmap
}

Gérer et afficher les résultats

Le générateur d'images renvoie un ImageGeneratorResult, qui inclut l'image générée, un horodatage de l'heure d'achèvement et l'image conditionnelle si vous en avez fourni une en entrée.

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

L'image ci-dessous a été générée à partir des entrées ci-dessous, uniquement à l'aide d'un modèle de base.

Entrées:

  • Invite: "Un raton laveur de dessin animé coloré portant un chapeau à large bords souple et tenant un bâton qui traverse la forêt, vue animée de trois quarts, peinture"
  • graine: 312687592
  • Itérations: 20

Image générée: