Cours d'introduction au langage de programmation Python

N.B. Niveau : Terminale S, enseignement de spécialité ISN (Informatique et Sciences du Numérique)
Ce cours a été testé sous Windows et GNU/Linux avec Python version 2.7

Chapitre 10 - Traitement des images

Compression

On peut compresser les images pour gagner de l'espace dur le disque dur ou pour envoyer une ou plusieurs images par Internet. On distingue la compression avec perte de qualité et la compression sans perte.
Grace au logiciel réseau photofiltre, crée une nouvelle image d'une taille de 16 pixels de large et 12 pixels de haut. Tracer 3 lignes horizontales d'épaisseur 2 de longueur 16 ayant les couleurs Rouge : 255-10-20, vert 10-255-20, et bleu : 10-20-255
rvb
Enregistrer votre fichier au format BMP
Editer ce fichier en utilisant le logiciel réseau Hex-ed
Le fichier est constitué d'une entête de 54 bits, puis chaque pixel est stocké par son code couleur RVB en partant de la ligne du bas. La taille de l'image est proportionnelle à la taille du fichier = résolution_x * résolution_y *3 + 56. Vérifier la taille de votre fichier et du calcul.
Ouvrir l'image portrait.bmp stockée sur le lecteur réseau de la classe de ISN. Enregistrer cette image au format PNG, puis JPEG avec une compression à 100%, ensuite en JPEG avec une compression à 50%. Comparez les tailles et les qualité, on peut distinguer les compression avec perte de données et celles sans perte de données. Tester le format GIF.

Les images au format PGM

Le format PGM (portable graymap file format) est utilisé pour des images en niveau de gris.
C'est un format d'image matricielle, sans compression, assez peu utilisé mais qui présente l'intérêt d'être facilement manipulé.

Commencez par copier sur votre Bureau une image en couleur de format quelconque (JPEG, PNG, BMP, GIF, PPM...).

image JPEG

