Aller au contenu

Le module PIL - Rappels

Le module PIL permet de manipuler un grand nombre de formats d'images. Ce module n'est pas inclus d'office dans Python, il faut télécharger puis installer la bibliothèque pillow. Pour cela, on peut utiliser pip :

>>> pip install pillow
ou sur un environnement Gnu / Linux :

sudo apt install python3-pil

Pour plus d'informations sur les possibilités de ce module, on pourra consulter le site de référence.

Dans cette page de rappels, vous allez travailler sur l'image ci-dessous (nommée Logo_NSI.png) après l'avoir enregistrée dans le même répertoire que le programme Python.

Logo NSI

Manipuler des fichiers externes avec Python

Le langage Python permet de créer, d'ouvrir et de manipuler des fichiers. En utilisant un IDE (interface de développement), le répertoire courant n'est pas forcément bien identifié.

La bibliothèque os comporte de nombreuses commandes permettant d'interagir avec le système d'exploitation.
Voici les instructions à placer en début de programme qui permettent de se placer dans le répertoire courant si besoin :

1
2
3
4
import os           # Importation du module
rep = os.getcwd()    # Obtenir le chemin du répertoire courant, c'est-à-dire
                   # celui qui contient le fichier .py du programme
os.chdir(rep)        # Changer de répertoire courant

Obtenir des informations sur une image

Copier/coller le code ci-dessous dans un programme Python :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Importation du module
from PIL import Image

# Importation/ouverture de l'image
# Pour pouvoir être "manipulée", cette image est affectée à une variable intitulée source (dans cet exemple)
source = Image.open('Logo_NSI.png')

# Récupération des dimensions
largeur, hauteur = source.size
print(f"Le nombre de colonnes est {largeur}, le nombre de lignes est {hauteur}.")

# Récupération de l'encodage
encodage = source.mode
print(f"L'encodage des couleurs est {encodage}.")

# récupération de la couleur du pixel supérieur gauche :
couleur_pixel_haut_gauche = source.getpixel( (0, 0) )
print(f"Le pixel en haut à gauche (colonne 0, ligne 0) a pour couleur {couleur_pixel_haut_gauche}.")

# récupération de la couleur du pixel inférieur droit :
couleur_pixel_bas_droit = source.getpixel( (largeur-1, hauteur-1) )
print(f"Le pixel en bas à droite (colonne {largeur-1}, ligne {hauteur-1}) a pour couleur {couleur_pixel_bas_droit}.")

Après exécution, ce programme affiche :

Le nombre de colonnes est 400, le nombre de lignes est 250.
L'encodage des couleurs est RGB.
Le pixel en haut à gauche (colonne 0, ligne 0) a pour couleur (255, 255, 255).
Le pixel en bas à droite (colonne 399, ligne 249) a pour couleur (255, 255, 255).

Résumé

On considère que l'image est affectée à la variable source.

  1. source.mode permet d'obtenir l'encodage des couleurs d'une image. La valeur renvoyée peut être :

    • 'RGBA' : couleurs avec gestion de la transparence (quadruplet d'entiers compris entre 0 et 255) ;
    • 'RGB' : couleurs sur trois composantes (triplet d'entiers compris entre 0 et 255) ;
    • 'L' : nuances de gris (un entier compris entre 0 et 255) ;
    • '1' (le chiffre « 1 ») : noir & blanc (un entier, soit 0, soit 1).
  2. source.size permet d'obtenir les dimensions de l'image (en pixels) sous forme d'un tuple (largeur, hauteur).

    Logo IREM

  3. Les coordonnées d'un pixel sont représentées par le couple (x, y). L'illustration ci-contre présente comment sont repérés les pixels d'une image. Les coordonnées du pixel rouge de cette image sont donc (3, 1).

  4. Pour récupérer (et stocker dans une variable nommée couleur) la couleur du pixel de coordonnées (x, y), on utilise l'instruction :

    couleur = source.getpixel( (x, y) )
    
    Selon l'encodage couleur de l'image (cf. point 1.), la variable couleur peut être un quadruplet (mode RGBA), un triplet (mode RGB) ou un entier (modes L ou 1).

Modifier une image existante

Téléchargez l'image ci-dessous (clic droit, enregistrer sous...) dans votre répertoire courant :

Logo NSI

Nous allons voir comment remplacer la couleur marron par un « joli » bleu.

Logo NSI bleu

Le principe pour réaliser cette transformation :

  1. Parcourir chaque pixel de l'image.
  2. Pour chaque pixel parcouru, remplacer les composantes (155, 63, 52) par (20, 60, 153).
    Pour cela :
    • on récupère le triplet du pixel grâce à la méthode .getpixel() ;
    • on injecte à la place le nouveau triplet grâce à la méthode .putpixel( (abscisse, ordonnee), composantes ).
  3. On sauvegarde ensuite l'image sous un nouveau nom puis on l'affiche à l'écran.

Copiez/collez/complétez le code ci-dessous afin de faire apparaître le logo modifié.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
from PIL import Image

# ouverture de l'image :
source = Image.open('Logo_NSI.png')

# récupération de ses dimensions :
largeur, hauteur = source.size


# parcours des pixels de l'image :

for ...
    for ...
        ...
        ...

source.save('Logo_NSI_bleu.png')
source.show()
Une solution
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
from PIL import Image

# ouverture de l'image:
source = Image.open('Logo_NSI.png')

# récupération de ses dimensions :
largeur, hauteur = source.size

for ligne in range(hauteur):
    for colonne in range(largeur):
        couleur = source.getpixel( (colonne, ligne) )
        if couleur == (155, 63, 52):
            source.putpixel( (colonne, ligne), (20, 60, 153) )

source.save('Logo_NSI_bleu.png')
source.show()

Une image à partir de rien

image en noir et blanc Le module PIL permet de créer très facilement une image « ex nihilo » en suivant ce protocole :

  1. Importer le module PIL.
  2. Définir les propriétés de l'image (dimensions et encodage de couleur).
  3. Créer et stocker la nouvelle image dans une variable à l'aide de l'instruction Image.new(encodage, dimensions).
  4. Parcourir chaque pixel de l'image pour le coloriser.
  5. Sauvegarder puis afficher l'image ainsi conçue.

Créez une image de dimension 100 x 100 au format « nuances de gris » (L) dans laquelle chaque pixel est soit blanc, soit noir. La probabilité d'apparition d'un pixel noir est 30 %.

Une solution
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from random import random
from PIL import Image

# Variables et constantes :
taille_image = 100
encodage = 'L'
dimensions = (taille_image, taille_image)
proba = 0.3

# Définition de la nouvelle image :
resultat = Image.new(encodage, dimensions)

# Colorisation des pixels de l'image :
for x in range(taille_image):
    for y in range(taille_image):
        nb = random()
        if nb < proba:
            resultat.putpixel((x, y), 0)
        else :
            resultat.putpixel((x, y), 255)

resultat.save('image_nb.png')
resultat.show()