<strong>Algorithmes</strong> <strong>de</strong> <strong>la</strong> <strong>morphologie</strong> <strong>mathématique</strong> <strong>pour</strong> les architectures orientées fluxJaromír BRAMBOR<strong>pour</strong> chaque pixel tous les tests <strong>de</strong> dépassement <strong>de</strong> bord <strong>de</strong> l’image ou <strong>de</strong> parité <strong>de</strong> ligne/colonne. Leterme naïve n’a pas un sens péjoratif et désigne <strong>la</strong> métho<strong>de</strong> <strong>la</strong> plus simple possible qui peut égalementêtre <strong>la</strong> plus convenable dans <strong>la</strong> mesure où nous voulions un outil générique et rapi<strong>de</strong>ment utilisable etnous ne nous focalisions pas prioritairement sur les performances mais plutôt sur le fonctionnement.5.1.1.1 Skeleton algorithmique ngbAlgo <strong>de</strong> l’approche naïve au travail sur le voisinageNous commençons notre explication par <strong>la</strong> présentation du skeleton algorithmique dédié à <strong>la</strong> construction<strong>de</strong>s algorithmes concrets travail<strong>la</strong>nt sur le voisinage. Il se décompose en quatre phases. Dans <strong>la</strong> première,nous passons d’un array 2D à un stream <strong>de</strong>s in<strong>de</strong>x ; dans <strong>la</strong> <strong>de</strong>uxième, nous extrayons le voisinagelocal, dans <strong>la</strong> troisième nous appliquons le kernel travail<strong>la</strong>nt sur le voisinage qui désigne l’opérationmorphologique et dans <strong>la</strong> quatrième et <strong>de</strong>rnière phase, nous reconstituons l’array <strong>de</strong> sortie à partir dustream.Algorithme 5.1 : ngbAlgo, skeleton algorithmique <strong>de</strong> l’approche naïve <strong>pour</strong> le travail sur le voisinage1 ngbAlgo :: Streamize α → ExtrNgb α → NgbOp α → Ar ( I , I ) α → Ar ( I , I ) α2 ngbAlgo strm extr op ar = array (bounds ar)3 ( (zip ixs )4 ◦ (map op)5 ◦ (map (extr ar))6 $ ixs )7 where ixs = strm$arL’algorithme 5.1 présente, par <strong>la</strong> fonction ngbAlgo, <strong>la</strong> structure <strong>de</strong> ce skeleton. Il prend quatre argumentsdont le premier, strm qui est du type Streamize α, désigne <strong>la</strong> manière dont on parcourt l’image,autrement dit, il s’agit d’une fonction qui retourne un stream <strong>de</strong>s in<strong>de</strong>x dans un ordre choisi. Le <strong>de</strong>uxième,extr qui est du type ExtrNgb α, désigne <strong>la</strong> fonction d’extraction <strong>de</strong>s éléments du voisinage. Cet argumentest puissant car très général et nous expliquerons plus tard les éventualités <strong>de</strong> son utilisation. Letroisième argument, op qui est du type NgbOp α, désigne <strong>la</strong> fonction <strong>de</strong> l’opération locale sur le voisinageet correspond à une opération morphologique que nous voulons effectuer. Le quatrième paramètre,ar, désigne l’array d’entrée qui contient notre image à traiter.boundsar(Arrayd’entrée)Streamize ExtrNgb NgbOp ziparrayArray<strong>de</strong> sortieCréation <strong>de</strong> l’array <strong>de</strong> sortieFIG. 5.1 : Graphe <strong>de</strong> flux exprimant le fonctionnement du skeleton algorithmique ngbAlgoLe fonctionnement <strong>de</strong> ce skeleton est assez simple et nous le présentons sur <strong>la</strong> fig. 5.1 en tant quediagramme <strong>de</strong> flux. Tout d’abord (ligne 7), nous obtenons un stream <strong>de</strong>s in<strong>de</strong>x par l’application <strong>de</strong> <strong>la</strong>fonction strm sur l’array d’entrée ar. Vu que le sens <strong>de</strong> parcours n’est pas substantiel dans les traitementsdéfinis par ce skeleton, <strong>la</strong> seule obligation posée sur <strong>la</strong> fonction strm est qu’elle doit parcourir toutel’image, l’ordonnancement exact <strong>de</strong>s in<strong>de</strong>x dans le stream n’est pas important.Sur chaque élément <strong>de</strong> ce stream (ligne 6), nous appliquons sur <strong>la</strong> ligne 5 (en utilisant <strong>la</strong> fonctionmap) <strong>la</strong> fonction extr qui représente le kernel d’extraction du voisinage et qui retourne, <strong>pour</strong> un in<strong>de</strong>xdonné, une liste <strong>de</strong>s éléments qui constituent le voisinage d’un in<strong>de</strong>x donné dans l’array ar. Il faut préciserque dans <strong>la</strong> <strong>morphologie</strong> <strong>mathématique</strong>, <strong>la</strong> structure <strong>de</strong> cette liste est définie par l’élément structurant,100
Jaromír BRAMBOR5.1. ALGORITHMES ÉLÉMENTAIRES POUR LES GPPet elle peut contenir ainsi (ou pas) le pixel même, ses voisins mais également les pixels qui sont plus éloignés<strong>de</strong>s voisins les plus proches du pixel concerné. Malgré ce fait, nous parlons du voisinage local (ou<strong>de</strong> local neighborhood en ang<strong>la</strong>is). Et c’est, en effet, <strong>la</strong> fonction extr qui assure tout en ce qui concerne<strong>la</strong> notion du voisinage, le type <strong>de</strong> <strong>la</strong> grille, <strong>la</strong> manière dont on gère les effets <strong>de</strong> bord et <strong>la</strong> manière exacte<strong>de</strong> l’échantillonnage <strong>de</strong>s pixels dans l’image. Ainsi, nous obtenons un stream <strong>la</strong>rge dont les élémentssont les listes composées <strong>de</strong>s pixels formant le voisinage.Sur tous les éléments <strong>de</strong> ce stream <strong>la</strong>rge, nous appliquons, sur <strong>la</strong> ligne 4, <strong>la</strong> fonction map qui secharge d’exécuter le kernel <strong>de</strong> l’opération morphologique op. Il s’agit, en effet, d’un kernel <strong>de</strong> réduction,cf. 3.4.1.2, page 45, qui calcule une nouvelle valeur <strong>pour</strong> l’in<strong>de</strong>x donné à partir d’un ensemble <strong>de</strong>s voisins.Nous obtenons un stream <strong>de</strong>s résultats auquel nous ajoutons (ligne 3) l’information sur <strong>la</strong> position par <strong>la</strong>fonction zip avec le stream <strong>de</strong>s in<strong>de</strong>x ixs comme argument. Le résultat <strong>de</strong> cette opération est un stream<strong>de</strong>s tuples (in<strong>de</strong>x, valeur) à partir duquel nous reconstituons, sur <strong>la</strong> ligne 2, un array <strong>de</strong> sortie par <strong>la</strong>fonction standard array.Il faut préciser que nous avons obtenu un skeleton algorithmique qui est très général et dont nouspouvons dériver beaucoup <strong>de</strong> cas particuliers. Il décrit le principe <strong>de</strong> fonctionnement et n’exhibe pasexplicitement les détails secondaires. Ainsi, <strong>la</strong> gran<strong>de</strong> partie du travail lourd n’est pas exposée et resteà définir par l’utilisateur lors <strong>de</strong> <strong>la</strong> spécialisation <strong>de</strong> ce skeleton à travers <strong>la</strong> fonction d’extraction duvoisinage ExtrNgb α.5.1.1.2 <strong>Algorithmes</strong> concrets utilisant le skeleton algorithmique ngbAlgoUne fois <strong>la</strong> structure du mo<strong>de</strong> opérationnel <strong>de</strong> l’approche naïve <strong>de</strong> travail sur le voisinage présentée,nous allons procé<strong>de</strong>r à <strong>la</strong> construction <strong>de</strong>s algorithmes concrets et utilisables en pratique par <strong>la</strong> spécialisation<strong>de</strong> ce skeleton.Mais tout d’abord, il faut ajouter une précision concernant l’extraction du voisinage. L’extractiond’un pixel à partir d’un array 2D est simple. Pour pouvoir extraire les valeurs <strong>de</strong>s pixels voisins à ce<strong>de</strong>rnier, nous avons besoin <strong>de</strong> déterminer certains détails. Pour les applications travail<strong>la</strong>nt sur le voisinagelocal dans le domaine digitalisé 1 , il s’agit notamment :• du voisinage utilisé – 4, 6, 8 voisins ou autres, représentés par les in<strong>de</strong>x re<strong>la</strong>tifs,• du type <strong>de</strong> <strong>la</strong> grille – hexagonale, carrée ou spécifique (graphes <strong>de</strong> voisinage particuliers), représenté,en général, par <strong>la</strong> fonction qui met en correspondance les in<strong>de</strong>x re<strong>la</strong>tifs désignant les voisinsavec l’emp<strong>la</strong>cement exact <strong>de</strong>s voisins dans l’array d’entrée,• <strong>de</strong> <strong>la</strong> façon <strong>de</strong> gérer les effets <strong>de</strong> bord – valeur <strong>de</strong> bord constante, valeur du voisin le plus prochedans l’image, gestion particulière du voisinage aux bords, etc.C’est <strong>la</strong> fonction d’extraction du voisinage qui assure toutes ces activités. Elle nous retourne, <strong>pour</strong>chaque in<strong>de</strong>x concret qui localise une position à l’intérieur <strong>de</strong> l’array, une liste <strong>de</strong>s valeurs <strong>de</strong>s pixelsdésignées par l’élément structurant. Cette liste, qui est le seul argument d’entrée à l’opération morphologiquesur le voisinage, peut être perçue par certains algorithmes comme un stream où l’ordonnancementn’est pas important (e.g. di<strong>la</strong>tation morphologique), mais nous pouvons utiliser avec avantage <strong>la</strong> notion<strong>de</strong> l’ordre dans cette liste dans d’autres algorithmes (e.g. <strong>la</strong> transformation tout ou rien).Expliquons cette implémentation (définie par <strong>la</strong> fonction dilSQR) sur un exemple précis <strong>de</strong> <strong>la</strong> di<strong>la</strong>tationmorphologique sur <strong>la</strong> grille carrée par un élément structurant <strong>de</strong> 4 voisins. Nous allons utiliser<strong>la</strong> fonction d’extraction <strong>de</strong>s voisins extrNgbSQR qui est spécialisée <strong>pour</strong> <strong>la</strong> grille carrée. Le voisinageest défini par <strong>la</strong> liste <strong>de</strong>s dép<strong>la</strong>cements re<strong>la</strong>tifs <strong>pour</strong> un point et ses 4 voisins ngbSQR4. La fonction <strong>de</strong>traitement <strong>de</strong>s bords que nous avons choisie, cBor<strong>de</strong>r, représente le bord <strong>de</strong> l’image dont <strong>la</strong> valeur estconstante, c’est-à-dire que cette fonction nous retourne <strong>pour</strong> tous les in<strong>de</strong>x <strong>la</strong> valeur <strong>de</strong> son premier argumentbrdval. L’opération <strong>de</strong> di<strong>la</strong>tation morphologique est assurée par le kernel <strong>de</strong> réduction du stream<strong>de</strong>s voisins, ce kernel est exprimé par <strong>la</strong> fonction ngbDi<strong>la</strong>te. Le <strong>de</strong>rnier point à préciser est l’utilisation1Notons que ce principe est utilisé dans le champs plus <strong>la</strong>rge <strong>de</strong>s applications et ne se restreint pas seulement à <strong>la</strong> Morphologie<strong>mathématique</strong>101