Détecteur de contours Sobel vs Canny

Fais passer une image de test à travers le pipeline complet de détection de contours qui se cache derrière la vision robotique — niveaux de gris, flou gaussien, gradients de Sobel, suppression des non-maxima, hystérésis de Canny — et survole n'importe quelle étape pour inspecter les mathématiques derrière un seul pixel.

Chargement de la simulation interactive...

pourquoi flouter d'abord, et pourquoi deux seuils 🖖

Une dérivée amplifie tout ce qu’on lui donne, bruit compris : si vous dérivez directement une image brute, la moindre fluctuation d’un pixel prend l’apparence d’un contour. Une convolution gaussienne préalable (étape 2) résorbe ce bruit par moyennage, sans presque altérer les variations d’intensité à grande échelle qui correspondent aux véritables contours. C’est pourquoi, en pratique, tout détecteur fondé sur le gradient lisse l’image avant de la dériver. Les noyaux de Sobel sont eux-mêmes des approximations séparables des dérivées partielles ∂I/∂x et ∂I/∂y. Leur pondération 1-2-1 suivant l’axe perpendiculaire donne davantage de poids à la ligne ou à la colonne centrale. Appliquer un seuil unique à la norme du gradient impose un choix insoluble : trop bas, il laisse le bruit parsemer le résultat ; trop haut, il morcelle les contours peu contrastés en pointillés. Le seuillage par hystérésis (étape 6) évite ce compromis grâce à deux seuils. Le seuil haut (Thigh) repère les contours dont la présence ne fait guère de doute. Le seuil bas (Tlow) ne s’applique qu’aux pixels déjà voisins d’un contour fort. Un contour réel peut ainsi traverser une zone momentanément peu marquée, sans que le bruit puisse en amorcer un à lui seul. Ce même principe de double seuillage intervient dans la segmentation par remplissage et dans les circuits à bascule de Schmitt, partout où un seuil unique provoquerait des oscillations.

Deux questions sur une même image 🖖

Sobel et Canny posent des questions différentes sur la même image. Sobel produit une carte de gradient : chaque pixel reçoit un nombre indiquant la brutalité du changement de luminosité, si bien que les contours ressortent épais et en niveaux de gris, comme une lueur diffuse. Canny reprend ce même gradient et impose une décision : la suppression des non-maxima ne garde que le pixel le plus lumineux sur toute la largeur de chaque crête, amincissant la lueur en une ligne nette d'un pixel, puis la classe comme contour ou non. Basculez entre les onglets Gradient et Canny pour voir une carte floue se réduire à un tracé net.

Les contours de Canny cachent un compromis intrinsèque 🖖

John Canny n'a pas trouvé sa recette à tâtons. Dans son article de 1986, il a formulé la détection de contours comme une optimisation à trois objectifs — détecter les vrais contours, les localiser précisément et ne répondre qu'une fois par contour — et l'a résolue par le calcul des variations ; la solution s'est révélée être presque exactement la dérivée première d'une gaussienne. Le hic qu'il a aussi démontré : détection et localisation s'opposent à mesure que le flou s'élargit, si bien qu'un σ plus grand trouve des contours plus faibles mais brouille leur position, et aucun σ n'est le meilleur pour les deux. Faites glisser σ et observez.

