Génération d’images avec Python, DALL-E et StableDiffusion

La hype autour du modèle de génération d’image Dall-E a amené une grande attention sur les modèles autogénératifs de contenu. Dall-E est, à l’heure actuelle, le modèle le plus célèbre de génération d’image à partir de texte. Il est maintenant possible de créer, depuis Python grâce à l’implémentation de StableDiffusion, soit-même ses propres images rigolotes.

Tutoriel
Avancé
Author

Lino Galiana

Published

2024-04-27

Pour tester les exemples présentés dans ce chapitre:

1 Contexte

La publication en avril 2022 par l’organisation Open AI de son modèle de génération de contenu créatif Dall-E-2 (un jeu de mot mélangeant Dali et Wall-E) a créé un bruit inédit dans le monde de la data science. A propos de Dall-E, le bloggeur tech Casey Newton a pu parler d’une révolution créative dans le monde de l’IA. The Economist a par consacré un numéro au sujet de l’émergence de ces intelligences artificielles créatrices de contenu.

Ce bruit sur la capacité des intelligences artificielle à générer du contenu créatif a d’ailleurs été amplifié plus récemment avec la publication du chatbot chatGPT (voir cet éditorial du Guardian).

L’inconvénient principal de Dall-E pour générer facilement du contenu est que le nombre de contenu pouvant être créé avec un accès gratuit est limité (50 crédits gratuits par mois). Depuis le 22 Août 2022, un générateur de contenu similaire est disponible gratuitement, avec une licence plus permissive1. Ce générateur, développé par une équipe de chercheurs (Rombach et al. 2022), s’appelle Stable Diffusion (dépôt Github pour le code source et dépôt HuggingFace pour le modèle mis à disposition2). Un excellent article de blog décrit la démarche de Stable Diffusion. La plupart des exemples originaux dans cette partie seront basés sur Stable Diffusion.

Dall-E-2 et StableDiffusion sont des modèles généralistes. D’autres modèles, plus spécialisés, existent également. Le modèle Midjourney (produit propriétaire de la société du même nom) permet la production de contenu artistique, DreamBooth (développé par Google) est spécialisé dans la génération de contenu dans un nouveau contexte.

Le principe de tous ces modèles est le même: un utilisateur donne une instruction (une ou plusieurs phrases) et l’intelligence artificielle l’interprète et génère une image censée être cohérente avec l’instruction.

Voici par exemple l’une des productions possibles de DALL-E-2

“A Shiba Inu dog wearing a beret and black turtleneck”

Midjourney, spécialisé dans le contenu esthétique, génèrera l’image suivante avec l’instruction “mechanical dove” :

StableDiffusion, modèle généraliste comme Dall-E, crééra le contenu suivant avec l’instruction “A photograph of an astronaut riding a horse” :

“A photograph of an astronaut riding a horse”

“A photograph of an astronaut riding a horse”

Enfin, DreamBooth pourra lui introduire un chien dans une grande variété de contextes:

Un compte Twitter (Weird AI Generations) propose de nombreuses générations de contenu drôles ou incongrues. Voici un premier exemple de production humoristique faite à partir de Mini Dall-E, la version publique:

Ainsi qu’un deuxième:

Les modèles Dall-E-2 et Stable Diffusion s’appuient sur des réseaux de neurones à différents niveaux :

  • le contenu de la phrase est analysé par un réseau de neurones similaire (mais bien sûr plus évolué) que ceux que nous avons présenté dans la partie NLP
  • les éléments importants de la phrase (recontextualisés) sont ensuite transformés en image à partir de modèles entraînés à reconnaître des images

Illustration du fonctionnement de ce type de générateur d’image (ici à partir de Stable Diffusion)

2 Générer du contenu avec Dall-E via l’API d’OpenAI

Le contenu de cette partie s’appuie sur le tutoriel du site realpython L’utilisation de Dall-E sera faite via le package openai qui donne accès à l’API d’OpenAI. Pour l’installer depuis la cellule d’un Notebook:

!pip install openai

Après avoir obtenu votre clé d’API, on va supposer que celle-ci est stockée dans une variable key:

key = "sk-XXXXXXXXXX"  # remplacer avec votre clé

Ensuite, l’utilisation de l’API est assez directe:

openai.api_key = key
openai.Image.create(
    prompt="Teddy bears working on new AI research underwater with 1990s technology",
    n=2,
    size="1024x1024",
)

L’output est un JSON avec les URL des images générées. Voici les deux images générées :

Pour aller plus loin, vous pouvez consulter le tutoriel de realpython

