Traitement d'image

In [ ]:
%pylab inline
Populating the interactive namespace from numpy and matplotlib
In [ ]:
def display(pixels):
    plt.figure(figsize=(8, 6))
    if len(pixels.shape) == 2:
        plt.imshow(pixels, cmap='gray', vmin=0, vmax=255, 
                   interpolation='none')
    else:
        plt.imshow(pixels, interpolation='none')

Image en noir et blanc

C'est bien connu, une image est composée de pixels. Ces pixels peuvent être décrits par un tableau de nombres. La façon la plus efficace de manipuler des tableaux de nombres en Python est d'utiliser la bibliothèque Numpy.

Dans ce TP vous allez écrire des programmes réalisant quelques tranformations simples sur une image.

Exécutez l'instruction suivante :

In [ ]:
pixels = plt.imread("damier-ng.jpeg")

L’image stockée dans le fichier damier-ng.jpeg est maintenant représentée en mémoire sous la forme d’un tableau 2D accessible sous le nom pixels :

In [ ]:
pixels
Out[ ]:
array([[254, 254, 254, ..., 254, 254, 254],
       [254, 254, 254, ..., 254, 254, 254],
       [255, 255, 255, ..., 255, 255, 255],
       ..., 
       [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255]], dtype=uint8)

Comme le montre les double crochets, il s'agit d'un tableau à deux dimensions. Plus précisément :

In [ ]:
pixels.shape
Out[ ]:
(795, 1024)

L'image comporte 795 pixels en hauteur et 1024 pixels en largeur.

Chaque pixel est représenté par un entier positif codé sur 8 bits, donc compris entre 0 et 255.

In [ ]:
display(pixels)

Le slicing

Les cases du tableau peuvent être accédées individuellement ou par tranche (slice en anglais) :

Syntaxe Signification
pixels[i, j] Pixel de coordonnées (i, j)
pixels[i:r, j:s] Sous-tableau 2D formé des lignes de i à r-1 et des colonnes de j à s-1
pixels[:i, j:] Sous-tableau 2D formé des lignes strictement inférieures à i et des colonnes supérieures ou égales à j
pixels[:, j] Colonne j (tableau 1D)

La bibliothèque Numpy permet d'écrire du code à la fois concis et efficace. Par exemple :

In [ ]:
pixels = plt.imread("damier-ng.jpeg")
pixels[50:250, 150:250] = 80
display(pixels)

Question 1

Les cases $A$ et $B$ sont-elles de la même couleur ? Pour aider à répondre à cette question, dessiner un rectangle gris qui recouvre une partie des deux cases.

In [ ]:
 

Question 2

Créez un bord gris de 100 pixels d’épaisseur tout autour de l’image.

In [ ]:
 

Question 3

Modifier l'image en inversant l’intensité des pixels. En particulier le blanc et le noir seront inversés.

Utilisez pour cela deux boucles imbriquées

In [ ]:
 

Question 4

Modifier l'image en effectuant une symétrie par rapport à l'axe vertical.

In [ ]:
 

Image en couleur

N'importe quelle couleur peut être produite en superposant des sources de lumières rouge, verte et bleue dans des proportions adéquates. La couleur d'un pixel peut donc être représentée par trois nombres compris entre 0 et 255 donnant respectivement les quantités de chacune des couleurs primaires rouge, verte et bleue. C'est le principe du codage RGB.

Une image couleur est donc décrite par un tableau à trois dimensions : (hauteur, largeur, 3). On peut se représenter ce tableau comme la superposition de trois tableaux 2D.

  • pixels[i, j, 0] est l'intensité de rouge du pixel de coordonnées (i, j)
  • pixels[i, j, 1] est l'intensité de vert du pixel de coordonnées (i, j)
  • pixels[i, j, 2] est l'intensité de bleu du pixel de coordonnées (i, j)

Le code ci-dessous a pour effet de créer un tableau à trois dimensions à partir d'une l'image en noir et blanc damier-ng.jpeg.

In [ ]:
pix = plt.imread("damier-ng.jpeg")
hauteur, largeur = pix.shape
pixels = np.zeros((hauteur, largeur, 3), dtype=np.uint8)
pixels[:, :, 0] = pix
pixels[:, :, 1] = pix
pixels[:, :, 2] = pix
display(pixels)

Cette image apparait toujours en niveau de gris car les trois couches sont identiques. Modifions le canal rouge d'une zone rectangulaire :

In [ ]:
pix = plt.imread("damier-ng.jpeg")
hauteur, largeur = pix.shape
pixels = np.zeros((hauteur, largeur, 3), dtype=np.uint8)
pixels[:, :, 0] = pix
pixels[:, :, 1] = pix
pixels[:, :, 2] = pix
pixels[300:500, 600:800, 0] = 255
display(pixels)

La fonction randint du module python random permet d'obtenir des entiers aléatoires

In [ ]:
from random import randint

print(randint(1, 100))
print(randint(1, 100))
33
38

Question 5

Créer une image de 20 pixels sur 20 pixels en choisissant au hasard la couleur de chaque pixel.

In [ ]:
 

Question 6

L'image ci-dessus provient du fichier brba.jpeg. Modifier cette image en remplaçant le fond jaune par un fond vert.

In [ ]: