Vous êtes sur la page 1sur 4

MPSI-PCSI TP informatique 12

Matrices et traitement d'images

Exercice 1 : Introduction aux tableaux numpy

Ce sujet manipule des matrices, sous forme de tableaux de la bibliothèque numpy. On


importe cette bibliothèque à l'aide de la commande :
import numpy as np
Toutes les fonctions issues de cette bibliothèque seront précédées du préxe np. pour
signier d'où elles proviennent.
On utilise généralement le terme "vecteur" pour désigner des tableaux numpy de di-
mension 1, et le terme "matrice" pour ceux de dimension 2. Les commandes usuelles sur
ces objets sont :
1. np.zeros(n) : crée un vecteur nul de taille n (unidimensionnel), par défaut c'est
un vecteur de ottants mais on peut changer le type en ajoutant dtype = ....
De même pour créer une matrice de zéros : np.zeros((n,m), dtype = ...) (at-
tention, ne pas oublier les parenthèses) où n, m sont respectivement le nombre de
lignes et de colonnes.
2. np.array(L) : crée un vecteur à partir d'une liste. Si c'est une liste de listes, cela
créera une matrice.
3. Si v est un vecteur, v[i] nous donne l'élément d'indice i (entre 0 et len(v)-1).
4. Si M est une matrice, M[i,j] ou M[i][j] pour accéder (ou modier avec =) au
coecient de coordonnées (i, j) (i pour la ligne, j pour la colonne).
5. Si M est une matrice, len(M) renvoie son nombre de lignes ! Pour avoir le nombre
de colonnes on peut regarder la taille d'une ligne, par exemple len(M[0]).
6. Il y a aussi la commande M.shape (sans parenthèses) qui renvoie directement le
couple (n, m) (nombre de lignes, nombre de colonnes).
7. Si M est une matrice, M[i] renvoie sa i-ème ligne, et M [:, j] sa j -ième colonne.
Pour comprendre les diérences entre les listes et les vecteurs, on propose l'exercice
suivant : dénir les objets :

L1 = [1,2,3]
L2 = [4,5,6]

v1 = np.array(L1)
v2 = np.array(L2)

Exécuter puis commenter ce qui est renvoyé par les commandes suivantes :

1
print(L1 + L2)
print(v1 + v2)
print(2 * L1)
print(2 * v1)
print(1.5 * L1)
print(1.5 * v1)
print(L1 ** 2)
print(v1 ** 2)
L1.append(7)
v1.append(7)
print(np.sin(v1))

Exercice 2 : Le type np.uint8 Pour : entier non signé codé sur 8 bits.

On représentera les niveaux de gris par un entier codé sur 8 bits entre 0 et 28 − 1 = 255
(voir cours du second semestre), à l'aide du type np.uint8 de Python. Pour comprendre
son incidence sur les opérations élémentaires, exécuter et commenter le code suivant :

