5.15. Opérations morphologiques

Les opérations morphologiques travaillent sur des images binaires – les masques issus du seuillage et de la détection de contours. Chaque opération parcourt le même type de voisinage glissant que celui qu’utilisent les filtres de lissage, mais la question qu’elle pose à chaque position est de type oui/non : chaque pixel du voisinage est-il activé, y a-t-il un pixel du voisinage activé, à quoi ressemble le motif activé/désactivé ? Les réponses font croître les régions, les rétrécissent et redécoupent leurs frontières d’une manière qu’un filtre de moyennage ne peut pas.

La morphologie est ce qui s’intercale entre un masque binaire initial – la sortie du seuillage, de la détection de contours ou d’un autre classifieur – et le masque binaire propre que le reste du pipeline peut utiliser. Une sortie de seuil brute présente généralement des pixels de bruit isolés disséminés dans les zones de véritable premier plan, de petits trous percés dans des régions par ailleurs pleines, et des frontières dentelées là où le seuil a coupé près du bord d’un objet. La morphologie supprime ces défauts.

5.15.1. Les quatre opérations classiques

Deux opérations primitives, et deux compositions de celles-ci, constituent la boîte à outils morphologique :

dilate() fait croître chaque région de premier plan. La règle est : tout pixel ayant au moins un voisin de premier plan dans sa fenêtre (2 * size + 1) devient premier plan. L’effet visible est que les régions de premier plan grandissent de size pixels dans chaque direction, et que les trous à l’intérieur rétrécissent (ou disparaissent) d’autant.

erode() fait l’inverse. Tout pixel qui n’a pas chacun de ses voisins dans sa fenêtre en premier plan devient arrière-plan. Les régions de premier plan rétrécissent de size pixels dans chaque direction, les pixels de premier plan isolés (qui n’ont aucun voisin de premier plan) disparaissent entièrement, et les petites connexions entre des régions plus grandes sont coupées.

Une région d'entrée binaire dans le panneau le plus à gauche : un carré plein avec un trou d'un pixel en son milieu et trois pixels de bruit isolés autour. Quatre panneaux à droite montrent le résultat de l'application de dilate, erode, open et close à cette entrée. Dilate fait croître la région, remplit le trou et transforme chaque pixel de bruit en un bloc ; erode rétrécit la région, agrandit le trou et supprime le bruit ; open supprime le bruit tout en reproduisant exactement la région et son trou ; close remplit le trou tout en reproduisant exactement le contour de la région et les pixels de bruit.

Les quatre opérations morphologiques classiques appliquées à une région binaire bruitée. Erode rétrécit ; dilate fait croître ; open est erode puis dilate (supprime le bruit) ; close est dilate puis erode (remplit les trous).

open() est erode suivi de dilate. L’image érodée a vu chaque pixel de bruit isolé supprimé, mais elle a aussi été rétrécie de size pixels dans chaque direction. Faire suivre l’erode d’un dilate de même taille restitue les véritables régions de premier plan à peu près à leurs frontières d’origine tout en laissant le bruit disparu. La composition est ce qui fait de open l’opération standard de « suppression du bruit » en morphologie classique : les pixels de premier plan isolés disparaissent, les vraies régions reviennent intactes.

close() est l’image miroir – dilate suivi de erode. Le dilate remplit les petits trous à l’intérieur des régions de premier plan et connecte les régions séparées par de petits écarts ; l’erode rétrécit le résultat jusqu’à sa frontière extérieure d’origine tout en laissant l’intérieur comblé plein. close est l’opération standard de « comblement des petits écarts ».

binary_mask.open(1)       # remove single-pixel noise
binary_mask.close(2)      # fill small holes and gaps

Le paramètre size a la même signification que dans les filtres de luminosité : size=1 désigne un voisinage de 3 sur 3, size=2 un voisinage de 5 sur 5, et ainsi de suite. Des tailles plus grandes signifient un nettoyage plus agressif – et un coût par pixel plus élevé.

5.15.2. Chapeau haut-de-forme et chapeau noir

Deux compositions supplémentaires valent la peine d’être connues car elles extraient exactement les caractéristiques que open et close suppriment :

top_hat() renvoie la différence entre l’image originale et sa version ouverte – les pixels de premier plan que open aurait supprimés. C’est littéralement un masque des pixels de bruit, des petites régions de premier plan isolées, des fines structures de premier plan que l’opération d’ouverture n’a pu préserver. Utile pour extraire de petites caractéristiques de premier plan lorsque ce sont précisément ces caractéristiques qui intéressent l’application, plutôt que de les supprimer.

black_hat() renvoie la différence entre la version fermée de l’image et l’originale – les pixels d’arrière-plan que close aurait comblés. C’est un masque des petits trous à l’intérieur des régions de premier plan, des écarts étroits entre régions que l’opération de fermeture aurait comblés.

On y recourt moins couramment qu’aux quatre opérations de base, mais le schéma vaut la peine d’être retenu – lorsqu’une application a besoin d’extraire de petites ou fines caractéristiques que la passe de nettoyage standard supprime, le chapeau haut-de-forme et le chapeau noir sont le moyen naturel de les récupérer.

5.15.3. Mode seuil

Les quatre opérations morphologiques de base acceptent toutes un argument nommé entier threshold qui adoucit le test activé/désactivé à chaque position. Sans lui, les opérations se comportent comme l’indiquaient les descriptions ci-dessus : erode() exige que chaque voisin soit activé, dilate() en exige au moins un. Avec threshold défini, chaque opération tolère que ce nombre de voisins votent dans l’autre sens. Pour erode, threshold est le nombre de voisins d”arrière-plan qu’un pixel peut avoir tout en survivant : threshold=4 conserve tout pixel ayant au moins quatre de ses huit voisins activés (dans une fenêtre de 3 sur 3, le pixel central a huit voisins), de sorte qu’il érode moins agressivement. Pour dilate, threshold est le nombre de voisins de premier plan qu’un pixel d’arrière-plan doit avoir en plus avant de s’activer : threshold=2 exige au moins trois voisins de premier plan au lieu d’un, de sorte qu’il croît moins agressivement.

La forme avec seuil est utile pour régler l’agressivité d’une passe morphologique sans changer la taille de sa fenêtre, ce qui changerait aussi l”échelle des caractéristiques sur lesquelles elle agit. La plupart des applications s’en tiennent au comportement par défaut ; la forme avec seuil est là pour les cas où la valeur par défaut est juste un peu trop ou un peu trop peu.