5.14. Lissage gaussien et contours¶
Deux tâches dominent l’usage des fenêtres de voisinage en vision industrielle classique : lisser proprement les variations de pixel à pixel, et trouver les contours là où l’image change brusquement. Le filtre gaussien est l’outil standard pour la première, les détecteurs fondés sur le laplacien l’outil standard pour la seconde – et les deux se composent, car tout détecteur de contours fonctionne mieux sur une entrée légèrement lissée.
5.14.1. Le filtre gaussien¶
gaussian() est le cousin pondéré vers le centre de mean(). Tous deux calculent une moyenne sur le voisinage de chaque pixel, mais les poids du gaussien ne sont pas uniformes : les pixels plus proches du centre du voisinage comptent davantage, ceux au bord du voisinage comptent moins, les poids suivant la fameuse courbe en cloche qui donne son nom au filtre.
La pondération en forme de cloche est ce qui rend un filtre gaussien plus lisse qu’une moyenne de boîte. Le filtrage par moyenne peut produire des artefacts visibles aux bords des objets – une coupure brutale dans la pondération introduit de petits motifs d’oscillation aux transitions nettes. Les poids du gaussien, qui décroissent en douceur, évitent ces oscillations et produisent un résultat plus proche de ce à quoi un « flou » devrait ressembler. Le coût est davantage de calcul par pixel que le filtre de moyenne, mais pas de façon spectaculaire – le coût par pixel reste bien inférieur à celui du filtre bilatéral.
img.gaussian(1) # 3x3 Gaussian -- a clean light blur
img.gaussian(2) # 5x5 Gaussian -- stronger smoothing
Le lissage gaussien est la première étape standard de presque tout pipeline de détection de contours. Les détecteurs de contours ci-dessous amplifient tous le contenu haute fréquence, y compris le bruit du capteur que l’algorithme ne veut en réalité pas détecter. Exécuter d’abord un léger gaussien atténue ce bruit sans trop adoucir les vrais contours, laissant le détecteur de contours trouver de vrais contours plutôt que du bruit ponctuel.
5.14.2. Masque flou (unsharp masking)¶
Une copie floutée par gaussien d’une image est la matière première qu’utilise la technique du masque flou (unsharp mask) pour l’accentuation classique. Définir unsharp=True sur le filtre le fait passer de « produire l’image floutée » à « soustraire l’image floutée de l’originale et rajouter la différence à l’originale » – l’effet est que les contours haute fréquence se trouvent amplifiés par rapport aux intérieurs lisses.
img.gaussian(1, unsharp=True)
Les paramètres optionnels mul et add règlent l’intensité du résultat du masque flou ; les valeurs par défaut (mul=1.0, add=0.0) correspondent à une accentuation modérée qui n’exagère pas le bruit du capteur.
5.14.3. Le filtre laplacien¶
laplacian() exécute une approximation discrète de la dérivée spatiale seconde de l’image. La sortie est élevée là où les valeurs des pixels changent rapidement, proche de zéro là où elles sont constantes ou varient linéairement. La lecture naturelle du résultat est une réponse de contours : les pixels où l’image change rapidement s’illuminent, les pixels des intérieurs lisses restent sombres.
img.laplacian(1) # 3x3 Laplacian -- edge response
Les mêmes paramètres que gaussian sont disponibles. sharpen=True produit une image accentuée (le laplacien ajouté à l’originale plutôt que renvoyé seul). mul et add règlent la réponse.
Un usage pratique au-delà de la détection de contours est la mesure de la mise au point. La réponse du laplacien moyennée sur une région donne une mesure approximative de la quantité de contenu haute fréquence que porte la région ; sur une trame bien mise au point, cette moyenne est élevée, sur une trame floue elle chute. Comparer la réponse du laplacien d’une trame à l’autre est le moyen peu coûteux de demander « l’objectif est-il au point ? » sans avoir besoin d’une métrique de contraste plus coûteuse.
5.14.4. La méthode find_edges¶
find_edges() exécute un pipeline complet de détection de contours plutôt qu’un simple filtre de réponse de contours. Elle fonctionne sur les images en niveaux de gris, et le résultat est une image binaire dont les pixels non nuls marquent les positions où l’entrée présente le type de changement de luminosité qui doit compter comme un contour.
La méthode prend un paramètre edge_type qui choisit entre deux algorithmes :
EDGE_SIMPLE exécute un filtre passe-haut, applique un seuil et renvoie le résultat. Rapide, mais la sortie inclut tout changement de luminosité au-dessus du seuil, y compris le bruit et la texture dont l’application ne se soucie probablement pas. Raisonnable pour des images propres et pour les cas où le bruit sera nettoyé par une passe morphologique ultérieure.
EDGE_CANNY exécute le détecteur de contours Canny – l’algorithme classique à plusieurs étapes. Il calcule le gradient de luminosité, supprime toute réponse non maximale le long de la direction du gradient (de sorte que chaque contour fasse un pixel de large), et applique un seuillage par hystérésis (de sorte qu’un contour fort à un endroit soit tracé même là où il s’estompe entre deux points). Le résultat est un ensemble propre, fin et connecté de pixels de contour, du type que recherche tout algorithme classique fondé sur les contours.
Le paramètre threshold est un tuple à deux éléments (low, high). Pour EDGE_CANNY, la valeur high est le seuil de coupure au-dessus duquel un pixel est assurément un contour, et la valeur low est le seuil de coupure au-dessus duquel un pixel n’est un contour que s’il est connecté à un contour certain. Pour EDGE_SIMPLE, seule la valeur high compte ; c’est le seuil de coupure unique au-dessus duquel un pixel compte comme un contour. La valeur par défaut (100, 200) est un point de départ qu’il vaut la peine d’ajuster pour la scène spécifique.
img.gaussian(1) # pre-smooth
img.find_edges(image.EDGE_CANNY, threshold=(50, 100))
Le détecteur Canny est le meilleur choix pour presque toute application où les contours importent. Le plus rapide EDGE_SIMPLE mérite d’être retenu pour les cas où le coût de Canny pose problème et où le rejet de bruit de son hystérésis n’est pas réellement nécessaire.
5.14.5. Seuillage adaptatif sur le gaussien¶
Comme les filtres statistiques, gaussian() accepte le couple de mots-clés threshold=True / offset=N pour le seuillage adaptatif. Le comportement est le même qu’avec mean() : la statistique gaussienne en chaque position devient le seuil de coupure local, et le pixel source est comparé à la statistique plus le décalage pour produire un résultat binaire.
La variante gaussienne est généralement le choix le plus propre pour le seuillage adaptatif lorsque l’entrée est raisonnablement exempte de bruit. La moyenne pondérée donne un seuil de coupure plus lisse que celui produit par le filtre de moyenne, avec moins d’artefacts aux transitions d’éclairage nettes.