3 Comment utiliser Stable Diffusion ?

Stable Diffusion est une intelligence artificielle créatrice de contenu qui permet de générer du contenu à partir d’une phrase - ce pour quoi nous allons l’utiliser - mais aussi modifier des images à partir d’instructions.

Stable Diffusion est un modèle plus pratique à utiliser depuis Python que Dall-E. Celui-ci est open-source et peut être téléchargé et réutilisé directement depuis Python. La méthode la plus pratique est d’utiliser le modèle mis à disposition sur HuggingFace. Le modèle est implémenté à travers le framework PyTorch.

PyTorch, librairie développée par Meta, n’est pas implementé directement en Python pour des raisons de performance mais en C++ - Python étant un langage lent, le revers de la médaille de sa facilité d’usage. A travers Python, on va utiliser une API haut niveau qui va contrôler la structure des réseaux de neurones ou créer une interface entre des données (sous forme d’array Numpy) et le modèle. Pour ce type de packages qui utilisent un langage compilé, l’installation via Pandas

Configuration spécifique à Colab 👇

Sur Colab, conda n’est pas disponible par défaut. Pour pouvoir installer un package en utilisant conda sur Colab, on utilise donc l’astuce suivante :

!pip install -q condacolab
import condacolab
condacolab.install()

3.1 Installation de PyTorch

Pour installer PyTorch, la librairie de Deep Learning développée par Meta, il suffit de suivre les recommandations sur le site web officiel. Dans un Notebook, cela prendra la forme suivante :

!conda install mamba
!mamba install pytorch torchvision torchaudio cudatoolkit=10.2 -c pytorch

3.2 Accès à HuggingFace

La question - non négligeable - de l’accès à de la GPU mise à part, la réutilisation des modèles de Stable Diffusion est très facile car la documentation mise à disposition sur HuggingFace est très bien faite.

La première étape est de se créer un compte sur HuggingFace et se créer un token3. Ce token sera donné à l’API de HuggingFace pour s’authentifier.

L’API d’HuggingFace nécessite l’installation du package diffusers. Dans un Notebook, le code suivant permet d’installer la librairie requise:

!pip install --upgrade diffusers transformers scipy accelerate
import os

HF_TOKEN = os.getenv("HF_PAT")

4 Générer une image

On va créer l’image suivante :

“Chuck Norris fighting against Zeus on Mount Olympus in an epic Mortal Kombat scene”

Pas mal comme scénario, non ?!

import torch

generator = torch.Generator("cuda").manual_seed(123)

Si vous voulez vous amuser à explorer différents résultats pour un même texte, vous pouvez ne pas fixer de racine aléatoire. Dans ce cas, retirer l’argument generator des codes présentés ultérieurement.

Nous allons donc utiliser l’instruction suivante :

prompt = (
    "Chuck Norris fighting against Zeus on Mount Olympus in an epic Mortal Kombat scene"
)

L’initialisation du modèle se fait de la manière suivante :

import torch
from torch import autocast
from diffusers import StableDiffusionPipeline

model_id = "CompVis/stable-diffusion-v1-4"
device = "cuda"

generator = torch.Generator("cuda").manual_seed(1024)

Enfin, pour générer l’image:

pipe = StableDiffusionPipeline.from_pretrained(
    model_id, use_auth_token=HF_TOKEN, generator=generator
)
pipe = pipe.to(device)

with autocast("cuda"):
    image = pipe(prompt, guidance_scale=7.5, generator=generator)["images"][0]


image.save("featured.png")

Qui peut être visualisé avec le code suivant, dans un notebook:

from IPython.display import Image

pil_img = Image(filename="featured.png")
display(pil_img)

C’est une représentation assez fidèle du pitch “Chuck Norris fighting against Zeus on Mount Olympus in an epic Mortal Kombat scene” :boom:. Y a un petit côté Les Dix Commandements que j’aime bien.

En voici une autre que j’aime bien (mais malheureusement je ne peux la reproduire car je n’ai pas gardé en mémoire la racine l’ayant généré :sob:)

Il est également possible de générer plusieurs images du même texte (voir la note de blog de l’équipe à l’origine de Stable Diffusion). Cependant, c’est assez exigeant en mémoire et cela risque d’être impossible sur Colab (y compris en réduisant le poids des vecteurs numériques comme proposé dans le post)

5 Bonus

Pour le plaisir, voici PuppyMan, le dernier né du Marvel Universe:

prompt = "In a new Marvel film we discover puppyman a new super hero that is half man half bulldog"
import torch
from torch import autocast
from diffusers import StableDiffusionPipeline