Problème entièrement résolu

  1. Norme du gradient au pixel (31, 3) de l'image test en damier 9 étapes

    L'image de test en damier — noir et blanc pur, carrés de 32 pixels de large — à σ = 1,0 avec le noyau de flou 3×3, Tlo = 30 et Thi = 80. Calculez la magnitude du gradient au pixel (31, 3), la dernière colonne blanche avant la première frontière verticale, puis déterminez combien de pixels de large fait le contour auquel il appartient.

    1. Passons d'abord en niveaux de gris, ce qui n'a aucun effet sur cette image : les trois poids s'additionnent pour donner exactement 1, de sorte qu'un pixel ayant des valeurs égales pour le rouge, le vert et le bleu conserve sa valeur. Le blanc reste à 255, le noir reste à 0, donc chaque nombre ci-dessous provient de ces deux seules valeurs.

    2. Les poids gaussiens décroissent avec le carré de la distance. À σ = 1, le centre reçoit 1, les 4 pixels partageant un côté reçoivent e-0,5 = 0,6065 et les 4 coins reçoivent e-1 = 0,3679 ; en divisant par le total de 4,8976, on en fait une moyenne pondérée.

    3. La ligne 3 se situe bien à l'intérieur d'une bande horizontale, de sorte que les 3 lignes de n'importe quelle fenêtre s'y trouvant sont identiques et la structure verticale du noyau s'annule. Seuls ses totaux par colonne comptent, et il n'y en a que 2.

    4. Flou de part et d'autre de la frontière. À x = 31, la fenêtre couvre 2 colonnes blanches et 1 noire ; à x = 32, elle couvre 1 blanche et 2 noires. Le saut net de 255 à 0 est devenu la rampe 255, 185, 70, 0 — ces 2 valeurs centrales, arrondies, sont celles qu'affiche l'inspecteur.

    5. Sobel pondère la colonne de gauche par -1, -2, -1, celle de droite par +1, +2, +1, et la colonne centrale par rien du tout. Avec 3 lignes égales, ces poids se réduisent à un facteur unique de 4, si bien que la convolution complète vaut 4 fois la différence entre les colonnes de chaque côté.

    6. Le gradient vertical s'annule pour la raison symétrique inverse : la ligne au-dessus du pixel et la ligne au-dessous sont constituées des 3 mêmes nombres, de sorte que la somme +1, +2, +1 annule terme à terme la somme -1, -2, -1. Ce contour présente un gradient purement horizontal, ce qui simplifie l'étape suivante.

    7. En combinant les deux, la magnitude est simplement la magnitude horizontale.

    8. Comparez avec ce que donnerait le même contour sans flou : un saut brut de 255 à travers le même noyau. Le lissage a coûté 280 unités, soit un peu plus de 27 % de la réponse disponible, et c'est le prix de l'immunité au bruit — non pas une perte par arrondi, mais un compromis délibéré.

    9. Répétez à présent une colonne plus à droite. À x = 32, la fenêtre lit 185, 70, 0, donc la différence vaut à nouveau -185 et la magnitude vaut à nouveau 740. Une colonne plus loin de chaque côté, la différence s'effondre à environ -70 et la magnitude à 280.

    Réponse

    740 — et le contour s'avère large de 2 pixels. La suppression des non-maxima conserve un pixel lorsque sa magnitude est ≥ à celle de ses deux voisins le long du gradient. Ici, le gradient est orienté selon x, le pixel 31 est donc comparé à 280 sur sa gauche et 740 sur sa droite, et le pixel 32 à 740 et 280. Chacun est à égalité avec l'autre, et une égalité satisfait ≥, les deux survivent donc ; à 740, tous deux dépassent de plus de 9 fois Thi = 80, ils ressortent donc tous deux en blanc. Aucun couple de seuils ne peut les séparer, car les seuils n'en sont pas la cause. La véritable frontière se situe à x = 31,5, exactement à mi-chemin entre le dernier pixel blanc et le premier pixel noir, et un flou symétrique laisse le gradient symétrique par rapport à ce demi-entier — il n'y a pas de maximum unique à trouver. C'est bon à savoir avant de régler quoi que ce soit : une ligne doublée dans une carte de contours est parfois un défaut de seuillage, parfois de l'arithmétique, et ici il s'agit de 740 = 740 sur une image dont les carrés se trouvent avoir une largeur entière en pixels.

Références (1)

Exemples de problèmes

  • Formes nettes - État par défaut : σ = 1,4, avec les seuils 30 et 80, dans l’onglet Canny. Sur une géométrie nette, un contour d’un pixel ressemble particulièrement au trait d’un dessin.
  • Gradient de damier - C’est le seul préréglage qui s’arrête à la carte du gradient : vous obtenez donc un épais halo gris plutôt qu’une décision binaire. Il reprend aussi les paramètres de l’exercice corrigé : σ = 1,0, Tlo = 30, Thi = 80.
  • Pistes de circuit - Avec σ = 0,8, c’est ici le flou le plus faible, ce qui préserve les fines pistes de cuivre. Les seuils sont identiques à ceux de Visage ; seul σ diffère.
  • Visage lissé - σ = 2,5 avec un noyau 5×5 : trois fois plus de flou que pour Circuit imprimé, à seuils identiques. La texture disparaît, les structures subsistent, mais la position des contours s’étale elle aussi.