NSI : 2024-2025, traitement d’images et tuples

1. Pillow : une bibliothèque de traitement d’images en Python.

Nous allons utiliser pour ce TP certaines fonctions de la bibliothèque Pillow ou PIL.
Pour en savoir plus : https://he-arc.github.io/livre-python/pillow/index.html

2. Mise en place du tp :

  • Créer un dossier TP_images,
  • Ouvrir Thonny, et copier-coller le code ci-dessous dans l’éditeur de programme,
  • enregistrer votre fichier avec le nom « TP_images » dans le dossier TP_images,
  • enregistrer dans le dossier les deux images de la Joconde ci-dessous.
from PIL import Image # on importe la classe Image et ses méthodes de la
# bibliothèque Pillow alias PIL

image = Image.open("Mona_lisa.jpg") # Chargement d'une image avec PIL
# image est déclarée comme un objet de la classe Image de PIL

def taille(img):
    return img.size # méthode propre à la classe Image

def format(img):
    return img.format # méthode propre à la classe Image

def lire_pixel(img,x,y):
    return img.getpixel((x,y)) # méthode propre à la classe Image

def changer_pixel(img,x,y,couleur):
    image=img
    image.putpixel((x,y),couleur) # méthode propre à la classe Image
    return image

def afficher(img):
    img.show() # méthode propre à la classe Image

# premieres fonctions de traitement de l'image

def eclaircir(img,e):
    image_retour=img.copy()
    (l, h) = taille(image)
    for y in range(h):
        for x in range(l):
            c = lire_pixel(image_retour,x,y)
            nouvelle_c=(c[0]+e,c[1]+e,c[2]+e)
            image_retour=changer_pixel(image_retour,x,y,nouvelle_c)
    afficher(image_retour)
    return image_retour

3. Découverte des premières fonctions.

a) Tester la commande taille(image).
Que retourne cette commande ? Quel type d’objet python est retourné par cette commande ?

b) Tester la commande format(image).
Que retourne cette commande ? Quel type d’objet python est retourné par cette commande ?

c) Tester la commande lire_pixel(image,100,100)
Que retourne cette commande ?
Quel type d’objet python est retourné ?
A votre avis quel est le système de couleur utilisé pour décrire le contenu de ce pixel ?

d) On parle un peu de format d’images :
En considérant que l’image n’est constituée que des pixels qu’elle contient, chaque pixel ayant une couleur codée sur 3 octets, déterminer la taille mémoire occupée théoriquement par l’image de Mona Lisa.
Comparer avec les informations proposées pour les 2 images que vous avez enregistrées.
Que peut-on remarquer ?

d) Tester la commande changer_pixel(image,100,100,(255,0,0)) suivie de lire_pixel(image,100,100).

e) Tester la commande afficher(image)

4. Première fonction de traitement d’image.

Tester la fonction eclaircir() avec comme premier paramètre image, et comme second respectivement les 3 valeurs 10, puis 50 et enfin -50.
Etudier cette fonction pour la suite.
Interroger vous sur la ligne 27 : image_retour=img.copy().

5. De nouvelles fonctions de traitement de l’image.

Un pixel est caractérisé par sa couleur sous la forme d’un tuple de type (R,V,B).
1) En vous inspirant de la fonction eclaircir, écrire 3 fonctions canal_R, canal_V et canal_B qui afficheront et retourneront l’image où pour chaque pixel, on n’a conservé respectivement que le canal couleur (R,0,0), (0,V,0) et (0,0,B).

2) Créer une fonction degrade_gris() qui affiche et retourne l’image où chaque canal de couleur a été remplacé par la valeur (R+V+B)/3

3) Créer une fonction symetrie() qui affiche et retourne l’image après une symétrie par rapport à l’axe vertical partageant l’image en deux.

4) Créer une fonction photo_maton() qui réalise la transformation décrite dans cet article :
https://interstices.info/mona-lisa-au-photomaton/

Proposition correction

from PIL import Image # on importe la classe Image et ses méthodes de la
# bibliothèque Pillow alias PIL

image = Image.open("Mona_lisa.jpg") # Chargement d'une image avec PIL
# image est déclarée comme un objet de la classe Image de PIL

def taille(img):
    return img.size # méthode propre à la classe Image

def format(img):
    return img.format # méthode propre à la classe Image

def lire_pixel(img,x,y):
    return img.getpixel((x,y)) # méthode propre à la classe Image

def changer_pixel(img,x,y,couleur):
    image=img
    image.putpixel((x,y),couleur) # méthode propre à la classe Image
    return image

def afficher(img):
    img.show() # méthode propre à la classe Image

# premieres fonctions de traitement de l'image

def eclaircir(img,e):
    image_retour=img.copy()
    (l, h) = taille(image)
    for y in range(h):
        for x in range(l):
            c = lire_pixel(image_retour,x,y)
            nouvelle_c=(c[0]+e,c[1]+e,c[2]+e)
            image_retour=changer_pixel(image_retour,x,y,nouvelle_c)
    afficher(image_retour)
    return image_retour

def canal_R(img):
    image_retour=img.copy()
    (l, h) = taille(image)
    for y in range(h):
        for x in range(l):
            c = lire_pixel(image_retour,x,y)
            nouvelle_c=(c[0],0,0)
            image_retour=changer_pixel(image_retour,x,y,nouvelle_c)
    afficher(image_retour)
    return image_retour

def canal_V(img):
    image_retour=img.copy()
    (l, h) = taille(image)
    for y in range(h):
        for x in range(l):
            c = lire_pixel(image_retour,x,y)
            nouvelle_c=(0,c[1],0)
            image_retour=changer_pixel(image_retour,x,y,nouvelle_c)
    afficher(image_retour)
    return image_retour

def canal_B(img):
    image_retour=img.copy()
    (l, h) = taille(image)
    for y in range(h):
        for x in range(l):
            c = lire_pixel(image_retour,x,y)
            nouvelle_c=(0,0,c[2])
            image_retour=changer_pixel(image_retour,x,y,nouvelle_c)
    afficher(image_retour)
    return image_retour

def convertir_noir_blanc(img):
    image_retour=img.copy()
    (l, h) = taille(image)
    for y in range(h):
        for x in range(l):
            c = lire_pixel(image_retour,x,y)
            moyenne=int((c[0]+c[1]+c[2])/3)
            nouvelle_c=( moyenne , moyenne , moyenne )
            image_retour=changer_pixel(image_retour,x,y,nouvelle_c)
    afficher(image_retour)
    return image_retour

def symetrie1(image):
    image_retour=image.copy()
    (l, h) = taille(image)
    for y in range(h):
        for x in range(l//2):
            c = lire_pixel(image_retour,x,y)
            image_retour=changer_pixel(image_retour,l-1-x,y,c)
    afficher(image_retour)
    return image_retour