Traitement d’images
informatique, 11/2017
1 — Format numérique d’image
Une image peut être numérisée sous forme d’image matricielle (en anglais « bitmap ») par
une matrice de points colorés.
Cette matrice a n lignes (la hauteur de l’image) et p colonnes (la largeur). L’élément (i, j)
[1,0,0]
représente un pixel, c’est-à-dire une portion d’image considérée de couleur constante.
Il existe plusieurs manières de coder la couleur. La méthode accessible avec la
bibliothèque [Link] est la méthode RGB 1 . Chaque couleur est
représentée par une liste à trois entrées [r,g,b] où r , g et b sont trois réels
représentant respectivement la quantité de rouge, de vert et de bleu que contient la
[0,0,1]
couleur. La méthode de mélange des couleurs est la synthèse additive : on peut penser à
trois spots de couleurs qui éclairent un fond noir. Le mélange des trois lumières colorées [1,1,0]
crée la couleur désirée.
Si r = g = b = 0, le pixel est noir. Si r , g et b ont leur valeur maximale, le pixel est blanc.
Cette valeur maximale dépend de l’image et du format d’image : il peut être de 1 ou de
255. Créons maintenant une image très simple.
Supposons que la valeur maximale soit à 1 : [1,0,0] est du rouge pur, [0,1,1] est le 1 import numpy as np
cyan (complémentaire du rouge), etc. Les couleurs ayant des proportions identiques de 2 import [Link] as mpimg
rouge, vert et bleu [x,x,x] sont des gris de plus en plus clair lorsque x augmente. 3 import [Link] as plt
4 #import pylab
2 — Création d’une image
5
Avec numpy une image est donc codée avec une matrice A de dimension 3. La première
6 # codage des couleurs pour plus de facilité
dimension représente le numéro de la ligne, la seconde le numéro de la colonne et la
7 rouge = [0.807, 0.066, 0.149]
dernière le numéro de la couleur.
8 blanc = [1, 1, 1]
Par exemple, si A code l’image ci-dessous, on aura A[0,0] qui vaut [1,1,1],
9 bleu = [0, 0.129, 0.278]
A[0,6,0] qui vaut 1 et A[0,6,1] et A[0,6,2]qui valent 0, etc.
10
1. pour « Red-Green-Blue », on dirait RVB en bon français. 11 hauteur = 210
12 largeur = 2*hauteur
13
14 # Image de départ, entièrement noire
15 image = [Link]((hauteur, largeur, 3))
16
17 # Remplissage ...,
18 image[:, 0:largeur//3 ] = bleu [ 0.45882353, 0.57647061, 0.32549021],
19 image[:, largeur//3:2*largeur//3 ] = blanc [ 0.43921569, 0.55686277, 0.30588236],
20 image[:, 2*largeur//3:largeur ] = rouge [ 0.43529412, 0.5529412 , 0.3019608 ]]], dtype=float32)
21
Les couleurs sont codées par 3 flottants entre 0 et 1 (cette information est importante à
22
retenir, car ce n’est pas toujours le cas). La librairie [Link] a décodé le
23 [Link]("[Link]", image)
fichier et chargé l’image sous forme d’un tableau numpy.
Comme d’habitude on commence par inclure les libraires. Ensuite l’image est gérée Comme img est un tableau, il est facile de le manipuler avec les méthodes de numpy ou
comme une array de numpy. Chaque pixel reçoit comme valeur une liste [r, g, b] avec des boucles. Pour cela on a besoin d’en connaître les dimensions à l’aide de l’attribut
de trois réels pour coder la couleur. On utilise la puissance de numpy pour remplir shape (sans parenthèses !). Par exemple, modifions l’image ci-dessus pour en saturer la
rapidement l’image. couleur bleue.
À la fin du script, l’instruction [Link]() demande à matplotlib d’interpréter
img[:,:,2] = 1
cet array en tant qu’image bitmap. La commande [Link]() permet l’affichage et
[Link]() la sauvegarde sur disque. La librairie [Link] ne connait On obtient l’image suivante :
2
que le format d’image PNG : on sauvegarde donc avec l’extension png.
3 — Ouverture et manipulation d’une image existante
Voyons un exemple
import [Link] as mpimg
img = [Link](’[Link]’)
L’image [Link] est stocké dans le tableau numpy nommé img (la librairie matplotlib
a chargé numpy pour nous). Voyons d’un peu plus près l’objet img
img
array([[[ 0.90588236, 0.91764706, 0.93725491],
[ 0.90588236, 0.91764706, 0.93725491],
[ 0.90588236, 0.91764706, 0.93725491], Exercice 1
..., Écrire différentes fonctions qui reçoivent par paramètre le nom d’un fichier image,
[ 0.92156863, 0.93333334, 0.95294118], transforment cette image, et sauvegardent le résultat dans un fichier. On les testera avec
[ 0.92156863, 0.93333334, 0.95294118], l’image [Link].
[ 0.92156863, 0.93333334, 0.95294118]], 1. Inversion de couleurs : la valeur x de chaque couleur est remplacé par 1 − x .
2. Séparation en trois images : l’une avec la composante rouge, une deuxième avec la
2. Portable Network Graphics (PNG) est un format ouvert d’images non destructeur, c’est-à-dire qu’il compresse composante verte et la troisième avec la composante bleue.
l’information sans la simplifier (au contraire de JPEG par exemple). 3. Transformation en niveau de gris. On a plusieurs moyen de le faire :
2
a) Dans la couleur grise, les trois niveaux de couleur sont égaux. On remplace donc 4 — Convolution
rouge, vert et bleu par la moyenne des trois couleurs. La convolution 2D est un traitement d’image où la valeur de chaque pixel est recalculé en
b) Mais on peut aussi remplacer chaque niveau par la moyenne pondérée fonction des valeurs des pixels voisins.
0, 21 × R + 0, 71 × V + 0, 07 × B (la « luminosité » du pixel). Cherchons par exemple à « flouter » une image. La valeur du pixel [i,j] est remplacé
c) Enfin on peut prendre la moyenne entre le minimum et le maximum des trois par la moyenne pondérée des valeurs des pixels voisins.
composantes.
1 1
4. Proposer et implémenter une méthode pour transformer l’image en noir et blanc. pixel[x, y] = pixel[x − 1, y − 1] + pixel[x − 1, y]+
Exercice 2 — Amélioration du contraste 8 8
1 1
Pour améliorer le contraste, on transforme le niveau de gris d’entrée en un nouveau pixel[x − 1, y + 1] + · · · + pixel[x + 1, y + 1]
8 8
niveau de gris dans le but d’exagérer les différences entre les niveaux. Pour cela on
Évidemment, cette formule n’est pas valable pour les pixels du bord de l’image, une autre
applique une fonction « bien choisie ».
formule doit être appliquée. On ne va pas se soucier dans ce TD : l’image de sortie sera
1. Améliorer le contraste en utilisant une fonction racine carrée : on remplace chaque
p donc un peu plus petite que l’image d’entrée.
niveau d’entrée x par x .
Mais on va faire plus fort : on va généraliser cette formule avec des coefficients différents.
2. Comparer avec l’usage d’un courbe « en S » (un morceau de sin convenablement
transformé).
1 1 1
f (x) = + × sin π (x − )
valeur de sortie 2 2 2
p
x a b c
e
d f
(x, y)
g h i
O valeur d’entrée
3. Expliquer en quoi la transformation précédente améliore le contraste de l’image.
4. Quel type de fonction est susceptible d’être utile ?
pixel[x, y] = a × pixel[x − 1, y − 1] + b × pixel[x − 1, y]+
c × pixel[x − 1, y + 1] + · · · + i × pixel[x + 1, y + 1]
Exercice 3 — Convolution – Floutage
3
1. Écrire une fonction convolution2D( image, matrice ) qui prend en
paramètre une image et une matrice 3 × 3 de la forme
a b c
M = d e f
g h i
et qui effectue l’opération de convolution décrite précédemment.
2. Flouter l’image hibiscus en lui appliquant une convolution convenable.
Exercice 4 — Détection des bords – Méthode de la convolution
Dans une image, les bords des objets correspondent à des zones où les valeurs des pixels
changent rapidement. C’est le cas par exemple lorsque l’on passe d’un objet clair (avec des
valeurs grandes) à un arrière plan sombre (avec des valeurs petites).
Considérons une image à laquelle on applique une convolution avec la matrice
1 1 1
M = 1 −8 1
1 1 1
1. Que se passe-t-il pour les pixels dans des zones uniformes ? Et pour des pixels dans des
zones à fort contraste.
2. Appliquez cette convolution à l’image [Link]. Commentez.
3. Dans certaines images, comme [Link] on s’intéresse à une détection de bord
dans une certaine direction (ici horizontale). Proposez une convolution pour se faire.