Un contour est un changement brusque de clarté
Un contour est une ligne où la luminosité change brusquement. On le détecte en mesurant la variation entre pixels voisins, que l’on appelle le gradient.
Les contours dessinent la forme des objets : le bord d’une route, d’une lettre ou d’une pièce. C’est souvent plus utile que les couleurs elles-mêmes.
À la fin de cette leçon
Remarque
Je peux trouver les contours d’une image avec un gradient et un seuil.
Mots clés
| Mot | Ce que ça veut dire |
|---|---|
| Contour | une ligne où la clarté change brusquement |
| Gradient | la variation de clarté entre deux pixels voisins |
| Force du contour | la taille du gradient en un pixel |
| Seuil de contour | la force à partir de laquelle un pixel est un contour |
| Lissage | un flou léger avant de chercher les contours |
| Détecteur de Canny | une méthode qui rend des contours fins |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Le gradient mesure le changement de clarté
Dans une zone uniforme, les voisins ont presque la même valeur : rien ne change. Sur un bord, la valeur saute du sombre au clair.
Pour mesurer ce saut, prenez la valeur de droite moins celle de gauche. Faites de même avec celle d’en bas moins celle d’en haut. La force est la somme des deux écarts, sans leur signe.
Exemple travaillé : du sombre au clair
| Colonne | 0 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|---|
| Valeur | 10 | 10 | 10 | 200 | 200 |
| Droite moins gauche | (bord) | 0 | 190 | 190 | (bord) |
| Force | (bord) | 0 | 190 | 190 | (bord) |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Calculer la force le long d’une ligne
# Une ligne de pixels : du sombre, puis du clair.
ligne = [10, 10, 10, 200, 200]
for colonne in range(1, 4):
force = abs(ligne[colonne + 1] - ligne[colonne - 1])
print("colonne", colonne, "force", force)
# Remplacez les deux 200 par 100, puis relancez.
# Que devient la force ? Et si toute la ligne vaut 10 ?
Canny trouve des contours fins et propres
Le détecteur de Canny ajoute des soins à cette idée. Il lisse l’image et mesure le gradient. Il garde le pixel le plus fort de chaque bord, pour le rendre fin. Puis il ne retient que les bords assez forts.
Scikit-image l’offre sous feature.canny, avec un réglage sigma pour la force du lissage. Le script edges.py l’applique à shapes.png, des formes de couleurs vives sur fond blanc.
Trouver les contours avec edges.py
docker exec jupyter python3 steps/edges.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 erreur fréquente
Attention
Beaucoup pensent qu’un contour est un pixel sombre. Un contour est un endroit où la clarté change, que le côté sombre soit à gauche ou à droite. Une grande zone noire, ou blanche, n’a aucun contour en son milieu.
Les lignes d’une route sont des contours
Sur l’image road.png, une ligne blanche de six pixels de large a deux bords. L’un va du gris vers le blanc, l’autre du blanc vers le gris. Chaque trait de la ligne centrale en a aussi.
Compter les pixels de contour donne une idée de la quantité de détails de l’image.
Compter les contours de la route
docker exec jupyter python3 -c "import numpy as np; from PIL import Image; from skimage import feature; g=np.array(Image.open('images/road.png')); print(int(feature.canny(g, sigma=1).sum()), g.size)"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.
Pour aller plus loin
Dans votre carnet, relancez feature.canny sur images/shapes.png en gris avec sigma=3, puis comptez les pixels de contour.
Trouvez-vous plus ou moins de contours qu’avec sigma=1 ? Dites en une phrase pourquoi un lissage fort supprime des détails.