Séparer un objet du fond avec un seuil
Le seuillage sépare les objets du fond : tout pixel plus clair qu’un niveau choisi, le seuil, devient blanc, et les autres deviennent noirs.
C’est la méthode la plus simple pour isoler une pièce de monnaie, une lettre ou une tache avant de la mesurer. Un histogramme aide à choisir le bon niveau.
À la fin de cette leçon
Remarque
Je peux choisir un seuil avec un histogramme et compter les pixels d’un objet.
Mots clés
| Mot | Ce que ça veut dire |
|---|---|
| Histogramme | le nombre de pixels pour chaque niveau de gris |
| Classe | une bande de niveaux de gris, comptée ensemble |
| Seuil | le niveau qui sépare le sombre du clair |
| Masque | une image de oui ou non, blanc là où le test réussit |
| Fond | la partie de l’image qui n’est pas l’objet |
| Méthode d’Otsu | un calcul qui choisit le seuil à votre place |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Un histogramme compte les pixels par niveau
Pour une image en niveaux de gris, l’histogramme dit combien de pixels ont chaque valeur. On regroupe souvent les 256 valeurs en quelques classes.
Une image avec des pièces claires sur un fond sombre a deux tas : un tas de pixels sombres et un tas de pixels clairs. Entre les deux, il reste un creux vide.
Exemple travaillé : les pièces en quatre classes
| Classe de gris | Pixels | Ce que c’est |
|---|---|---|
| 0 à 63 | 63 231 | Le fond sombre |
| 64 à 127 | 0 | Le creux entre les deux |
| 128 à 191 | 13 566 | Les pièces |
| 192 à 255 | 3 | Quelques points très clairs |
| Total | 76 800 | 320 colonnes fois 240 lignes |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Compter les pixels par classe
docker exec jupyter python3 steps/grey.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.
L’histogramme d’un dégradé régulier
docker exec jupyter python3 -c "from PIL import Image; h=Image.open('images/gradient.png').histogram(); print(len(h), h[0], h[255])"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.
Un seuil transforme l’image en masque
Un seuil pose une question à chaque pixel : êtes-vous plus clair que ce niveau ? La réponse est oui ou non. Le résultat est un masque, blanc là où la réponse est oui.
La commande précédente affiche 256 64 64 : le dégradé a 256 cases, et 64 pixels dans chacune. Le script threshold.py essaie trois seuils sur les pièces.
Essayer trois seuils avec threshold.py
docker exec jupyter python3 steps/threshold.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.
Exemple travaillé : trois seuils sur 76 800 pixels
| Seuil | Pixels gardés | Part de l’image | Verdict |
|---|---|---|---|
| 30 | 58 806 | 76,6 % | Trop bas : le bruit du fond passe aussi |
| 100 | 13 569 | 17,7 % | Bon : le seuil est dans le creux |
| 160 | 10 062 | 13,1 % | Trop haut : il mord dans les pièces |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Une erreur fréquente
Attention
Beaucoup pensent que l’ordinateur trouve seul le bon seuil. Ici, 100 marche parce que vous avez regardé l’histogramme. Sur une page numérisée à l’éclairage inégal, un seul seuil peut réussir à gauche et échouer à droite. Vérifiez toujours le masque à l’œil.
La méthode d’Otsu calcule un seuil
Quand le creux est net, on peut choisir à l’œil. Sinon, la méthode d’Otsu cherche le seuil qui sépare le mieux les deux tas. Elle ne comprend pas l’image : elle regarde seulement l’histogramme.
Scikit-image la propose sous le nom threshold_otsu. Sur les pièces, elle rend 63, au bord du fond sombre.
Laisser Otsu choisir le seuil
docker exec jupyter python3 -c "import numpy as np; from PIL import Image; from skimage import filters; g=np.array(Image.open('images/coins.png').convert('L')); print(filters.threshold_otsu(g))"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.
Compter les pixels au-dessus d’un seuil
# Une petite image de 3 lignes, 4 colonnes, et un seuil.
grille = [
[20, 25, 200, 210],
[18, 30, 205, 90],
[22, 24, 28, 26],
]
seuil = 100
compte = 0
for ligne in grille:
for valeur in ligne:
if valeur > seuil:
compte = compte + 1
print("pixels au-dessus de", seuil, ":", compte)
# Changez le seuil en 50, puis en 205. Que devient le compte ?
# Quel seuil sépare le mieux les deux groupes de cette grille ?
Pour aller plus loin
Dans votre carnet, ouvrez images/scan.png en gris et appliquez un seuil de 180 sur la moitié gauche, puis sur la moitié droite. Comptez les pixels gardés des deux côtés.
L’éclairage de la page n’est pas régulier. Les deux comptes sont-ils proches ? Dites ce que cela change au choix d’un seuil unique.