Imaginez pouvoir créer des images transparentes avec la même facilité que vous composez des calques dans votre logiciel d’édition graphique préféré. C’est là que réside le potentiel fascinant de la génération de contenu en couches et d’images transparentes, une dimension encoder négligée par la recherche. Alors que les modèles de génération d’images (text-to-image) ont révolutionné la génération d’images, peu d’attention a été portée à cette capacité pourtant essentielle.
Dans un monde où la demande de contenu visuel est sans cesse croissante, il est surprenant de constater le manque de recherche dans ce domaine. La plupart des logiciels d’édition visuelle que nous utilisons au quotidien sont basés sur des couches, mais la génération de contenu transparent reste largement inexploitée. Pourquoi ? Le manque de données d’entrainement de qualité et les défis techniques liés à la manipulation des modèles existants sont parmi les principales raisons.
Cependant, ne désespérez pas. Nous avons entre nos mains une solution prometteuse : l’approche de « transparence latente ». Cette méthode innovante permet aux modèles de diffusion latente de générer non seulement des images transparentes, mais aussi plusieurs couches transparentes simultanément.
Dans ce article, nous explorerons une approche intéressante appelée Layer Diffusion. Vous découvrirez comment la transparence d’une image est codée dans un « décalage latent », préservant ainsi la qualité des résultats obtenus par Stable Diffusion. Nous aborderons également l’utilisation d’un mécanisme d’attention partagée et de LoRAs pour créer des compositions harmonieuses entre les différentes couches d’image.
Comment marche Layer Diffusion
L’approche de Layer Diffusion permet à un modèle de diffusion latent (Latent Diffusion Model, LDM), tel que Stable Diffusion, de générer des images transparentes et d’étendre ensuite le modèle pour produire simultanément plusieurs couches transparentes.
L’objectif de cette approche est d’ajouter la prise en charge de la transparence aux modèles de diffusion latente à grande échelle, tels que Stable Diffusion, qui utilisent généralement un encodeur-décodeur latent (Variational Autoencoder, VAE) pour convertir les images RVB (rouge, vert, bleu) en images latentes avant de les alimenter dans un modèle de diffusion.
Pour y parvenir, une méthode de « transparence latente » est utilisée pour aligner explicitement l’espace latent modifié (qui prend en compte la transparence) avec la distribution latente d’origine. Cela permet à Stable Diffusion d’être directement affiné sur le nouvel espace latent, produisant ainsi des images transparentes de haute qualité.
Après avoir introduit la méthodologie de Layer Diffusion, explorons maintenant un phénomène mis en évidence par plusieurs recherches dans divers domaines : les réseaux neuronaux ont la capacité de « cacher » des caractéristiques dans des perturbations à l’intérieur de caractéristiques existantes sans modifier les distributions de caractéristiques globales.
Par exemple, dans une expérience de CycleGAN [1], un visage humain peut être caché dans une image de ramen via des perturbations de pixels invisibles. De même, des techniques telles que le downscaling [2] inversible et le grayscale [3] inversible montrent que les réseaux neuronaux peuvent dissimuler des images à l’intérieur d’autres images et les reconstruire.
L’approche « transparence latente » utilise ces principes : elle cache des caractéristiques de transparence dans des perturbations ajoutées à l’espace latent de Stable Diffusion, tout en préservant la distribution globale de cet espace. Cela permet une transition fluide des modèles de diffusion d’images non transparentes vers des modèles transparents, facilitant ainsi le réglage fin ultérieur.
L’ensemble de données de base comprend 20’000 images transparentes de haute qualité, utilisées pour entrainer les modèles à l’aide d’une méthode « human-in-the-loop », qui consiste à collecter des images et à les ajuster de manière itérative. Ce processus est répété pendant 25 itérations pour obtenir un ensemble de données final de 45’000 images.
De plus, l’ensemble de données est étendu en une structure multi-couche pour entrainer des modèles de couches multiples. En utilisant des paires de requêtes structurées générées par un modèle GPT, des données pour les couches avant-plan, arrière-plan et texte sont obtenues, permettant ainsi de créer des compositions visuelles plus complexes.
Plus en profondeur
Les grands modèles de diffusion, comme Stable Diffusion, compressent une image (RGB) dans un espace latent grâce à un VAE (Variational Autoencoder) qui sera l’entrée du processus de diffusion. Ce VAE se compose d’un encodeur et d’un décodeur, on notera l’encodeur $\mathcal{E}^{*}_{sd}(\cdot)$ et le décodeur $\mathcal{D}^{*}_{sd}(\cdot)$, où l’étoile * indique que les paramètres du modèle sont gelés (ils ne seront pas mis à jour pendant l’entrainement). En prenant une image RGB notée $\mathcal{I}$, on peut calculer sa représentation dans l’espace latent $x = \mathcal{E}^{*}_{sd}(\mathcal{I})$ et reconstruire l’image d’origine avec le décodeur $\mathcal{I} = \mathcal{D}^{*}_{sd}(x)$.
Le VAE et le processus de diffusion doivent partager un espace latent similaire, sans quoi tout mauvais alignement entre ces deux composants dégradera les performances du système (donc la qualité des images produites). Layer Diffusion ajuste cet espace latent pour supporter la transparence, mais l’espace latent de base doit être préservé le plus possible. Comment être sûr que l’espace latent d’origine est bien préservé ? Simplement en vérifiant les images latentes décompressées par le décodeur du VAE, si ces images ont des artéfacts, alors l’espace latent d’origine a été dégradé.
Comment mettre ce principe sous forme d’équations ? Pour cacher la transparence dans l’espace latent, on ajoute une perturbation $x_{\epsilon}$ au latent d’origine pour donner $x_{\alpha} = x + x_{\epsilon}$. Pour évaluer la préservation de l’espace latent d’origine, on peut décoder l’image latente perturbée $\hat{\mathcal{I}} = \mathcal{D}^{*}_{sd}(x_{\alpha})$ et la comparer à l’image d’origine $\mathcal{I}$ avec
où $||\cdot||_2$ est la distance Euclidienne. $\mathcal{L}_{identity}$ est une fonction objectif, plus elle a une valeur basse plus l’image d’origine $\mathcal{I}$ et sa reconstruction $\mathcal{\hat{I}}$ sont proches. Si au contraire elle retourne une valeur haute, la perturbation ajoutée a détruit la capacité du décodeur a reconstruire l’image d’origine. La fonction objectif $\mathcal{L}_{identity}$ va donc garantir que pendant l’entrainement, l’espace latent d’origine est préservé.
L’idée de Layer Diffusion est donc d’encoder la transparence dans ces perturbations $x_{\epsilon}$. On sait maintenant comment préserver les capacités du décodeur, mais comment encoder la transparence dans les perturbations ? Pour cela, Layer Diffusion introduit un encodeur de transparence $\mathcal{E}(\cdot, \cdot)$ qui va prendre les canaux RGB $\mathcal{I}_c$ et alpha $\mathcal{I}_{\alpha}$ en entrée et les projeter dans l’espace latent des perturbations
Pour pouvoir décoder l’espace latent ajusté $x_{\alpha} = x + x_{\epsilon}$ et récupérer les canaux RGB et alpha, un décodeur est entraîné qui prend en entrée l’image décodée par le décodeur classique $\mathcal{\hat{I}}$ et le latent ajusté $x_{\alpha}$,
Le nouvel encodeur ainsi que le nouveau décodeur sont tous les deux entraînés « from scratch ». On peut donc obtenir les canaux RGB $\hat{\mathcal{I}}_{c}$ et alpha $\mathcal{\hat{I}_{\alpha}}$ reconstruits. On calcule la qualité de ces reconstructions par
et la fonction objectif finale est obtenue en combinant la préservation de l’identité $\mathcal{L}_{identity}$, la fidélité de la reconstruction $\mathcal{L}_{recon}$ et un objectif de discrimination issu d’un GAN (PatchGAN) $\mathcal{L}_{disc}$,
où les poids $\lambda_{identity}, \lambda_{recon}$ et $\lambda_{disc}$ permettent d’ajuster l’importance de chaque objectif. En entrainant ces nouveaux encodeurs et décodeurs, Layer Diffusion peut projeter de l’espace des pixels RGBA vers un espace latent ajusté pour contenir la transparence, et inversement. On peut alors utiliser des images transparentes pour fine-tuner Stable Diffusion.
Layer Diffusion permet d’effectuer plusieurs opérations, de la création d’une image transparente à la création d’un fond correspondant. Pour permettre cela, les auteurs de Layer Diffusion n’ont pas fine-tuné Stable Diffusion mais ont modifié les poids de SD via des LoRA, différents pour chaque layer. Comme le montre le figure 5, Layer Diffusion utilise un LoRA pour l’avant (Foreground LoRA) et le fond (Background LoRA), chacun permettant de diriger SD vers la génération des différents layer.
Pour avoir une cohérence entre l’avant et l’arrière-plan, les poids d’attention sont partagés entre les deux UNets. Layer Diffusion a donc ainsi une grande flexibilité qu’on verra dans le test. On peut ainsi initier la génération avec une image de fond pour générer ensuite l’avant et l’arrière-plan avec le calque alpha correspondant (background to foreground). Ou initier la génération avec une image transparent mais un arrière-plan aléatoire pour générer un arrière plan qui correspond à l’avant-plan (foreground to background), ou encore, générer les deux couches en même temps.
Pour accéder à Layer Diffusion, nous allons passer par Forge, un fork du projet Automatic1111, qui est lui-même une interface web locale qui permet de générer des images avec Stable Diffusion.
Installation
Le première étape consiste à installer Forge qui se trouve à l’adresse https://github.com/lllyasviel/stable-diffusion-webui-forge. Selon votre système d’exploitation, la procédure d’installation peut être légèrement différente mais elle consiste en gros à:
- Télécharger Forge.
- Soit en clonant le repos de Forge : git clone https://github.com/lllyasviel/stable-diffusion-webui-forge
- Soit en téléchargeant la dernière version: https://github.com/lllyasviel/stable-diffusion-webui-forge/archive/refs/heads/main.zip
- Lancer l’application en vous dirigeant dans le répertoire de téléchargement et en lançant le script webui.sh.
- Installer l’extension sd-forge-layerdiffuse.
- Le repos de l’extension est à l’adresse suivante: https://github.com/layerdiffusion/sd-forge-layerdiffuse.
- Comme Forge vous pouvez soit clone le repos soit télécharger la dernière version: https://github.com/layerdiffusion/sd-forge-layerdiffuse/archive/refs/heads/main.zip.
- Le répertoire de l’extension (dézippée donc) doit être placé dans le répertoire extensions du répertoire principal de Forge.
- Relancer Forge une fois l’extension télécharger.
L’extension étant encore instable et en développement, il reste de nombreux bugs comme nous le verrons dans les tests. Nous testerons donc la transparence pour SDXL qui fonctionnait contrairement à la transparence pour la version 1.5 qui retournait de nombreuses erreurs (en date du 23 mars 2024).
Première image transparente
Une fois le script webui.sh lancé, vous pouvez vous rendre dans votre navigateur à l’adresse indiquée par la sortie du script pour accéder à l’interface. Elle est similaire à celle de automatic 1111, si vous n’êtes pas habitué cette outil, veuillez vous référer aux articles précédents de la section « AI & Art ».
Avec l’extension sd-forge-layerdiffuse, un onglet supplémentaire sera accessible nommé « LayerDiffusion ».
Ce onglet contient plusieurs contrôle. Le plus simple étant la case à cocher « Enabled » qui permet d’activer LayerDiffusion.
Le menu de sélection Method permet de choisir la méthode de génération. Elles sont réparties en deux groupes. Le premier pour Stable Diffusion 1.5 et le deuxième pour Stable Diffusion XL. Il vous faudra donc choisir selon le modèle que vous utilisez (celui que vous avez choisi tout en haut de l’interface dans Stable Diffusion Checkpoint). Il est à noter aussi que LayerDiffusion utilisant un encodeur-decodeur home-made et un entrainement LoRA, n’importe quel modèle fine-tuné peut être utilisé.
Les méthodes de génération sont les suivantes:
- Only Generate Transparent Image (Attention Injection): générer une image transparente seule (méthode 1)
- Only Generate Transparent Image (Conv Injection): générer une image transparente seule (méthode 2)
- From Foreground to Background: générer un arrière-plan à partir d’une image transparente.
- From Background to Foreground: générer un avant-plan à partir d’un fond.
- Generate Everything together: générer l’avant et l’arrière-plan ensemble.
Ces méthodes marchent pour Stable Diffusion 1.5. L’équivalent existe pour SDXL, sauf la génération conjointe de l’avant et de l’arrière-plan. Mais devrait être accessible rapidement. Nous allons nous concentrer sur ces 4 opérations dans la suite de cette article.
Génération d’une image transparente
On commence par générer une image transparente. Pour cela on va suivre ce qui se trouve sur la page github du projet et essayer de reproduire leurs résultats.
On choisit donc « (SD1.5) Only Generate Transparent Image » dans le champs méthodes et les paramètres suivants.
Prompt: girl in dress, comics, Pixar style, 3d rendering, high quality, high quality, 4k
Negative prompt: bad, ugly
Taille: 512 x 640
Seed: 12345
Batch count: 4
Modèle: realisticVisionV51
Il nous reste plus qu’à appuyer sur le bouton « Generate » pour obtenir les image suivantes.
Comme vous pouvez le voir la séparation entre le personnage et le fond est très clair et les images parfaitement exploitable.
Génération de l’arrière-plan
À partir de cette image transparente, on va essayer de générer un fond correspondant. Pour cela, on change la méthode pour « (SD1.5) From Foreground to Background » avec les paramètres suivants.
Prompt: street, high quality, 4k
Negative prompt: nsfw, nude, bad, ugly
Taille: 512 x 640
Seed: 12345
Batch count: 4
Modèle: realisticVisionV51
L’interface de l’onglet change et on peut alors télécharger une image d’avant-plan pour guider la génération. On choisit l’une des images qu’on a générer à l’étape précédente. En appuyant sur le bouton « Generate », on obtient les images suivantes.
Les images s’intègrent bien avec l’image d’avant-plan même si une des images ajoute un élément indésirable. De manière générale, il peut arriver que certaine image soit incohérente ou ajoute des éléments comme des personnages. Il faut alors jouer sur le prompt et le prompt négatif pour éliminer les éléments indésirables. Faites attention aussi à ne pas introduire de mots dans le prompt qui pourrait faire référence à des personnes par exemple (dans ce cas).
Génération d’un avant-plan
On va maintenant générer une image transparente d’avant-plan à partir d’un fond. Pour cela, on change la méthode pour « (SD1.5) From Background to Foreground ». Un contrôle nous permet de choisir une image de fond. On va prendre l’image fournie par les auteurs du papier sur le repo du projet.
On choisit les paramètres suivants.
Prompt: an old man sitting, high quality, high quality, 4k
Negative prompt: bad, ugly
Taille: 512 x 640
Seed: 0
Batch count: 4
Modèle: realisticVisionV51
On obtient les images d’avant-plan suivantes.
De nouveau, ces images d’avant-plan s’intègrent bien avec l’image d’arrière-plan fournies.
Exemple avancé
On va refaire ces étapes avec des exemples différents pour voir si la cohérences entre les différents composants est à l’arrivée. On commence par générer une image transparente de base avec les paramètres suivants.
Prompt: a viking fighting, high quality, 4k
Negative prompt: nsfw, nude, bad, ugly
Taille: 512 x 640
Seed: 12345
Batch count: 1
À partir de cette image, on génère 4 images d’arrière-plan, mais cette fois, nous varions le paramètre poids. Avec un poids de 0.1, on obtient.
Avec un poids normal de 1.0, on a
Alors que avec un poids plus important de 1.5, on obtient,
On voit que le paramètre poids n’a pas d’impact très important à ce niveau là (nous verrons plus bas, l’impact du poids sur la génération d’images transparentes).
À partir d’une des images d’arrière-plan, on va générer une image d’avant-plan. On prend cette image comme condition.
On va utiliser les paramètres suivants pour générer les images d’avant-plan.
Prompt: military walking, high quality, 4k
Negative prompt: bad, ugly
Taille: 512 x 640
Seed: 12345
En les collant directement sur le fond utilisé, on peut voir que les images générées correspondent plus ou moins. Dans un cas pratique, on devra donc certainement sélectionner les bonnes images.
Paramètres de génération
Weight & Stop At
Le poids de la couche de transparence peut être changée grâce au paramètre Weight et au slider qui se trouve dans l’onglet de LayerDiffusion. Ce paramètre varie entre 0.0 et 2.0.
La figure (4) suivante montre l’impact de ce paramètre sur la génération d’image transparente seule (Only Generate Transparent Image). Un poids de 0.0 ne produit aucune couche alpha qui commence à apparaître autour de 0.5. Passée une valeur de 1.2, la génération va perdre en qualité et en cohérence.
Il existe un deuxième paramètre Stop At. Ce paramètre ainsi que le précédent (Weight) ne sont pas bien documentés dans l’article. On doit alors avoir une approche empirique en testant différentes valeurs. Ce paramètre peut aussi être modifié grâce à un slider présent dans l’onglet de Layer Diffusion.
La figure suivante (5) présente des générations d’image pour chaque valeur de ce paramètre qui varie entre 0.0 et 1.0. On peut voir que ce paramètre n’a pas d’impact direct sur le premier-plan de l’image mais qu’une valeur en dessous de 0.2 va impacter la couche alpha.
Références
- Zhu, J. Y., Park, T., Isola, P., & Efros, A. A. (2017). Unpaired image-to-image translation using cycle-consistent adversarial networks. In Proceedings of the IEEE international conference on computer vision (pp. 2223-2232).
- Xiao, M., Zheng, S., Liu, C., Wang, Y., He, D., Ke, G., … & Liu, T. Y. (2020). Invertible image rescaling. In Computer Vision–ECCV 2020: 16th European Conference, Glasgow, UK, August 23–28, 2020, Proceedings, Part I 16 (pp. 126-144). Springer International Publishing.
- Xia, M., Liu, X., & Wong, T. T. (2018). Invertible grayscale. ACM Transactions on Graphics (TOG), 37(6), 1-10.
Leave a Comment