Pillow
La bibliothèque Python de manipulation d'images « simple ». Ouvrir, redimensionner, convertir, dessiner — en quelques lignes. C'est la brique image utilisée en interne par YOLO, scikit-image et la plupart des notebooks ML qui touchent à de la vision.
À quoi ça sert
Pillow (anciennement PIL, Python Imaging Library) est le couteau suisse pour manipuler des fichiers image en Python :
- Ouvrir et sauvegarder — JPEG, PNG, GIF, WebP, TIFF, BMP, ICO et une vingtaine d'autres formats.
- Redimensionner / recadrer — opérations basiques avant de passer une image à un modèle ML.
- Convertir — RGB ↔ niveaux de gris, mode 8-bit ↔ 16-bit, etc.
- Dessiner — texte, formes, ajouter un watermark ou une bounding box sur une image.
- Appliquer des filtres — flou, netteté, détection de contours basique (mais pour du vrai traitement d'image, on préfère OpenCV).
Pillow = manipulation simple de fichiers image,
API conviviale, image stockée comme un objet Image.
OpenCV = traitement
d'image et vision par ordinateur, plus puissant et plus rapide,
mais image stockée comme un array NumPy
au format BGR (et pas RGB — piège classique). Règle pratique :
si tu ouvres juste un fichier et le redonnes à un modèle, Pillow
suffit. Si tu fais du filtrage / détection / transformations
géométriques avancées, passe à OpenCV.
Un exemple d'usage
Tu reçois un dossier de photos hétérogènes et tu veux toutes les redimensionner à 512×512 en JPEG, prêtes pour un modèle :
from pathlib import Path
from PIL import Image
src = Path("raw")
dst = Path("prepared"); dst.mkdir(exist_ok=True)
for path in src.iterdir():
img = Image.open(path).convert("RGB")
img.thumbnail((512, 512)) # garde le ratio
img.save(dst / f"{path.stem}.jpg", quality=85)
.convert("RGB") est l'étape qui sauve la mise : certaines
images peuvent être en RGBA (avec canal alpha) ou en mode palette
(GIF) — les convertir en RGB évite des erreurs cryptiques quand on
sauve en JPEG (qui ne supporte pas l'alpha) ou qu'on les passe à un
modèle qui attend 3 canaux.
How-to : installer et utiliser Pillow
-
Installer Pillow
Dépendance principale (cf. UV) — note que la lib s'installe sous le nom
Pillowmais s'importe sous le nomPIL(héritage de PIL, l'ancêtre) :bashuv add pillowpythonfrom PIL import Image, ImageDraw, ImageFilter -
Ouvrir et inspecter une image
pythonimg = Image.open("photo.jpg") img.size # (width, height) en pixels img.mode # "RGB", "RGBA", "L" (gris), "P" (palette)… img.format # "JPEG", "PNG", … img.info # métadonnées (EXIF, DPI…)Important :
Image.openest paresseux. Il ne lit pas vraiment les pixels avant qu'on en ait besoin (utile pour parcourir un dossier vite). Pour forcer le chargement :img.load(). -
Redimensionner, recadrer, faire pivoter
python# Redimensionner à taille exacte (peut déformer) img.resize((300, 200)) # Vignette : garde le ratio, modifie l'image en place img.thumbnail((512, 512)) # Recadrer (left, top, right, bottom) img.crop((50, 50, 450, 450)) # Rotation (en degrés) img.rotate(90, expand=True) # expand=True évite le rognage # Flip / miroir img.transpose(Image.FLIP_LEFT_RIGHT) -
Convertir entre formats et modes
python# Modes de pixel img.convert("RGB") # couleur img.convert("L") # niveaux de gris img.convert("1") # noir et blanc 1 bit # Sauvegarde : le format est déduit de l'extension img.save("out.jpg", quality=90) img.save("out.png", optimize=True) img.save("out.webp", quality=80) -
Dessiner sur une image (annotations)
Particulièrement utile pour visualiser une sortie de modèle (bounding boxes YOLO, par exemple) :
pythonfrom PIL import Image, ImageDraw, ImageFont img = Image.open("photo.jpg") draw = ImageDraw.Draw(img) # Rectangle (left, top, right, bottom) draw.rectangle([(50, 50), (200, 150)], outline="red", width=3) # Texte (police par défaut) draw.text((55, 55), "chien (92%)", fill="red") img.save("annotated.jpg") -
Aller-retour avec NumPy
Indispensable quand on passe l'image à un modèle ML :
pythonimport numpy as np from PIL import Image img = Image.open("photo.jpg").convert("RGB") # Image → array NumPy (H, W, 3) en uint8 arr = np.array(img) print(arr.shape, arr.dtype) # (H, W, 3) uint8 # Array NumPy → Image img2 = Image.fromarray(arr) -
Filtres simples
pythonfrom PIL import ImageFilter img.filter(ImageFilter.BLUR) img.filter(ImageFilter.SHARPEN) img.filter(ImageFilter.FIND_EDGES) img.filter(ImageFilter.GaussianBlur(radius=5))Pour du traitement plus poussé (convolutions personnalisées, morphologie, transformations géométriques), c'est le moment de passer à OpenCV.
Aide-mémoire
from PIL import Image
img = Image.open("in.jpg").convert("RGB")
img.thumbnail((512, 512))
img.save("out.jpg", quality=85)
img.resize((w, h))
img.crop((l, t, r, b))
img.rotate(90, expand=True)
img.transpose(Image.FLIP_LEFT_RIGHT)
img.convert("L")
from PIL import ImageDraw
d = ImageDraw.Draw(img)
d.rectangle([(x1, y1), (x2, y2)], outline="red", width=3)
d.text((x, y), "label", fill="red")
Pillow et le reste de l'écosystème
-
NumPy — pont obligatoire
dès qu'on quitte le fichier image vers un calcul.
np.array(img)etImage.fromarray(arr)forment le pont aller-retour. -
OpenCV — la lib qu'on
sort dès qu'on a besoin de plus que de la manipulation de fichier.
Attention au piège du format BGR d'OpenCV : un
cv2.imread()renvoie une image en BGR, pas en RGB. - YOLO / PyTorch — la plupart des modèles vision en Python acceptent une image PIL directement en entrée. Pas besoin de convertir d'abord en tensor à la main.
-
matplotlib —
plt.imshow(np.array(img))pour afficher rapidement une image PIL dans un notebook Jupyter. -
FastAPI — pour recevoir
une image en upload : FastAPI livre un
UploadFile, on l'ouvre avecImage.open(file.file), on le passe à un modèle, on renvoie le résultat.
Beaucoup de photos prises au smartphone embarquent une orientation
dans les métadonnées EXIF (le capteur photo prend en paysage, tu
tournes le téléphone). Pillow lit les pixels « dans le sens
capteur » et n'applique pas l'orientation par défaut → ton image
peut sortir tournée à 90°. Utilise
ImageOps.exif_transpose(img) pour appliquer la
rotation indiquée par l'EXIF.
Pour aller plus loin
- Site officiel : pillow.readthedocs.io
- Handbook (intro complète) : pillow.readthedocs.io/en/stable/handbook
- Liste des formats supportés : pillow.readthedocs.io/en/stable/handbook/image-file-formats.html