a = np.uint8(280)
b = np.uint8(240)
print(a)
print(a+b)
print(a-b)
print(a//b)
print(a/b)

Les fonctions numpy qui eectuent de manière répétitive des opérations élémentaires
prennent la précaution d'utiliser pour leurs calculs intermédiaires et leur résultat un
type compatible avec le type de base de la plus grande capacité possible. Par exemple
le résultat de np.sum(np.array([100, 200], dtype=np.uint8)) est de type np.uint32
(entier non signé codé sur 32 bits) et vaut bien 300. On les utilisera donc si besoin.

Exercice 3 : Images et matrices de pixels

Les images sont représentées par des matrices de pixels. On distingue deux catégories :
1. Les images en couleur : chaque pixel code une couleur sous forme d'un vecteur
de taille 3 contenant 3 entiers associés à la décomposition de la couleur dans le
système RVB (rouge-vert-bleu), codés en général sur 8 bis (donc de type np.uint8,
voir exercice 2). Ainsi une image en couleur est une "matrice de vecteurs" donc un
tableau à 3 dimensions. Si img est une telle image, img[i,j] renvoie le pixel de
coordonnées (i, j), c'est donc un vecteur de taille 3.
2. Les images en niveaux de gris : chaque pixel n'est cette fois représenté que par un
seul entier, codant la nuance de gris entre le noir (0) et le blanc (255). Une image
en niveaux de gris est une matrice (donc un tableau à 2 dimensions).

2
Pour manipuler des images avec Python, on importe les modules :
import numpy as np
import matplotlib.pyplot as plt
Pour des manipulations plus complexes, on peut aussi utiliser from scipy import
ndimage mais ce n'est pas le cas dans ce TP.
Une image au format JPEG peut être convertie en matrice de pixels à l'aide de la
commande :
img = plt.imread("image.jpg")
Téléchargez sur Cahier de prépa l'image "plage.jpg", l'enregistrer dans le répertoire de
travail (c'est celui où sont enregistrés les chiers créés sur Python, voir le TP "Lecture
et écriture de chiers"), puis l'ouvrir à l'aide de cette commande, observez la nature et
les dimensions de l'objet img. Les fonctions des exercices suivants pourront être testées
sur cette image.
Pour acher une image associée à une matrice de pixels, on utilisera :
plt.imshow(img)
plt.show()
Si l'image est en niveaux de gris :
plt.imshow(img, cmap = plt.cm.gray)
plt.show()
Remarque :La commande plt.imsave permet de d'enregistrer une matrice de pixels
dans un chier.

Exercice 4 : Traitement d'images

1. Écrire une fonction gris(p) prenant en entrée un pixel de couleur (donc un vecteur
de taille 3) et renvoyant le niveau de gris correspondant à la moyenne de ses 3
composantes RVB, arrondie à l'entier le plus proche. On utilisera les commandes :
- np.mean(v) : renvoie la moyenne des éléments du vecteur v (sous forme d'un
ottant), compatible avec le type np.uint8 (voir exercice 2)
- round pour arrondir un ottant en entier
- on convertira le résultat en entier codé sur 8 bits à l'aide du type np.uint8
2. Écrire une fonction conversion(img) prenant en entrée une image en couleurs
(donc un tableau à 3 dimensions) et renvoyant une image en niveaux de gris (donc
un tableau à 2 dimensions) construite à partir de celle-ci en prenant pour chaque
pixel la moyenne (arrondie) de ses 3 composantes RVB.
Remarque : Si vous voulez enregistrer votre image en niveau de gris dans un -
chier, il faudra utiliser : plt.imsave(<fichier>,<matrice>,cmap = plt.cm.gray).

Dans toute la suite, on ne manipulera que des images en niveaux de gris, donc des

tableaux à 2 dimensions.

3
3. Écrire une fonction inverser(A) renvoyant l'image inverse de A, c'est-à-dire que
chaque pixel de niveau de gris p est remplacé par celui de niveau 255-p.
4. Écrire une fonction flip(A) renvoyant l'image obtenue à partir de A en appliquant
une symétrie d'axe vertical passant par le milieu de l'image.
5. Écrire une fonction tourner(A) renvoyant l'image obtenue à partir de A en appli-
quant une rotation de 90°.
6. On souhaite maintenant redimensionner une image. On dispose d'une image A de
taille (N, M ) que l'on veut redimensionner en appliquant un facteur f .
On obtient alors une image R de taille (n = bf · N c, m = bf · M
h
c).
i
On devrait alors avoir pour (i, j) ∈ [[0, n[[×[[0, m[[ : R[i, j] = A i j
f, f .
Malheureusement, sauf si f est l'inverse d'un entier, i
f et j
f ne sont en général pas
des entiers.
a) Méthode du plus proche voisin :
Dans cette méthode, on remplace fi et fj par leurs arrondis entiers ou leurs
parties entières.
Si on veut prendre les arrondis, il faut faire attention à ne pas sortir de l'image
d'origine.
Écrire une fonction ppvoisin(A,f) prenant en entrée une image A en niveaux
de gris et facteur f et qui renvoie une nouvelle image en ayant appliqué à A le
facteur f de l'interpolation au plus proche voisin.
Dans un premier temps, vous utiliserez les parties entières et si vous avez du
temps, les arrondis.
b) Par interpolation bilinéaire
Étant donné deux entiers a et b et une fonction f à deux variables, on interpole
f en ((a, b), (a + 1, b), (a, b + 1), (a + 1, b + 1)) par une fonction du type :
g(x, y) = α + β(x − a) + γ(y − b) + δ(x − a)(y − b).
En remplaçant x et y par a, a + 1 , b et b + 1 on obtient :
α = f (a, b), β = f (a + 1, b), γ = f (a, b + 1) − f (a, b) et δ = f (a + 1, b + 1) +
f (a, b) − f (a + 1, b) − f (a, b + 1).
Écrire une fonction qui modie la taille d'une image par interpolation bilinéaire.
Attention : il peut y avoir des problèmes au bord de l'image.

7. On souhaite maintenant détecter les contours d'une image. Pour cela on remplace
chaque pixel A(i, j) par la norme de son gradient discret :
(A(i, j) − A(i, j − 1))2 + (A(i, j) − A(i − 1, j))2 (sauf pour la première ligne et
p

la colonne où on mettra des 0). Écrire une fonction contour(A) réalisation cette
opération à l'image A (pour plus de lisibilité, on pourra renvoyer une image inver-
sée). Pour réaliser la soustraction de deux entiers x et y codés sur 8 bits, on pourra
écrire x + (-1)*y (le résultat sera codé sur 32 bits), et on pourra utiliser np.sqrt
pour la racine carrée.

Vous aimerez peut-être aussi