Photoshop

TP Image

TP Image

Sommaire

Introduction

Dans ce TP nous aurons besoin de la bibliothèque Pillow.  C’est une bibliothèque permettant de travailler sur les images.

 Cette bibliothèque est déjà installée avec EduPython

Maintenant créez un dossier TP_image. Nous travaillerons dans ce dossier. Dans cette activité, nous allons travailler avec l’image ci-dessous « IMAGE.jpg ».

Télécharger cette image et la copier dans un répertoire « TP_image »

Pour en savoir plus sur l’origine de cette photo : https://fr.wikipedia.org/wiki/Lenna

Lenna

Votre dossier devrait ressembler à  ça :

Quelques rappels sur les images :

  • Une image est constituée de pixels (points), la définition d’une image L x H (par exemple 330 x 330 pour l’image considérée correspond au nombre de pixels de l’image (L : la largeur de l’image en pixel, H : la hauteur de l’image en pixel).
  • Chaque pixel est constitué de 3 éléments (chacun est appelé aussi canal) : un rouge, un vert et un bleu (RVB). C’est la somme de ces 3 couleurs qui permet d’obtenir un grand nombre de couleurs (synthèse additive).
  • Classiquement, à chaque canal, on associe un nombre binaire codé sur 8 bits (soit donc 24 bits par pixel).
  • Pour chaque pixel, on aura donc une valeur pour le rouge (comprise entre 0 et 255 puisque codé sur 8 bits), une valeur pour le vert (comprise entre 0 et 255) et une valeur pour le bleu (comprise entre 0 et 255).
    Quelques exemples : (0,0,0) => noir ; (255,0,0) => rouge ; (255,255,255) => blanc ; (0,255,0) => vert…

Remarque : Il peut exister un 4e canal en plus du canal rouge, canal vert et canal bleu, le canal « alpha » qui permet de gérer la transparence du pixel (par exemple, les images au format .png gèrent la transparence). Chaque pixel est donc codé sur 32 bits (4 x 8).

Partant du principe que l’image que vous avez copiée possède une définition de 508*512, que chaque pixel est constitué de 3 éléments (RVB) chacun codé sur 8 bits = 1 octet, calculez la taille (ou poids) de cette image en kilo octet (ko).
Rappel : 1 ko = 1024 octets ; 1 octet = 8 bits
Si vous regardez la taille réelle de l’image en ko, vous allez sans doute trouver une valeur inférieure à celle que vous venez de calculer. Ceci est tout à fait normal, car le .jpeg est un format compressé (le taux de compression est compris entre 10 : 1 et 25 : 1).
Vous pouvez convertir cette image en .PNG avec « paint » ou « photofiltre » et comparer sa nouvelle taille à la taille précédente.

Fonctions de base

1. Voici le code minimal vous permettant d’ouvrir une image et de l’afficher :

from PIL import Image

image =  Image.open("IMAGE.jpg")
image.show() 

Attention ! Pour que cela fonctionne votre fichier .py doit se trouver dans le même dossier que votre image !
La première ligne permet d’indiquer que nous utiliserons les outils de la bibliothèque Pillow.
La deuxième ligne permet d’ouvrir l’image et de l’enregistrer dans variable (pour simplifier) “image”
La troisième ligne permet d’afficher l’image à l’écran.

2. Plutôt que d’afficher l’image on peut plutôt en enregistrer une copie:

from PIL import Image

image = Image.open("IMAGE.jpg")
image.save("resultat.jpg", "JPEG") 

La ligne “image.save(“resultat.jpg”,”JPEG”)” permet de sauvegarder une image. L’image sera sauvegardée dans le dossier courant (le même dossier que “IMAGE.jpg”) et aura pour nom “resultat.jpg”.

3. La méthode getpixel((x,y)) renvoie un tuple (un tuple ressemble beaucoup à une liste, à l’exception près, qu’un tuple, une fois créé, n’est pas modifiable.) contenant les trois composantes : rouge, verte et bleue du pixel situé aux coordonnées x, y (sachant que le pixel de coordonnées 0, 0 se situe en haut à gauche de l’image).

Pixel de coordonnées (3; 1)

Saisissez, analysez et testez ce code :

from PIL import Image

image = Image.open("IMAGE.jpg")
(r, v, b) = image.getpixel((100, 100))
print(r, v, b) 

Si tout se passe correctement, vous devriez avoir à l’écran (dans la console) : (175, 68, 76). Nous pouvons donc affirmer que le pixel de l’image “IMAGE.jpg”, ayant pour coordonnées (100, 100), a pour composantes : Rouge=>175 ; Vert=>68 ; Bleu=>76. Encore une chose importante sur les tuples : si vous voulez récupérer une valeur du tuple, cela se passe exactement comme avec les listes. Si vous reprenez l’exemple ci-dessus, tu [0] est égal à 175 et tu [2] est égal à 68. Vous remarquerez que la méthode getpixel prend en paramètre un tuple : (100,100).

4. Autre fonction très utile : putpixel. Cette méthode permet de modifier les canaux Rouge, Vert et Bleu d’un pixel. La méthode putpixel prend deux paramètres (2 tuples) : le premier paramètre correspond aux coordonnées du pixel que nous voulons modifier (tuple avec 2 éléments : (x, y)). Le second paramètre correspond aux valeurs à attribuer aux canaux R, V, B (tuple avec 3 éléments : (255,255,255), ici un pixel blanc).Saisissez, analysez et testez ce code :

from PIL import Image

image = Image.open("IMAGE.jpg")
image.putpixel((312, 444), (0, 0, 255))
image.save("resultat.jpg", "JPEG") 

Cherchez maintenant le pixel bleu sur l’image. (vers l’épaule 🙂 )

5. Récupérer la définition d’une photo

(L, H) = image.size 

6. Redimensionner une photo

image = image.resize((L, H)) 

L et H étant les nouvelles dimensions de « image »

7. Visualiser une image

image.show() 

Pixel art

Nous allons construire un petit drapeau français sur 6 pixels :

Voici le programme en question :

from PIL import Image

image = Image.new('RGB', (3, 2))

image.putpixel((0, 0), (5, 20, 64))
image.putpixel((0, 1), (5, 20, 64))
image.putpixel((1, 0), (255, 255, 255))
image.putpixel((1, 1), (255, 255, 255))
image.putpixel((2, 0), (236, 25, 32))
image.putpixel((2, 1), (236, 25, 32))

image.save("image.png") 

Pensez à zoomer, le drapeau est tout petit 🙂

Si vous le souhaitez vous pouvez redimensionner l’image avec :

image = image.resize((300, 200)) 

Exercices

Exercice :

  • Modifiez le programme pour obtenir le drapeau allemand.

Exercice :

  • Une fois ce drapeau réalisé essayez de réaliser un dessin de votre choix. (une lettre, un smiley, etc )

Exercice supplémentaire (Exercice un peu difficile, vous pouvez le passer si vous êtes en seconde) :

  1. Ecrivez une procédure qui permet de colorier un rectangle d’une certaine longueur, d’une certaine largeur et d’une certaine couleur.
    Compléter :
from PIL import Image

def rectangle(origine, image, longueur, largeur, couleur):
    # A vous de complèter ici

# test de la procédure :
image = Image.new('RGB', (50, 50))
rectangle((2,2), image, 20, 30, (0, 0, 250)) 

Le programme précédent devrait dessiner un rectangle bleu de 20 pixels sur 30 pixels. Le coin en haut à gauche de ce rectangle se situe sur le pixel de coordonnées (2;2)

Utilisez la fonction précédente pour faire un drapeau français de 500 pixels de côté.

Modification d’une photo

Très souvent il est nécessaire de parcourir les pixels d’une image.  Voyons un exemple permettant de transformer tous les pixels en bleu :

from PIL import Image

image = Image.open("IMAGE.jpg")
(L, H)= image.size
# On parcours les lignes de pixels de l'image
for i in range(H): 
    # Pour chaque ligne on parcours les pixels de la ligne i
    for j in range(L):
        image.putpixel((j, i), (0, 0, 255))
image.save("resultat.jpg", "JPEG")
image.show() 

Le résultat n’est pas très intéressant… Avant d’aller plus loin assure toi d’avoir bien compris ce petit programme.

 

Regardons des manipulations plus intéressantes :

Les corrigés sont disponibles pour les étudiants connectés seulement.

(Avant de consulter les corrigés tu peux essayer un peu quand même… Et si tu es amené à consulter le corriger assure toi de bien le comprendre)

Assombrir une image

Écrire et commenter le programme permettant de d’assombrir l’image. (soustraire 50 à chaque canal, par exemple)
Indication : Il faut penser à utilise get.pixel pour récupérer les couleurs de ce pixel.

Corrigé (visible si connecté)

Négatif d'une image

Écrire et commenter un programme en Python qui permettra de transformer une image couleur en son négatif.

Corrigé

from PIL import Image

image = Image.open("IMAGE.jpg")
(L, H) = image.size
for i in range(H):
    for j in range(L):
        (r, v, b) = image.getpixel((j, i))
        image.putpixel((j, i), (255 - r, 255 - v, 255 - b))      
image.save("resultat.jpg", "JPEG") 

Image en niveau de gris

Écrire et commenter un programme en Python qui permettra de transformer une image couleur en une image en niveau de gris (souvent improprement appelée “noir et blanc”, car une image “noir et blanc” est uniquement composée de pixel noir et de pixel blanc).
Une des façons d’obtenir du gris est de prendre les fractions suivantes pour les composantes RVB : (rouge=0.299 ;
verte=0.587 ; bleue=0.144), la somme faisant 1.

Remarque : en Python, int(x) permet de prendre la valeur entière de x.

Corrigé

from PIL import Image

image = Image.open("IMAGE.jpg")
(L, H) = image.size
for i in range(H):
    for j in range(L):
        (r, v, b) = image.getpixel((j, i))
        image.putpixel((j, i), (int(0.299 * r), int(0.587 * v), int(0.144 * b)))      
image.save("resultat.jpg", "JPEG") 

Symétrique d'une image

Transformer une image en sa symétrique par rapport à l’axe de symétrie « vertical » (principal) de la fenêtre graphique.

Corrigé

from PIL import Image

image = Image.open("IMAGE.jpg")
(L, H) = image.size

# On utilise une nouvelle image
nouvelle_image = Image.new("RGB", (L, H))
                        
for i in range(H):
    for j in range(L):
        (r, v, b) = image.getpixel((j, i))
        nouvelle_image.putpixel((j, -i+H-1), (r, v, b))     
nouvelle_image.save("resultat.jpg", "JPEG") 

Rotation d'une image

(Attention, cette question est optionnelle en seconde) Faite tourner l’image d’un quart de tour dans le sens des aiguilles d’une montre. (Et sans dupliquer l’image si vous souhaitez faire la question en mode Iron Man)

Exercices

Exercice :

Pour la future application FaceSturm, pourriez vous écrire un programme qui change la couleur du rouge à lèvre de cette dame.

Faite la même chose pour la deuxième photo mais en faisant attention de ne pas modifier la couleur du fond !

Variation autour d'une pomme

Pour commencer, télécharger cette image de pomme :

 

Maintenant testez le code qui permet de coller l’image de pomme dans une image de fond :

from PIL import Image

# On ouvre l'image de pomme
image = Image.open("pomme.jpg")
# On réccupère la définition de l'image de pomme
(L, H) = image.size
# Je crée une nouvelle image pouvant contenir 4 fois l'image de pomme
fond = Image.new("RGB", (L * 2, H * 2))
# Je colle l'image en (0, 0) (coin en haut à gauche
fond.paste(image, (0, 0))
fond.save("resultatf.jpg", "JPEG")
fond.show()  

Maintenant modifiez ce code pour obtenir l’image suivante :

from PIL import Image

# On ouvre l'image de pomme
image = Image.open("pomme.jpg")
# On réccupère la définition de l'image de pomme
(L, H) = image.size
# Je crée une nouvelle image pouvant contenir 4 fois l'image de pomme
fond = Image.new("RGB", (L * 2, H * 2))
# Je colle l'image en (0, 0) (coin en haut à gauche
fond.paste(image, (0, 0))
fond.paste(image, (L, 0))
fond.paste(image, (0, H))
fond.paste(image, (L, H))
fond.save("resultatf.jpg", "JPEG")
fond.show()  

En vous inspirant de ce code :

[pastacode lang=”python” manual=”from%20PIL%20import%20Image%0A%0A%23%20On%20ouvre%20l’image%20de%20pomme%0Apomme1%20%3D%20Image.open(%22pomme.jpg%22)%0A%23On%20cr%C3%A9e%20une%20copie%20de%20la%20pomme%0Apomme2%20%3D%20pomme1.copy()%0A%23%20On%20r%C3%A9ccup%C3%A8re%20la%20d%C3%A9finition%20de%20l’image%20de%20pomme%0A(L%2C%20H)%20%3D%20pomme1.size%0A%23%20Je%20cr%C3%A9e%20une%20nouvelle%20image%20pouvant%20contenir%204%20fois%20l’image%20de%20pomme%0Afond%20%3D%20Image.new(%22RGB%22%2C%20(L%20*%202%2C%20H%20*%202))%0A%0A%23%20Je%20modifie%20ma%20copie%20de%20pomme%0Afor%20i%20in%20range(H)%3A%20%23%20On%20parcours%20les%20lignes%20de%20pixels%20de%20l’image%0A%20%20%20%20for%20j%20in%20range(L)%3A%20%23%20On%20parcours%20les%20pixels%20de%20la%20ligne%20i%0A%20%20%20%20%20%20%20%20(r%2C%20v%2C%20b)%3Dpomme1.getpixel((j%2C%20i))%0A%20%20%20%20%20%20%20%20pomme2.putpixel((j%2C%20i)%2C%20(255%20-%20r%2C%20255%20-%20v%2C%20255%20-%20b))%0A%0A%0Afond.paste(pomme1%2C%20(0%2C%200))%0Afond.paste(pomme2%2C%20(L%2C%20H))%0Afond.save(%22resultatf.jpg%22%2C%20%22JPEG%22)%0Afond.show()%20%0A” message=”” highlight=”” provider=”manual”/]

et en réutilisant tout ce que vous avez vu dans ce TP, écrivez un programme permettant d’obtenir l’image suivante :

(Pour chaque image une couleur a été supprimée)

Et maintenant, laissez libre cours à votre imagination ! Réalisez votre œuvre d’art.

Retour en haut
Retour haut de page