Avec le logiciel de traitement d'images GIMP, nous allons convertir cette image dans le format PGM :
Ouvrir le fichier avec GIMP
Fichier → Enregistrer sous
Sélectionner le type de fichier (selon l'extension) → Image PGM
Exporter
Formatage des données → Brut
Enregistrer

Renommez ce fichier : image.pgm

Télécharger le fichier image.pgm

Un exemple de traitement : l'inversion de couleurs

Le script inversion_image_pgm.py permet d'inverser les couleurs d'une image.
On obtient ainsi le "négatif" :

# script inversion_image_pgm.py
import imghdr

print 'Inversion d\'une image PGM en mode binaire à 256 niveaux de gris\n' NomFichierSource = 'image.pgm' NomFichierDestination = 'imageInverse.pgm' print 'Fichier source :',NomFichierSource
print 'Fichier destination :',NomFichierDestination

def Inversion(octet):
# cette fonction fait une inversion du niveau de gris
# 0 (noir) -> 255 (blanc)
# 255 (blanc) -> 0 (noir)
return 255-octet

if imghdr.what(NomFichierSource)=='pgm': # test du format de l'image FichierSource = open(NomFichierSource,'rb')
TailleFichier = len(FichierSource.read())
print '\nTaille du fichier (en octets) :',TailleFichier

Largeur = int(raw_input('Largeur de l\'image (en pixels) ? '))
Hauteur = int(raw_input('Hauteur de l\'image (en pixels) ? '))
NbPixel = Largeur*Hauteur

TailleEntete = TailleFichier - Largeur*Hauteur

FichierSource.seek(0)

# extraction de l'en-tête
# la variable Entete est une chaîne de caractères
Entete = FichierSource.read(TailleEntete) # extraction des données
# Data est une liste de nombre entiers
# la fonction ord() retourne le contenu d'un octet sous forme d'un entier
# ord('\xf3') -> 243
Data = [ord(i) for i in FichierSource.read()]

FichierSource.close()

if NbPixel == len(Data):
print 'Nombre de pixels :',Largeur*Hauteur
print 'Nombre d\'octets de données :',len(Data)
print 'Taille de l\'en-tête :',TailleEntete

FichierDestination = open(NomFichierDestination,'wb')
# écriture de l'en-tête du fichier destination FichierDestination.write(Entete) # écriture des données du fichier destination for i in Data:
# la fonction chr() fait le contraire de la fonction ord()
# chr(243) -> '\xf3'
FichierDestination.write(chr(Inversion(i)))

FichierDestination.close()
print 'Travail terminé !' else:
print 'Erreur dans la saisie des données !' else:
print 'Ce n\'est pas une image PGM !'
>>>
Inversion d'une image PGM en mode binaire à 256 niveaux de gris

Fichier source : image.pgm
Fichier destination : imageInverse.pgm

Taille du fichier (en octets) : 153654
Largeur de l'image (en pixels) ?
480
Hauteur de l'image (en pixels) ? 320
Nombre de pixels : 153600
Nombre d'octets de données : 153600
Taille de l'en-tête : 54
Travail terminé !

Le script crée le fichier imageInverse.pgm dans le répertoire courant.

Affichons l'en-tête des fichiers image PGM :

>>> print Entete.encode('hex')	# contenu de l'en-tête en hexadécimal
50350a232043524541544f523a2047494d5020504e4d2046696c74
65722056657273696f6e20312e310a343830203332300a3235350a
>>> print Entete # contenu de l'en-tête en chaîne de caractères P5
# CREATOR: GIMP PNM Filter Version 1.1
480 320
255
>>>

L'en-tête contient en particulier la largeur et la hauteur de l'image (480 pixels x 320 pixels) et le nombre 255 (soit 256 niveaux de gris).

La couleur d'un pixel est codée sur un octet.
On va du noir (0x00) au blanc (0xff) en passant par tous les niveaux de gris.

>>> print Data[0],hex(Data[0])	# premier octet : pixel en haut à gauche de l'image
153 0x99
>>> print Data[1],hex(Data[1])	# deuxième octet : pixel à droite du précédent
142 0x8e
>>> print hex(Data[479])	# 480ème octet : pixel en haut à droite
0xbf
>>> print hex(Data[480])	# 481ème octet : pixel de la deuxième ligne à gauche
0x92
>>> print hex(Data[153599]) 	# dernier octet : pixel en bas à droite de l'image (320ème ligne)
0x25

Avec un éditeur hexadécimal, observons le contenu du fichier image.pgm :

GHex

et comparons avec le contenu du fichier imageInverse.pgm :

GHex

Inversion de couleurs avec le logiciel GIMP

Il suffit de faire :
Couleurs → Inverser

La librairie PIL (Python Imaging Library)

Cette librairie spécialisée de Python fournit des outils de traitement d'images.

Installation

PIL n'est pas présente par défaut.
Il faut donc la télécharger et l'installer.

Télécharger la librairie PIL

Traitement d'images avec la librairie PIL

Le script suivant permet de convertir une photo en couleur au format JPEG en une image en niveau de gris au format PGM, puis de la transposer (retournement, miroir).
Les résultats sont affichés dans des fenêtres graphiques indépendantes et enregistrés dans des fichiers images :

# importation du module Image de la librairie PIL
from PIL import Image

# ouverture de l'image img = Image.open('photo.jpg')
# affichage de l'image img.show() # affichage de la taille de l'image (en pixels) print img.size
# conversion au format PPM (en couleur) et enregistrement de l'image img.save('photo.ppm','PPM')
img.show()
# conversion en niveau de gris (pour obtenir le format PGM) img0 = img.convert('L')
# enregistrement dans le fichier image.pgm img0.save('image.pgm')
img0.show()

# retournement de l'image img1 = img0.rotate(180) # affichage et enregistrement de l'image retournée img1.show() img1.save('image_retourne.pgm')

# miroir horizontal img2 = img0.transpose(Image.FLIP_LEFT_RIGHT) img2.show() img2.save('image_miroir_horizontal.pgm')

# miroir vertical img3 = img0.transpose(Image.FLIP_TOP_BOTTOM) img3.show() img3.save('image_miroir_vertical.pgm')
>>>
(480, 320)

Dessiner avec la librairie PIL

Le module ImageDraw de la librairie PIL permet de créer des formes géométriques simples dans une image : ligne, cercle, rectangle, texte...

Voici un script qui fabrique l'image d'un camenbert 2D (au format PNG) :

# script camenbert.py

from PIL import Image,ImageDraw

# création d'une image 400x400 (fond blanc)
img Image.new("RGB",(400,400),"#FFFFFF")

# création d'un objet Draw
dessin ImageDraw.Draw(img)

# dessine un arc partiel et le remplit
dessin.pieslice((50,50,350,350),0,60,fill="blue")
dessin.pieslice((50,50,350,350),60,150,fill="gray")
dessin.pieslice((50,50,350,350),150,360,fill="red")

# dessine du texte
dessin.text((50,20),"Camenbert 2D",fill="red")

img.save("camenbert.png","PNG")
img.show()

Exercices

Exercice 10.1 ★

1) Reprendre le script inversion_image_pgm.py de manière à réduire l'image initiale à deux couleurs (noir et blanc) en utilisant un seuil :