model_id = "CompVis/stable-diffusion-v1-4"
device = "cuda"

generator = torch.Generator("cuda").manual_seed(1024)

pipe = StableDiffusionPipeline.from_pretrained(
    model_id, use_auth_token=HF_TOKEN, generator=generator
)
pipe = pipe.to(device)

with autocast("cuda"):
    image = pipe(prompt, guidance_scale=7.5, generator=generator)["images"][0]


image.save("puppyman.png")

La moitié humain semble être son costume de super-héros, pas la bipédie. Mais le rendu est quand même épatant !

A vous de jouer :hugging_face:

6 Références

Rombach, Robin, Andreas Blattmann, Dominik Lorenz, Patrick Esser, and Björn Ommer. 2022. “High-Resolution Image Synthesis with Latent Diffusion Models.” In Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR), 10684–95.

Informations additionnelles

environment files have been tested on.

Latest built version: 2024-04-27

Python version used:

'3.11.6 | packaged by conda-forge | (main, Oct  3 2023, 10:40:35) [GCC 12.3.0]'
Package Version
affine 2.4.0
aiobotocore 2.12.2
aiohttp 3.9.3
aioitertools 0.11.0
aiosignal 1.3.1
alembic 1.13.1
aniso8601 9.0.1
annotated-types 0.6.0
appdirs 1.4.4
archspec 0.2.3
astroid 3.1.0
asttokens 2.4.1
attrs 23.2.0
Babel 2.14.0
bcrypt 4.1.2
beautifulsoup4 4.12.3
black 24.4.2
blinker 1.7.0
blis 0.7.11
bokeh 3.4.0
boltons 23.1.1
boto3 1.34.51
botocore 1.34.51
branca 0.7.1
Brotli 1.1.0
cachetools 5.3.3
cartiflette 0.0.2
Cartopy 0.23.0
catalogue 2.0.10
cattrs 23.2.3
certifi 2024.2.2
cffi 1.16.0
charset-normalizer 3.3.2
chromedriver-autoinstaller 0.6.4
click 8.1.7
click-plugins 1.1.1
cligj 0.7.2
cloudpathlib 0.16.0
cloudpickle 3.0.0
colorama 0.4.6
comm 0.2.2
commonmark 0.9.1
conda 24.3.0
conda-libmamba-solver 24.1.0
conda-package-handling 2.2.0
conda_package_streaming 0.9.0
confection 0.1.4
contextily 1.6.0
contourpy 1.2.1
cryptography 42.0.5
cycler 0.12.1
cymem 2.0.8
cytoolz 0.12.3
dask 2024.4.1
dask-expr 1.0.10
debugpy 1.8.1
decorator 5.1.1
dill 0.3.8
distributed 2024.4.1
distro 1.9.0
docker 7.0.0
duckdb 0.10.1
en-core-web-sm 3.7.1
entrypoints 0.4
et-xmlfile 1.1.0
exceptiongroup 1.2.0
executing 2.0.1
fastjsonschema 2.19.1
fiona 1.9.6
flake8 7.0.0
Flask 3.0.2
folium 0.16.0
fontawesomefree 6.5.1
fonttools 4.51.0
fr-core-news-sm 3.7.0
frozenlist 1.4.1
fsspec 2023.12.2
GDAL 3.8.4
gensim 4.3.2
geographiclib 2.0
geopandas 0.12.2
geoplot 0.5.1
geopy 2.4.1
gitdb 4.0.11
GitPython 3.1.43
google-auth 2.29.0
graphene 3.3
graphql-core 3.2.3
graphql-relay 3.2.0
graphviz 0.20.3
great-tables 0.5.0
greenlet 3.0.3
gunicorn 21.2.0
h11 0.14.0
htmltools 0.5.1
hvac 2.1.0
idna 3.6
imageio 2.34.1
importlib_metadata 7.1.0
importlib_resources 6.4.0
inflate64 1.0.0
ipykernel 6.29.3
ipython 8.22.2
ipywidgets 8.1.2
isort 5.13.2
itsdangerous 2.1.2
jedi 0.19.1
Jinja2 3.1.3
jmespath 1.0.1
joblib 1.3.2
jsonpatch 1.33
jsonpointer 2.4
jsonschema 4.21.1
jsonschema-specifications 2023.12.1
jupyter-cache 1.0.0
jupyter_client 8.6.1
jupyter_core 5.7.2
jupyterlab_widgets 3.0.10
kaleido 0.2.1
kiwisolver 1.4.5
kubernetes 29.0.0
langcodes 3.4.0
language_data 1.2.0
lazy_loader 0.4
libmambapy 1.5.7
llvmlite 0.42.0
locket 1.0.0
lxml 5.2.1
lz4 4.3.3
Mako 1.3.2
mamba 1.5.7
mapclassify 2.6.1
marisa-trie 1.1.0
Markdown 3.6
MarkupSafe 2.1.5
matplotlib 3.8.3
matplotlib-inline 0.1.6
mccabe 0.7.0
menuinst 2.0.2
mercantile 1.2.1
mizani 0.11.2
mlflow 2.11.3
mlflow-skinny 2.11.3
msgpack 1.0.7
multidict 6.0.5
multivolumefile 0.2.3
munkres 1.1.4
murmurhash 1.0.10
mypy 1.9.0
mypy-extensions 1.0.0
nbclient 0.10.0
nbformat 5.10.4
nest_asyncio 1.6.0
networkx 3.3
nltk 3.8.1
numba 0.59.1
numpy 1.26.4
oauthlib 3.2.2
opencv-python-headless 4.9.0.80
openpyxl 3.1.2
outcome 1.3.0.post0
OWSLib 0.28.1
packaging 23.2
pandas 2.2.1
paramiko 3.4.0
parso 0.8.4
partd 1.4.1
pathspec 0.12.1
patsy 0.5.6
Pebble 5.0.7
pexpect 4.9.0
pickleshare 0.7.5
pillow 10.3.0
pip 24.0
pkgutil_resolve_name 1.3.10
platformdirs 4.2.0
plotly 5.19.0
plotnine 0.13.5
pluggy 1.4.0
polars 0.20.18
preshed 3.0.9
prometheus_client 0.20.0
prometheus-flask-exporter 0.23.0
prompt-toolkit 3.0.42
protobuf 4.25.3
psutil 5.9.8
ptyprocess 0.7.0
pure-eval 0.2.2
py7zr 0.20.8
pyarrow 15.0.0
pyarrow-hotfix 0.6
pyasn1 0.5.1
pyasn1-modules 0.3.0
pybcj 1.0.2
pycodestyle 2.11.1
pycosat 0.6.6
pycparser 2.21
pycryptodomex 3.20.0
pydantic 2.7.1
pydantic_core 2.18.2
pyflakes 3.2.0
Pygments 2.17.2
PyJWT 2.8.0
pylint 3.1.0
PyNaCl 1.5.0
pynsee 0.1.7
pyOpenSSL 24.0.0
pyparsing 3.1.2
pyppmd 1.1.0
pyproj 3.6.1
pyshp 2.3.1
PySocks 1.7.1
python-dateutil 2.9.0
python-dotenv 1.0.1
python-magic 0.4.27
pytz 2024.1
pyu2f 0.1.5
pywaffle 1.1.0
PyYAML 6.0.1
pyzmq 25.1.2
pyzstd 0.15.10
QtPy 2.4.1
querystring-parser 1.2.4
rasterio 1.3.10
referencing 0.34.0
regex 2023.12.25
requests 2.31.0
requests-cache 1.2.0
requests-oauthlib 2.0.0
rpds-py 0.18.0
rsa 4.9
Rtree 1.2.0
ruamel.yaml 0.18.6
ruamel.yaml.clib 0.2.8
s3fs 2023.12.2
s3transfer 0.10.1
scikit-image 0.23.2
scikit-learn 1.4.1.post1
scipy 1.13.0
seaborn 0.13.2
selenium 4.20.0
setuptools 69.2.0
shapely 2.0.3
six 1.16.0
smart-open 6.4.0
smmap 5.0.0
sniffio 1.3.1
snuggs 1.4.7
sortedcontainers 2.4.0
soupsieve 2.5
spacy 3.7.4
spacy-legacy 3.0.12
spacy-loggers 1.0.5
SQLAlchemy 2.0.29
sqlparse 0.4.4
srsly 2.4.8
stack-data 0.6.2
statsmodels 0.14.1
tabulate 0.9.0
tblib 3.0.0
tenacity 8.2.3
texttable 1.7.0
thinc 8.2.3
threadpoolctl 3.4.0
tifffile 2024.4.24
tomli 2.0.1
tomlkit 0.12.4
toolz 0.12.1
topojson 1.8
tornado 6.4
tqdm 4.66.2
traitlets 5.14.2
trio 0.25.0
trio-websocket 0.11.1
truststore 0.8.0
typer 0.9.4
typing_extensions 4.11.0
tzdata 2024.1
Unidecode 1.3.8
url-normalize 1.4.3
urllib3 1.26.18
wasabi 1.1.2
wcwidth 0.2.13
weasel 0.3.4
webcolors 1.13
webdriver-manager 4.0.1
websocket-client 1.7.0
Werkzeug 3.0.2
wheel 0.43.0
widgetsnbextension 4.0.10
wordcloud 1.9.3
wrapt 1.16.0
wsproto 1.2.0
xgboost 2.0.3
xlrd 2.0.1
xyzservices 2024.4.0
yarl 1.9.4
yellowbrick 1.5
zict 3.0.0
zipp 3.17.0
zstandard 0.22.0

