<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 BRAMBOR4.4.4.3 Fonctions <strong>de</strong> parcours d’un arrayCommençons notre explication par l’introduction <strong>de</strong> <strong>la</strong> fonction concrète <strong>de</strong> parcours d’un array 1D.La fonction streamAr1D définit un skeleton algorithmique qui crée un stream <strong>de</strong>s in<strong>de</strong>x à partir d’unarray 1D. La valeur passée par son paramètre how détermine le sens du parcours que nous voulonsobtenir, <strong>la</strong> valeur ”FW” correspond au sens au-<strong>de</strong>vant, <strong>la</strong> valeur ”BW” correspond au sens en arrière. Lafig. 4.6 illustre ces <strong>de</strong>ux cas sur un vecteur <strong>de</strong> <strong>la</strong> taille 3.streamAr1D :: [Char] → Ar I α → [ I ]streamAr1D how ar| how == "FW" = [ (lo+ i ) | i ← [0 .. size−1]]| how == "BW"= [ (hi−i) | i ← [0 .. size−1]]where(lo ,hi ) = bounds $ ar ; size = rangeSize(lo,hi)1,1 1,2 1,3 (1,3) (1,2) (1,1)(a) sens au-<strong>de</strong>vant, streamAr1D avec "FW"1,1 1,2 1,3 (1,1) (1,2) (1,3)(b) sens en arrière, streamAr1D avec "BW"FIG. 4.6 : Choix du parcours <strong>de</strong> l’image <strong>pour</strong> un array <strong>de</strong> 1DTandis que <strong>pour</strong> les structures 1D le choix du sens <strong>de</strong> parcours est simple et nous utilisons soitle parcours au-<strong>de</strong>vant, soit le parcours en arrière, <strong>pour</strong> les structures 2D nous avons beaucoup plus <strong>de</strong>possibilités et nous décrivons celles qui sont utilisées le plus souvent. Il n’est pas difficile, en cas <strong>de</strong>besoin, d’en définir davantage qui seraient appropriées à un traitement particulier.Mais tout d’abord, nous définissons un type Streamize que nous allons utiliser <strong>pour</strong> désigner unefonction <strong>de</strong> parcours d’un array <strong>de</strong> 2D dans les signatures <strong>de</strong> types <strong>de</strong> nos algorithmes :type Streamize α = Ar ( I , I ) α → [ ( I , I ) ]Il s’agit <strong>de</strong>s fonctions qui prennent un array 2D comme argument et qui nous retournent un stream <strong>de</strong>sin<strong>de</strong>x.Nous définissons un skeleton <strong>pour</strong> <strong>la</strong> création d’un stream <strong>de</strong>s in<strong>de</strong>x à partir d’un array 2D par <strong>la</strong>fonction streamAr2D qui définit les parcours bien connus d’une image en sens vidéo et en sens antividéo.streamAr2D :: [Char] → Ar ( I , I ) α → [ ( I , I ) ]streamAr2D how ar| how == "FWFst" = [ ( flo + i ,slo+ j ) | j ←[0 .. smax], i←[0 .. fmax] ]| how == "FWSnd" = [ ( flo + i ,slo+ j ) | i←[0 .. fmax], j ←[0 .. smax]]| how == "BWFst" = [ ( fhi −i,shi−j) | j ←[0 .. smax], i←[0 .. fmax] ]| how == "BWSnd" = [ ( fhi −i,shi−j) | i←[0 .. fmax], j ←[0 .. smax]]where( ( flo ,slo) , ( fhi ,shi ) ) = bounds $ ar ;fmax = rangeSize(flo,fhi)−1smax = rangeSize(slo,shi)−1Le type du parcours exact est déterminé par <strong>la</strong> valeur du paramètre how <strong>de</strong> cette fonction et correspond<strong>pour</strong> les valeurs ”FWFst” / ”FWSnd” aux sens au-<strong>de</strong>vant par <strong>la</strong> première / <strong>de</strong>uxième coordonnée,et <strong>pour</strong> les valeurs et ”BWFst” / ”BWSnd” aux sens en arrière par <strong>la</strong> première / <strong>de</strong>uxième coordonnée,respectivement.Notons que l’application partielle <strong>de</strong> cette fonction avec <strong>la</strong> paramètre how concret, e.g. :(streamAr2D$"FWFst")72
Jaromír BRAMBOR4.4. PRIMITIVES DU CALCUL COMME SKELETONS ALGORITHMIQUESnous définit dans Haskell une nouvelle fonction qui est du type Streamize α et qui est ainsi directementutilisable dans les algorithmes comme une fonction du parcours d’un array.La figure 4.7 illustre le fonctionnement <strong>de</strong> ce skeleton <strong>pour</strong> un array 2D 3x3.1,1 1,2 1,31,1 1,2 1,32,1 2,22,3(3,3) (2,3) (1,3) (3,2) (2,2) (1,2) (3,1) (2,1) (1,1)2,1 2,22,3(3,3) (3,2) (3,1)(2,3) (2,2) (2,1)(1,3)(1,2)(1,1)3,1 3,23,33,1 3,23,3(a) sens au-<strong>de</strong>vant par <strong>la</strong> première coordonnée,streamAr2D avec ”FWFst”(b) sens au-<strong>de</strong>vant par <strong>la</strong> <strong>de</strong>uxième coordonnée,streamAr2D avec ”FWSnd”1,1 1,2 1,31,1 1,2 1,32,1 2,22,3(3,1) (3,2)(1,1) (1,2) (1,3) (2,3)(2,1) (2,2) (3,3)2,1 2,22,3(1,1) (1,2) (1,3) (2,1) (2,2) (2,3) (3,1) (3,2) (3,3)3,1 3,23,33,1 3,23,3(c) sens en arrière par <strong>la</strong> première coordonnée, streamAr2Davec ”BWFst”(d) sens en arrière par <strong>la</strong> <strong>de</strong>uxième coordonnée,streamAr2D avec ”BWSnd”FIG. 4.7 : Choix du parcours <strong>de</strong> l’image <strong>pour</strong> un array <strong>de</strong> 2D 3 × 34.4.5 Concept <strong>de</strong>s "superpixels"Dans certains <strong>de</strong> nos algorithmes, nous allons travailler avec un groupe <strong>de</strong> pixels et avec les pixelsvoisins <strong>de</strong> ce groupe, plutôt que <strong>de</strong> travailler avec un seul pixel et son voisinage. Il serait donc convenable<strong>de</strong> décrire à cette p<strong>la</strong>ce <strong>la</strong> manière dont on va travailler avec un tel groupe et <strong>de</strong> donner les bases formellesà ce travail.L’idée <strong>de</strong> travailler avec <strong>de</strong>s groupes <strong>de</strong> pixels et <strong>de</strong>s pixels voisins <strong>de</strong> ce groupe est propre à toutesles implémentations sur les architectures parallèles où on procè<strong>de</strong> à <strong>la</strong> division <strong>de</strong> l’image et on effectuele traitement <strong>de</strong> ces parties par <strong>la</strong> distribution sur différents processeurs. Cette idée est explorée parJin Yang qui utilise, q.v. page 57 <strong>de</strong> sa thèse Yan97 doctorale, les bords partagés (également appelés leshalos) qui sont ajoutés aux arrays parallèles ou aux graphes. Notons que ces bords partagés ont dans <strong>la</strong><strong>morphologie</strong> <strong>mathématique</strong> un sens plus <strong>la</strong>rge que celui du voisinage proche sur une grille donnée car ilsdoivent refléter le travail avec <strong>de</strong>s éléments structurants dans leur forme générale et souvent d’une tailleimportante, pas nécessairement celle qui définit le voisinage <strong>de</strong> taille 1.D’un point <strong>de</strong> vue formel, c’est le travail sur le voisinage qui nous empêche d’exprimer un tel groupe<strong>de</strong> pixels par un array découpé régulièrement sur les vecteurs paquetés ou sur les macro blocs car dans <strong>la</strong>perception <strong>de</strong>s arrays comme nous <strong>la</strong> décrivons par le formalisme fonctionnel, les voisins d’une donnéequi est du type α sont les données du même type. Par exemple, le voisinage d’un macro bloc concret estconstitué d’un ou plusieurs macro blocs voisins.Ceci ne correspond pas à <strong>la</strong> philosophie <strong>de</strong> travail que nous voulons employer <strong>pour</strong> les groupes <strong>de</strong>pixels dont le voisinage (proche ou dans le sens <strong>la</strong>rge) est constitué également <strong>de</strong>s pixels et non <strong>de</strong>sgroupes <strong>de</strong> pixels. Vu que l’utilisation <strong>de</strong> ces groupes <strong>de</strong> pixels dans les fonctions et <strong>la</strong> façon <strong>de</strong> travailleravec leurs pixels voisins sont semb<strong>la</strong>bles à celles que nous employons lors du travail à l’échelle <strong>de</strong>s pixelsnon-groupés, il nous semble approprié <strong>de</strong> désigner ces groupes comme <strong>de</strong>s superpixels, c’est-à-dire <strong>de</strong>spixels qui ont une notion é<strong>la</strong>rgie d’une entité <strong>de</strong> données qui peut contenir plus d’un seul pixel.Le concept <strong>de</strong>s superpixels que nous introduisons est pratique <strong>pour</strong> <strong>de</strong>ux raisons :• il est cohérent avec l’idée du sens du parcours implémentée par <strong>la</strong> fonction génératrice <strong>de</strong>s in<strong>de</strong>xet avec l’idée d’une fonction d’extraction <strong>de</strong>s pixels (ici <strong>de</strong> tout un groupe) à partir <strong>de</strong> l’image enutilisant un seul in<strong>de</strong>x, comme nous l’avons présenté dans <strong>la</strong> section 4.4.4, page 70.• les superpixels conservent le caractère <strong>de</strong>s pixels. Ainsi, nous n’avons pas besoin <strong>de</strong> percevoirles groupes <strong>de</strong> pixels très différemment (e.g. comme <strong>de</strong>s macro blocs), <strong>de</strong> définir un autre typequi serait spécifique aux groupes <strong>de</strong> pixels et qui nous aurait conduit à un travail très différent <strong>de</strong>73