Une photo, c’est une grille de nombres
Une image numérique est un tableau de nombres : chaque case, appelée pixel, retient la luminosité d’un petit point.
Savoir lire ces nombres est la première étape de la vision par ordinateur : mesurer, filtrer ou compter dans une image avec quelques lignes de code. Un programme ne « voit » rien d’autre.
À la fin de cette leçon
Remarque
Je peux lire une image comme un tableau de nombres : sa taille, son mode et la valeur d’un pixel.
Mots clés
| Mot | Ce que ça veut dire |
|---|---|
| Pixel | un point de l’image, mémorisé par un ou plusieurs nombres |
| Taille | la largeur et la hauteur de l’image, en pixels |
| Niveau de gris | un nombre de 0 (noir) à 255 (blanc) |
| Canal | une couche de nombres, comme le rouge |
| Mode | la façon dont les nombres d’un pixel sont rangés |
| Tableau | une grille de nombres rangés par lignes et colonnes |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Un pixel est un point avec une valeur
Une image est découpée en lignes et en colonnes de petits points. Chaque point est un pixel. Une photo de téléphone en compte plusieurs millions.
Dans une image en niveaux de gris, chaque pixel est un seul nombre de 0 à 255. Zéro est noir, 255 est blanc. Les nombres au milieu sont des gris.
Exemple travaillé : 4 lignes, 5 colonnes
| Ligne | Colonne 0 | Colonne 1 | Colonne 2 | Colonne 3 | Colonne 4 |
|---|---|---|---|---|---|
| 0 | 12 | 15 | 14 | 200 | 210 |
| 1 | 10 | 13 | 190 | 205 | 220 |
| 2 | 11 | 14 | 16 | 195 | 90 |
| 3 | 9 | 12 | 13 | 15 | 14 |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Lire une image avec look.py
docker exec jupyter python3 steps/look.pyAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Une image couleur a trois canaux
Un pixel en couleur ne tient pas dans un seul nombre. Il en faut trois : la quantité de rouge, de vert et de bleu. On dit que l’image est en mode RGB, pour red, green, blue.
Chaque couche de nombres, celle du rouge par exemple, est un canal. Le pixel de la pièce, (197, 157, 62), est donc très rouge, assez vert et peu bleu : un jaune doré.
La forme du tableau NumPy
docker exec jupyter python3 -c "import numpy as np; from PIL import Image; a=np.array(Image.open('images/coins.png')); print(a.shape, a.dtype, a[50, 50])"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
La hauteur vient avant la largeur
La commande précédente affiche (240, 320, 3) uint8 [197 157 62]. La forme du tableau se lit : 240 lignes, 320 colonnes, 3 canaux. Les nombres sont des entiers de 0 à 255, le type uint8.
Pillow donne une position par getpixel((x, y)), colonne d’abord. NumPy la lit par a[ligne, colonne], ligne d’abord.
Une erreur fréquente
Attention
Beaucoup pensent que (50, 20) désigne toujours la même case. Ce n’est pas le cas : Pillow lit x puis y, donc colonne 50, ligne 20. NumPy lit la ligne d’abord. Quand une valeur est étrange, vérifiez d’abord l’ordre.
Chercher le pixel le plus clair
# Un petit morceau d'image : 4 lignes, 5 colonnes, des niveaux de gris.
grille = [
[12, 15, 14, 200, 210],
[10, 13, 190, 205, 220],
[11, 14, 16, 195, 90],
[9, 12, 13, 15, 14],
]
meilleur = -1
for ligne in range(len(grille)):
for colonne in range(len(grille[0])):
if grille[ligne][colonne] > meilleur:
meilleur = grille[ligne][colonne]
pos_ligne = ligne
pos_colonne = colonne
print("plus clair :", meilleur, "ligne", pos_ligne, "colonne", pos_colonne)
# Remplacez le 9 de la dernière ligne par 255, puis relancez.
# Où se trouve maintenant le pixel le plus clair ?
Pour aller plus loin
Dans une cellule de votre carnet, ouvrez images/gradient.png et affichez .size, .mode et getpixel((0, 0)). Faites la même chose avec le pixel (255, 0).
Quelle valeur attendez-vous aux deux bouts, et pourquoi cette image est-elle un bon exemple de niveaux de gris ?