View file history

SHA Date Author Description
005d89b 2023-12-20 17:23:04 Lino Galiana Finalise l’affichage des statistiques Git (#478)
3fba612 2023-12-17 18:16:42 Lino Galiana Remove some badges from python (#476)
1f23de2 2023-12-01 17:25:36 Lino Galiana Stockage des images sur S3 (#466)
a06a268 2023-11-23 18:23:28 Antoine Palazzolo 2ème relectures chapitres ML (#457)
69cf52b 2023-11-21 16:12:37 Antoine Palazzolo [On-going] Suggestions chapitres modélisation (#452)
a771183 2023-10-09 11:27:45 Antoine Palazzolo Relecture TD2 par Antoine (#418)
154f09e 2023-09-26 14:59:11 Antoine Palazzolo Des typos corrigées par Antoine (#411)
8082302 2023-08-25 17:48:36 Lino Galiana Mise à jour des scripts de construction des notebooks (#395)
3bdf3b0 2023-08-25 11:23:02 Lino Galiana Simplification de la structure 🤓 (#393)
29ff3f5 2023-07-07 14:17:53 linogaliana description everywhere
9918817 2022-12-30 15:10:59 Lino Galiana Retour sur le chapitre DallE / StableDiffusion (#344)
86b77e7 2022-12-30 08:40:27 lgaliana openAI
d8eafc9 2022-12-30 08:38:06 lgaliana dallE
8f24e44 2022-12-30 08:34:25 lgaliana dallE
742add1 2022-09-03 18:33:41 Lino Galiana Corrige quelques coquilles dans le tutoriel DallE (#266)
82254fe 2022-08-26 16:11:40 Lino Galiana Chapitre sur Dall-E (#261)
Back to top

Footnotes

  1. Il est notamment possible de réutiliser l’image générée à des fins commerciales. En revanche, il est interdit de chercher à nuire à une personne. Pour cette raison, il est fréquent que les visages de personnes célèbres soient floutés pour éviter la création de contenu nuisant à leur réputation.↩︎

  2. Comme les autres plateformes du monde de la data science, HuggingFace a adopté l’utilisation standardisée des jetons (token) comme méthode d’authentification. Le jeton est comme un mot de passe sauf qu’il n’est pas inventé par l’utilisateur (ce qui permet qu’il ne soit pas partagé avec d’autres sites web potentiellement moins sécurisés), est révocable (date d’expiration ou choix de l’utilisateur) et dispose de droits moins importants qu’un mot de passe qui vous permet, potentiellement, de changer tous les paramètres de votre compte. Je recommande vivement l’utilisation d’un gestionnaire de mot de passe pour stocker vos token (si vous utilisez Git, Docker, etc. vous en avez potentiellement beaucoup) plutôt que stocker ces jetons dans des fichiers non sécurisés.↩︎

  3. Comme les autres plateformes du monde de la data science, HuggingFace a adopté l’utilisation standardisée des jetons (token) comme méthode d’authentification. Le jeton est comme un mot de passe sauf qu’il n’est pas inventé par l’utilisateur (ce qui permet qu’il ne soit pas partagé avec d’autres sites web potentiellement moins sécurisés), est révocable (date d’expiration ou choix de l’utilisateur) et dispose de droits moins importants qu’un mot de passe qui vous permet, potentiellement, de changer tous les paramètres de votre compte. Je recommande vivement l’utilisation d’un gestionnaire de mot de passe pour stocker vos token (si vous utilisez Git, Docker, etc. vous en avez potentiellement beaucoup) plutôt que stocker ces jetons dans des fichiers non sécurisés.↩︎

Citation

BibTeX citation:
@book{galiana2023,
  author = {Galiana, Lino},
  title = {Python Pour La Data Science},
  date = {2023},
  url = {https://pythonds.linogaliana.fr/},
  doi = {10.5281/zenodo.8229676},
  langid = {en}
}
For attribution, please cite this work as:
Galiana, Lino. 2023. Python Pour La Data Science. https://doi.org/10.5281/zenodo.8229676.