Skip to main content Informatique en prépa - Lycée Malherbe 

10.1- TP - Traitement d'image

Ce travail a pour objectif la programmation de plusieurs algorithmes de traitement d'images.

Vous allez travailler sur des images en niveaux de gris qui seront des listes de listes d'entiers compris entre 0 et 255.

La première cellule de code utilise la bibliothèque PIL pour charger trois images qui vous serviront de tests. Ces images au format PIL sont converties en liste de listes, donc vous n'avez pas à vous préoccuper du fonctionnement de la librairie.

Pour afficher ces images vous utiliserez la fonction imshow définie dans cette première cellule.

Vous devrez donc toujours exécuter cette cellule au début de votre travail.

Python
code masqué : pas besoin de le lire pour suivre, exécutez-le simplement
Python

Loading editor...

imshow(guepiers)

I. Préliminaires

Q1

Compléter la fonction dim, qui prend en argument une image et renvoie le couple d'entiers (h, w), w étant la largeur de l'image, et h sa hauteur (en nombre de pixels). On pourra ainsi dans la suite utiliser (h, w) = dim(img) pour récupérer les dimensions d'une image.

Python

Loading editor...

def dim(image) :
    ...

Dans la plupart des questions suivantes, on vous demandera d'écrire une fonction qui réalise une opération sur une image. Vous ne devez pas modifier les images originelles (par exemple "guepiers"). Si vous avez besoin de réaliser la copie d'une image, vous pouvez utiliser la ligne suivante :

copie = [[pixel for pixel in ligne] for ligne in image]
Q2

Écrivez une fonction inverse(image) qui renvoie l'image avec son contraste inversé (un pixel blanc doit devenir noir, et vice-versa).

Python

Loading editor...

II. Les convolutions

Beaucoup d'opérations de traitement d'images utilisent des convolutions. C'est une opération très générale, qui consiste à appliquer un "filtre" à une image.

Image
20
20
20
20
20
20
20
20
200
200
200
20
20
20
20
200
200
200
20
20
20
20
200
200
200
20
20
20
20
20
20
20
250
20
20
20
20
20
20
20
250
20
20
20
20
20
20
20
20
Filtre
1/9
1/9
1/9
1/9
1/9
1/9
1/9
1/9
1/9
Résultat
1 / 26

Chaque pixel de sortie est la somme des 9 pixels autour, multipliés par les coefficients du filtre.

On se donne une image, et un filtre (qui est une matrice 3x3 dans notre cas). Chaque pixel de l'image de sortie est la somme des 9 pixels qui l'entourent, multipliés par les cofficients contenus dans le filtre.

Pour vous aider à visualiser cette opération, vous pouvez utiliser ce site.

On va s'intérésser à la réalisation d'une fonction permettant de réaliser une convolution.

Q3

Écrivez une fonction filtre_un_pixel(image, filtre, y, x) qui applique le filtre à l'image à la position (y, x), et renvoie le pixel résultat. On suppose et .

On veut ainsi renvoyer la somme :

image[y-1][x-1]*filtre[0][0] + image[y-1][x]*filtre[0][1] + image[y-1][x+1]*filtre[0][2] +  
image[y][x-1]*filtre[1][0]   +    ...
                                  ...                     + image[y+1][x+1]*filtre[2][2]

NB : écrire la somme en entier fonctionne, mais mieux vaut utiliser des boucles...

Python

Loading editor...

Q4

En déduire une fonction convolution(image, filtre) qui renvoie la convolution de l'image par le filtre. Vous pouvez ignorer les bords (en enlevant les premières lignes et colonnes, ou bien en mettant des pixels noirs).

Python

Loading editor...

Q5

Appliquer les filtres suivants sur les images donnés, et décrivez leur effet en une phrase.

Filtre 1 :

Python

Loading editor...

Filtre 2 :

Python

Loading editor...

Filtre 3 :

Python

Loading editor...

III. Réduction d'image

Dans cette partie, on va essayer de réduire des images dans le sens de la largeur.

A. Réduction naïve de moitié

Q6

Écrire une fonction reduction_moitie_ligne, qui prend en argument une liste de longueur paire contenant des entiers , et renvoie la liste de longueur contenant , etc.

Python

Loading editor...

Q7

Écrire une fonction reduction_moitie_image, qui prend en argument une image (ayant une largeur paire) et en construit une nouvelle en appliquant à chaque ligne l'opération décrite dans la question précédente.

Python

Loading editor...

Q8

Quelle est sa complexité en fonction du nombre de lignes et du nombre de colonnes de l'image?
Testez, et constatez la déformation obtenue. (Justifier la complexité)

Python

Loading editor...

# tests

B. Calcul de l'énergie d'un pixel

Si l'on note le niveau de gris du pixel de coordonnées , l'énergie d'un pixel intérieur à l'image est définie comme

Cette quantité est d'autant plus petite que le pixel est dans une zone uniforme de l'image, et d'autant plus grande qu'il est dans une zone de forte variation du niveau de gris (par exemple au niveau d'un contour).

Il s'agit en fait d'une version discrétisée de , qui est une norme du gradient de l'image.

Q9

  • Complétez la fonction energie, qui prend en argument une image, et renvoie une nouvelle image correspondant à son énergie (les pixels n'auront plus nécessairement une valeur entière).
    On réfléchira en particulier à comment adapter la formule ci-dessus à un pixel situé sur un bord de l'image.
  • Testez, et affichez l'image des énergies obtenue.
Python

Loading editor...

def energie(img):
    '''Calcule l'énergie d'une image img.'''
    (h, w) = dim(img)
    
    
    return e
Python

Loading editor...

C. Deux algorithmes

Nous disposons d'une image et de son énergie.
Nous allons programmer deux algorithmes pour réduire l'image en utilisant l'énergie

  1. Pour réduire la largeur d'une image d'un pixel, nous allons simplement enlever un pixel d'énergie minimale dans chaque ligne.
  2. Pour réduire la largeur d'une image d'un pixel, nous allons supprimer la colonne de moindre énergie
Q10

Écrire une fonction indice_min qui renvoie l'indice de la valeur minimale d'une liste.

Python

Loading editor...

def indice_min(L):
    ...
Python

Loading editor...

Q11

Écrire une fonction enlever, qui prend en argument une liste L et un indice i compris entre 0 et la longueur de L moins 1, et renvoie une nouvelle liste correspondant à L dont l'élément d'indice i a été supprimé. On pourra utiliser des extractions de tranches et concaténations de listes.

Python

Loading editor...

def enlever(L, i):
    ...
Python

Loading editor...

Q12

Écrire le code de la fonction reduction_par_ligne, qui prend en arguments une image img et son énergie, et la modifie en supprimant un pixel d'énergie minimale dans chacune de ses lignes.

Votre fonction devra aussi enlever le pixel correspondant du tableau énergie.

Python

Loading editor...

def reduction_par_ligne(img, e):
    ...
Python

Loading editor...

Q13

Écrire le code de itere_reduction_par_ligne, qui prend en arguments une image img et un entier , applique fois la procédure décrite dans la question précédente à img. On ne veut calculer l'energie qu'une seule fois au total !

Python

Loading editor...

def iterer_reduction_par_ligne(img, n):
    ...
Python

Loading editor...

Q14

  • Quelle est sa complexité?
  • La tester. (On pourra par exemple réduire de 100 pixels la largeur de l'image flamants : au-delà, le calcul risque de dépasser la limite de 15 secondes.)
  • Expliquez les distorsions observées.
Python

Loading editor...

# tests
Question 15 : Programmation de l'algorithme 2

L'énergie d'une colonne est la somme des énergies des pixels de la colonne.

  • Écrire une fonction meilleure_colonne qui renvoie l'indice de la colonne d'énergie minimale d'une image.
  • Écrire le code de itere_reduction_colonne, qui prend en arguments une image img et un entier , et supprime n fois la colonne d'energie minimale. Votre fonction devra calculer une seule fois l'energie.
  • Testez, et expliquez qualitativement pourquoi les résultats obtenus sont «bons» sur les images guepiers et flamants, mais pas sur rue.
Python

Loading editor...

def meilleure_colonne(img, e):
    pass
Python

Loading editor...

Python

Loading editor...

def itere_reduction_colonne(img, n):
    pass
Python

Loading editor...

#tests

Entrez le code donné en cours pour accéder à la solution :