Python - Manipulation d'images
LE FONCTIONNEMENT DES COULEURS ET DES PIXELS
Avant de commencer à parler de PIL, voici un petit préambule explicatif sur le fonctionnement des pixels et des couleurs en programmation 🙂 ET une seconde partie sur la manipulation d’images en programmation (à lire avant de commencer à programmer !!)
Qu’est ce qu’un pixel ?
Les pixels, ce sont ces touts petites lumières qui composent ton écran et qui changent de couleur en fonction de ce qu’ils doivent afficher. C’est le composant principal de l’écran de ton ordi, de ton téléphone, de ta télé, etc…
D’ailleurs, quand on parle de résolution d’écran, on parle du nombre de pixels sur ce dernier ! Une résolution de 1920×1080 correspond à 1920 pixels de large pour 1080 pixels de haut sur ton écran !
Le pixel est aussi l’unité de mesure par défaut pour les images numériques ! 🙂 Une image de 200×200 mesure 200 pixels de côté !
De nos jours, les pixels peuvent afficher une palette d’à peu près 16 millions de couleurs. On garde cette info en tête pour un peu plus tard 😉
Cependant, un pixel n’affiche pas 16 millions de couleurs comme par magie !
Pour ça, il est décomposé en 3 parties, une pour chaque couleur primaire :
- Une partie qui affiche le Rouge (Red)
- Une partie qui affiche le Vert (Green)
- Une partie qui affiche le Bleu (Blue)
C’est ce qui nous donne ce qu’on appelle un code RGB (ou RVB en français) !
On ne peut pas voir à l’œil nu les trois couleurs primaires d’un pixel, mais en se mélangeant, ces trois couleurs peuvent former n’importe quelle couleur ! On va voir ça plus en détail dans le paragraphe en dessous 😉
Le code RGB
Comme expliqué au dessus, les pixels d’un écran sont composés des trois couleurs primaires, et en se mélangeant peuvent former n’importe quelle couleur. C’est le code RGB (Red Green Blue) !
Chaque couleur d’un pixel est codée sur 256 valeurs, allant de 0 à 255.
Comme on a trois couleurs, et que chacune peut prendre 256 valeurs, si on calcule le nombre total de couleurs qu’on peut faire : 256 * 256 * 256 = 16 777 216 couleurs différentes !
Donc un peux plus de 16 millions de couleurs différentes, comme on le disait juste un peu avant 😉
Voici quelques exemples de couleurs basiques avec leur code RGB pour que tu puisses te donner une idée !
Un code RGB s’écrit comme ceci : (R, G, B), où les lettres correspondent à la valeur de chaque couleur primaire 🙂
MANIPULER DES IMAGES EN PROGRAMMATION
Quand tu manipules des images en Python, tu vas noter dans ton code le chemin pour accéder à une image que tu as envie d’ouvrir. Si tu notes juste le nom de l’image, le programme va aller chercher dans le même dossier que le code pour trouver ton image. Il faut donc que ton image soit enregistré sur ton ordinateur au bon endroit pour l’ouvrir facilement !
Sur Repl.it, c’est pareil ! Il faut que ton image soit dans le même dossier que ton code pour l’ouvrir facilement. Il faut donc que tu l’importes dans Repl.it.
On va ouvrir une image avec le mot clé « open » (expliqué dans le bloc suivant). Voici deux exemples :
si tu es sur ton ordinateur et que tu programmes sur un éditeur comme SublimeText ou Atom
si tu utilises l’outil en ligne repl.it
ET voici comment importer une image sur l’outil Repl.it :
Si l’image n’est pas bien rangée (ou que tu as mal écrit son nom), tu auras ce message d’erreurs :
Python Imaging Library, est une bibliothèque pour Python qui permet de manipuler des images.
N’oublie pas d’importer le module avant chaque programme que tu crées !
/!\ Attention, avec l’outil Repl.it tu ne pourras pas montrer l’image avec « show », il te faudra sauvegarder l’image pour voir le rendu 😉
LES BASES DE PIL
Importer le module !!
Avant de faire quoi que ce soit, il est très important d’importer le module PIL en haut de ton programme Python !!
Afficher une image
Pour afficher une image, on doit d’abord la récupérer avec Image.open(« nomDeTonImage »), la stocker dans une variable. Puis on peut l’afficher avec image.show().
Sauvegarder une image
Pour sauvegarder une image, il suffit d’écrire image.save(« nomImage.png »)
Changer le mode
Il existe plusieurs modes de couleur d’une image:
- nuance de gris: l’image est grisée, les composantes des couleurs (rouge, vert & bleu) sont toutes égales
- en couleur: le mélange des couleurs rouge, verte & bleue forment un pixel de l’image
- en noir et blanc: chaque pixel est soit noir, soit blanc
Modifier la taille
La fonction ancienneimage.resize() permet de modifier la taille de l’image
Tourner l’image
On peut effectuer des rotations en degré avec la fonction ancienneimage.rotate().
Les coordonnées d’une image en Python
En Python, mais plus généralement en programmation, les coordonnées sont un peu différentes de ce qu’on connaît en maths classiques.
Comme tu peux le voir sur l’image de gauche, l’axe des ordonnées (Y) vas vers le bas au lieu d’aller vers le haut 🙂
L’origine de l’image est donc le point en haut à gauche de celle-ci !
C’est très important de savoir ça pour la suite, car on se sert des coordonnées des images dans les prochaines fonctions
Recadrer l’image
Pour recadrer une image, on utilise la fonction ancienneimage.crop() où on indique le point en haut à gauche (x,y) et le point en bas à droite (x,y) du nouveau cadre de la photo.
Intégrer une image dans une autre image
Pour copier une image dans une autre, on va utiliser la fonction image1.paste(image2, endroit). L’endroit doit être un rectangle dont on spécifie le coin supérieur gauche (x,y) et le coin inférieur droit (x,y).
Attention ! la fonction paste ne renvoie pas d’image, il ne faut donc pas faire image = image.paste(…) mais juste image.paste(…)
LES FILTRES
Module ImageFilter
Ce module te permet d’ajouter toutes sortes de filtres à tes images ! Modification des couleurs, de la netteté, ajout de flou, etc… Bref, tu vas t’amuser 😉
Sur tous les prochains exemples, tu verras un comparatif de l’image originale (à gauche) et de l’image modifiée (à droite) !
Penses à importer le module en haut de ton code 😉
Filtre Contour
Le filtre Contour permet de mettre en valeur les contours repérés dans ton image.
Filtre Edge_Enhance
Le filtre Edge_Enhance permet d’accentuer les contours de ton image.
Filtre Edge_Enhance_More
Le filtre contour fort permet d’accentuer fortement les contours de ton image.
Filtre Detail
Le filtre détail permet d’augmenter les détails de ton image.
Filtre Find_Edges
Le filtre Find_Edges permet de repérer où sont les contrastes forts entre 2 pixels, et les met en valeur.
Filtre Sharpen
Le filtre Sharpen permet d’augmenter la netteté d’une image.
Filtre Blur (flou)
Le filtre Blur permet de rendre ton image un peu floue.
Filtre Smooth (Flou)
Le filtre Smooth permet de lisser ton image.
Filtre Smooth_More (Flou)
Le filtre Smooth_More permet de lisser fortement ton image.
Plus on applique le filtre sur une image, plus on la transforme !
Voici le résultat après avoir appliqué le filtre trois fois d’affilée :
Filtre Smooth_More (Flou)
Le filtre Smooth_More permet de lisser fortement ton image.
Voici l’image après avoir appliqué le flou gaussien avec un argument égal à 20 !
Filtre ModeFilter (Flou)
Le filtre ModeFilter permet de modifier les couleurs dans un rayon que l’on donne en paramètre. Ainsi on obtient un rendu très flou avec de belles couleurs !
Module ImageOps
Ce module contient quelques fonctions de traitement d’images toutes faites, qui te permettront d’ajouter des effets cools à tes images, que des filtres ne pourraient pas faire ! 🙂
Sur tous les prochains exemples, tu verras un comparatif de l’image originale (à gauche) et de l’image modifiée (à droite) !
Penses à importer le module en haut de ton code 😉
Flip une image
La fonction ImageOps.flip(ancienneimage) permet de faire une symétrie horizontale de ton image.
Miroir
Pour faire un effet « miroir » sur ton image, il suffit de commencer par la retourner avec la fonction Flip (juste au dessus), et ensuite de la tourner de 180 degrés 🙂
Ajouter un bord
Avec le sous-module ImageOps de PIL, on peut dessiner un contour à notre image. On définit la largeur du contour en argument (à la place du « 10 » dans notre exemple).
Inverser les couleurs de l’image
Cet effet permet d’inverser les couleurs de ton image: le noir devient blanc et le blanc devient noir.
Inverser certaines couleurs de l’image
L’effet solarize te permet d’inverser les couleurs de l’image, mais seulement à partir d’un certain point.
Comme les couleurs sont codées sur 255 valeurs, on peut choisir la valeur à partir de laquelle la couleur sera inversée.
Sur le code ci-dessous, on inverse les couleurs qui ont une valeur supérieure à 128 🙂
Modifier le contraste
Cet effet te permet d’augmenter les contrastes d’une image : il enlèvera un pourcentage (donné en paramètre) des pixels les plus sombres et les plus clairs d’une image 🙂
Dans cet exemple, on enlève 10% des pixels sombres et clairs !
FUSION D’IMAGES
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.
Coller une image sur une autre
On peut coller une image sur une autre avec la fonction monImage.alpha_composite().
Le fonctionnement est assez simple :
- Premièrement, l’image de base et celle qu’on veut coller par dessus doivent être en mode RGBA.
- Ensuite, il suffit d’utiliser la fonction alpha_composite() de l’image sur laquelle on veut faire le collage. En l’occurrence, je veux mettre imageChat par dessus imagePlage, j’écris donc imagePlage.alpha_composite()
- Enfin, on doit choisir le pixel de destination de l’image à coller sur l’image de base. Sur l’exemple, je l’envoie en (0, 0), donc tout en haut à gauche (cf. le récap sur les coordonnées d’une image si tu ne te rappelles plus trop comment ça marche !).
Mélanger deux images
Pour mélanger 2 images, il faut qu’elles aient le même mode et la même taille.
Puis on utilise Image.blend(image1, image2, pourcentage). Le pourcentage correspond à la visibilité de l’image 1 à l’intérieur de l’image 2: plus il est élevé, plus on verra l’image 1.
Module ImageChops
Le module ImageChops te permet de fusionner deux images avec des effets de fusion différents
Sur tous les prochains exemples, tu verras un comparatif des deux images originales, puis du résultat de la fusion !
Penses à importer le module en haut de ton code 😉
Fusionner en ajoutant les couleurs
La fonction ImageChops.add(image1, image2) te permet de fusionner deux images en ajoutant les couleurs de tous leurs pixels.
Par exemple, si un pixel est gris sur la première image (100,100,100) et turquoise sur la deuxième (0,200,200), le nouveau pixel sera égal à la somme des deux (avec toujours un max de 255 par valeur).
Le nouveau pixel sera donc égal à (0,255,100) ! C’est pour ça que le résultat des deux images ci-dessous est si blanc : comme l’image de chat a beaucoup de pixels blancs de base (255,255,255), avec la somme de la deuxième photo, le rendu final est très blanc 🙂
Darker
La fonction ImageChops.darker(image1, image2) va parcourir chaque pixel des deux images, et ne va garder que le pixel le plus sombre pour le rendu final.
Lighter
La fonction ImageChops.lighter(image1, image2) va parcourir chaque pixel des deux images, et ne va garder que le pixel le plus clair pour le rendu final.
Difference
La fonction ImageChops.difference(image1, image2) va parcourir chaque pixel des deux images, et va faire la différence des couleurs des deux pixels pour le rendu final.
Par exemple, si un pixel est blanc (255, 255, 255) et l’autre est bleu (0, 0, 255), le pixel final sera jaune (255, 255, 0) !
Multiply
La fonction ImageChops.multiply(image1, image2) va fusionner les deux images en gardant toutes les couleurs principales des deux images, pour un rendu final le plus propre possible 🙂
AJOUTER DU TEXTE ET DES DESSINS
Ajouter du texte dans une image
Pour commencer, il ne faut pas oublier d’importer les deux modules ImageFont et ImageDraw en haut de ton code.
ImageFont te permettra d’importer une police de caractères personnelle.
ImageDraw te permettra de dessiner et d’écrire sur ton image.
Une fois ta police téléchargée, tu dois placer le fichier de la police dans le dossier de ton code !
Pour aller chercher des polices sympas, tu peux aller sur ces deux sites qui proposent des polices gratuites :
Au niveau du code, c’est très simple !
Tu dois d’abord charger la police grâce à ImageFont, puis tu dois créer une variable ImageDraw qui te servira à écrire sur l’image que tu veux.
Pour finir, grâce à cette variable, tu pourras écrire ton texte en précisant les coordonnées où tu veux le placer sur l’image, le texte en lui même, la police que tu veux utiliser, ainsi que la couleur du texte !
ellipse()
La fonction ellipse() nous permet de dessiner un cercle ou un ovale.
Il y a 3 paramètres à fournir :
- xy, qui correspond à 4 coordonnées. Les deux premières sont le X et le Y du point le plus en haut à gauche du cercle ; Les deux dernières sont le X et le Y du point le plus en bas à droite du cercle.
- outline, qui correspond à la couleur de la ligne extérieure du cercle
- fill, qui correspond à la couleur intérieure du cercle
rectangle()
La fonction rectangle() nous permet de dessiner un carré ou un rectangle.
Il y a 3 paramètres à fournir :
- xy, qui correspond à 4 coordonnées. Les deux premières sont le X et le Y du point le plus en haut à gauche du rectangle ; Les deux dernières sont le X et le Y du point le plus en bas à droite du rectangle
- outline, qui correspond à la couleur de la ligne extérieure du rectangle
- fill, qui correspond à la couleur intérieure du rectangle
point()
La fonction point() nous permet de dessiner un point à des coordonnées précises.
Il y a 2 paramètres à fournir :
- xy, qui correspond à 2 coordonnées : Le X et le Y du point
- fill, qui correspond à la couleur du point
Si on combine cette fonction à une boucle, on peut par exemple tracer une diagonale de plein de points 🙂
SCREENSHOT & WEBCAM
Dans cette section, tu vas découvrir comment faire une capture d’écran avec PIL ou utiliser la webcam avec OpenCV !
/!\ Attention, avec l’outil Repl.it tu ne pourras pas accéder à la webcam /!\
Faire une capture d’écran
Utiliser la Webcam avec OpenCV
Pour prendre une photo, on va se servir d’une autre module: cv2 !
Voici un code exemple pour récupérer l’image et la préparer pour toutes les transformations avec PIL !
Attention ! Sur certains ordinateurs, il faut doubler la ligne qui prend une photo (ret, image = cam.read()). Sinon la caméra n’a pas le temps de prendre la photo et on obtient juste une image noire !
Et après, le fun c’est de modifier le selfie !
VERS L’INFINI ET AU-DELA !
Pour finir, un exemple de montage pour t’inspirer 🙂
Avec le code ci-dessous :