Séance Python 7 : traitement d`images 1

PC
2014/2015
Séance Python 7 : traitement d’images
1
1.1
Représentation d’une image
Codage de l’image
Une image informatique est la donnée d’un tableau de pixels (points) de couleur. Cette couleur peut être
– un entier égal à 0 (noir) ou 1 (blanc) pour une image en noir et blanc ;
– un entier compris entre 0 (noir) et 255 (blanc) pour une image en niveaux de gris ;
– la donnée de trois entiers, chacun compris entre 0 et 255 pour une image en couleurs dans le codage
RGB : l’image est en fait la superposition de trois images, une rouge (R), une verte (G) et une bleue (B).
Avoir accès à ces pixels permet de modifier une image.
1.2
Accès aux pixels de l’image en python
On utilisera le module PIL (Python Image Library) de traitement d’images :
1
import PIL . Image as img
Je suppose que le script que vous exécutez est enregistré dans le répertoire TP7 de votre espace personnel
Travail. Après avoir récupéré l’image lena.tiff et l’avoir placée dans ce répertoire, on l’ouvre avec la
syntaxe
1
lena = img . open ( ’ // SERVEUR01 / UTILISATEUR / Travail / TP7 / lena . tiff ’)
(où UTILISATEUR est bien sûr à remplacer par votre nom d’utilisateur). La variable lena contient alors
l’image (sous une forme non directement accessible). On obtient ses dimensions (nombre de pixels :
largeur, hauteur) par
1
>>> lena . size
(512 , 512)
Son «mode» :
1
>>> lena . mode
’ RGB ’
L’image est en mode RGB. L’autre mode qui nous intéressera dans ce TD est ’L’ (pour luminance :
niveaux de gris).
L’accès à chaque pixel se fait via ses coordonnées : l’origine est le coin supérieur gauche de l’image ; l’axe
des abscisses est orienté vers la droite, celui des ordonnées vers le bas.
On récupère la couleur du pixel de coordonnées (i, j) comme suit :
1
>>> lena . getpixel ((10 ,15))
(226 , 133 , 96)
On modifie un pixel comme suit :
1
>>> lena . putpixel ((10 ,15) ,(0 ,0 ,0))
(le pixel a été colorié en noir : valeur nulle sur chacune des composantes R,G,B).
Enfin, on demande l’affichage de l’image lena par
1
>>> lena . show ()
2
2.1
Transformation d’images
Image en noir et blanc (niveaux de gris)
1. Écrire une fonction black_and_wite(image) qui prend en argument une image image (ouverte par la
syntaxe décrite ci-dessus) et renvoie l’image correspondante en niveau de gris. Pour cela, on créera une
nouvelle image de mêmes dimensions que l’image image, en mode ’L’, grâce à img.new, qui prend deux
1
arguments : le mode et la taille. On remplira ensuite cette image en choisissant pour luminance du pixel
(i, j) la moyenne des trois luminances dans les composantes R,G,B de l’image initiale. Ne pas oublier que
cette couleur doit être un entier.
On devra par exemple pouvoir lancer les commandes
1
2
1
>>> lenaGris = black_and_white ( lena )
>>> lenaGris . show ()
(création d’une image nommée lenaGris, version «niveaux de gris» de l’image lena, puis affichage
d’icelle).
Remarque : python possède des méthodes beaucoup plus performantes que ce traitement pixel par pixel.
Comparer avec le temps d’exécution de
>>> lenaGris = lena . convert ( ’L ’)
Nous travaillerons par la suite sur ce fichier plutôt que sur l’image couleur (pour la simplicité : un seul
canal de couleur à modifier au lieu des trois canaux).
2.2
Symétries
2. Écrire une fonction miroir(image) qui renvoie l’image miroir (le haut reste en haut ; la droite et la
gauche sont permutées) de l’image image.
3. Écrire une fonction rotation(image) qui renvoie une version de l’image obtenue par rotation d’angle
Quelles formules faudrait-il utiliser pour une rotation d’angle π ?
2.3
π
2.
Négatif
4. Écrire une fonction negatif(image) renvoyant le négatif de l’image (en niveaux de gris) et l’afficher. On
commencera par définir une fonction s qui réalise la transformation d’une couleur en une autre pour le
passage au négatif. Comparer (en temps d’exécution) à
1
>>> lenaNegatif = lenaGris . point ( s )
2.4
Augmentation du contraste
Pour augmenter le contraste d’une image, on applique une fonction croissante f : [[0, 255]] −→ [[0, 255]]
à chacun des pixels ; cette fonction doit laisser peu de pixels dans la zone médiane (autour de 128) : les
pixels de valeur supérieure à 128 doivent être sensiblement augmentés ; ceux de valeur inférieure à 128
sensiblement diminués.
5. La fonction f suivante est construite à partir d’une transformation simple effectuée sur la fonction cosinus.
Quelle est la formule pour f (x) ?
f (x)
1
g(x)
1
h(x)
255
1
1
255
6. Quelle est la formule pour la fonction g dessinée à côté de la fonction f ? g(x) = f (x)3 ou g(x) = f 3 (x)
(composée) ? Et pour la fonction h ?
7. Écrire une fonction augmente_contraste(image). On utilisera point.
2.5
Convolution
8. Pour flouter une image, on remplace chaque pixel par la moyenne des 9 pixels qui forment le carré dont il
est le centre (on ne traite que les pixels qui ne sont pas sur le bord). Écrire une fonction floutage(image).
9. Pour détecter les contours d’une image, on s’intéresse aux variations brusques de luminosité. Pour cela,
on calcule la quantité
p = 255 − (pi−1,j + pi+1,j + pi,j−1 + pi,j+1 − 4pi,j ),
c’est cette valeur p que l’on place dans le pixel (i, j) de l’image créée.
Écrire une fonction contour(image). On commencera par écrire une fonction renormalise(x) qui renvoie
x si x ∈ [[0, 255]], 0 si x < 0 et 255 si x > 255.
2
3
3.1
Stéganographie
Le principe
La stéganographie consiste en la dissimulation d’un message dans un autre (dans notre cas, une image dans
une autre). On dispose d’une image masque et d’une image secret, de mêmes dimensions. Chaque pixel de
l’image a une couleur c ∈ [[0, 255]]. Sa représentation binaire comporte donc 8 chiffres. Le principe consiste
à modifier (peu) la couleur de chaque pixel de l’image masque en ne modifiant que les trois derniers bits
de sa représentation binaire (au pire, la variation de couleur sera de 7, sur une échelle de 256 couleurs).
Dans ces trois derniers bits, on code la couleur du pixel correspondant de l’image secret. De cette couleur,
on ne retient qu’une information qui occupe trois bit, mais les trois bits de poids fort cette fois-ci.
Par exemple, si pour un pixel donné, la couleur de l’image masque est 152 et celle ce l’image secret est 47.
Les écritures binaires (sur 8 bits) de ces nombres sont respectivement b1 = 10011000 et b2 = 00101111.
On ne garde que les trois premiers bits 001 de b2 , que l’on place en remplacement des trois derniers
bits de b1 . On obtient b01 = 10011001 (qui représente l’entier 153). Lors du décodage, la couleur lue sera
b02 = 00100000 (i.e. 32) au lieu de b2 .
3.2
Manipulation des entiers bit à bit
Les entiers étant codés (en machine) en binaire, les opérations sur les bits sont implémentées efficacement.
On dispose en particulier des opérateurs & et | dont le fonctionnement est le suivant :
– si b1 et b2 sont deux bits, b1 &b2 désigne le bit qui vaut 1 si b1 et b2 sont égaux à 1, 0 dans tous les
autres cas ;
– si b1 et b2 sont deux bits, b1 |b2 désigne le bit qui vaut 0 si b1 et b2 sont égaux à 0, 1 dans tous les autres
cas.
Ces opérations sur les bits sont étendues aux opérations sur les entiers en travaillant bit par bit. Par
exemple, pour n1 = 23 et n2 = 120, de représentations binaires respectives b1 = 10111 et b2 = 1111000,
on commence par écrire b1 = 0010111 (pour avoir autant de bits dans chacune des écriture) puis on
applique l’opérateur & (ou |) bit à bit. On obtient
b1 &b2 = 0010000,
représentation binaire de l’entier r1 = 16 (donc on a 23&120 = 16), et
b1 |b2 = 1111111,
représentation de l’entier 127 (donc 23|120 = 127).
On dispose aussi des opérateurs de décalage >> : l’entier n >> i est obtenu en
– écrivant l’entier n en binaire ;
– supprimant les i chiffres de poids faible (les autres chiffres sont donc décalés de i rangs vers la droite).
Par exemple, pour obtenir l’entier 120 >> 3, on
– écrit 120 en base 2 : b2 = 1111000 ;
– supprime les trois chiffres de droite : on obtient 1111, représentation binaire de l’entier 15.
Ainsi, on a 120 >> 3 = 15.
Application : si c1 et c2 sont des entiers codés sur 8 bits (appartenant à l’intervalle [[0, 255]]), comment
– récupérer les trois bits de poids fort de c1 ? (on notera r1 le résultat)
– remplacer les trois bits de poids faible de c2 par des 0 ? (on notera r2 le résultat)
– remplacer les trois bits de poids faible de c2 par les trois bits de poids fort de c1 ? (on pourra utiliser
r1 et r2 ).
3.3
Mise en œuvre
Écrire une fonction cache(masque, secret) qui, à partir de deux images masque et cache (déjà ouvertes,
toutes deux en mode RGB, de mêmes dimensions), crée une image resultat sur le principe exposé cidessus et l’affiche. Écrire aussi une fonction revele qui, à partir d’une image resultat, retrouve l’image
cachée par le procédé précédent (évidemment, cette image a été un peu altérée par rapport à l’original).
On pourra pour cela utiliser l’opérateur de décalage à gauche << : n << i renvoie le nombre obtenu en
supprimant les i bits de poids fort de n, en décalant les bits restant de i rangs vers la droite, et en
rajoutant i bits nuls à droite.
3