2) Faire la même chose avec le logiciel GIMP.

Exercice 10.2 ★★

1) Reprendre le script inversion_image_pgm.py de façon à retourner l'image (rotation à 180 degrés) :

2) Faire la même chose avec le logiciel GIMP.

Exercice 10.3 ★★

1) Reprendre le script inversion_image_pgm.py afin de faire une transformation miroir horizontal :

2) Faire la même chose avec le logiciel GIMP.

Exercice 10.4 ★★

1) Reprendre le script inversion_image_pgm.py afin de faire une transformation miroir vertical :

2) Faire la même chose avec le logiciel GIMP.

Exercice 10.5 ★ Redimensionnement d'une image JPEG

A l'aide de la méthode resize() du module Image de la librairie PIL, redimensionner une image JPEG.

Par exemple :

>>>
Redimensionnement d'une image JPEG

Nom de l'image originale ?
photo.jpg
Taille de l'image originale : (largeur, hauteur) = (1944, 2592)

Nouvelle taille :
Hauteur en pixels ?
800
Largeur en pixels : 600

Enregistrement de l'image redimensionnée
Nom de l'image redimensionnée ?
photo_1.jpg
>>>

Exercice 10.6 ★★ Calcul du diamètre d'un disque

1) A l'aide de la méthode getpixel() du module Image de la librairie PIL, estimer le diamètre d'un disque blanc d'une image à fond noir.

getpixel((x,y)) retourne la couleur du pixel de coordonnées (x,y).

Par exemple :

>>>
Nom du fichier ? disque.png

Largeur en pixels : 380
Hauteur en pixels : 250

Nombre de pixels (blanc) : 8820
Position du centre : x = 129.0 y = 100.0
Diamètre en pixels : 105.971565925
>>>

2) Application en astronomie

Estimer les dimensions de cette étoile rouge géante (image au format JPEG) :

Exercice 10.7 ★★ Captcha

Avec le module ImageDraw de la librairie PIL et en s'inspirant du script camenbert.py, créer un générateur de captcha :

Exercice 10.8 ★★

Ecrire un script qui permet d'extraire de l'en-tête d'un fichier PGM :

Exercice 10.9 ★★★

L'image suivante contient un code secret. Saurez-vous le décrypter ?

Indice n°1 : Python n'est pas nécessaire.

Indice n°2 :


Télécharger le fichier enigmaCodeSecret.pgm

Remarque : Au jour d'aujourd'hui (25/10/2013), personne n'a trouvé.

Webographie