IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Contribuez Discussion :

[Image] Opérateurs d'érosion et de dilatation


Sujet :

Contribuez

  1. #1
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Par défaut [Image] Opérateurs d'érosion et de dilatation
    Bonjour,

    Etant donné que la documentation sur les opérateurs morphologiques d'érosion et de dilatation sur des images en couleurs est assez difficile à trouver, je vais vous expliquer le principe.

    La diffusion et l'érosion s'effectue suivant un noyau, en général, quand on voit ces opérateurs, on travaille avec des images binaires :

    Par exemple, l'érosion :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Avant          Apres
    0 0 0 0 0      0 0 0 0 0
    0 1 1 0 0      0 0 0 0 0
    0 1 1 1 0      0 0 1 0 0
    0 0 1 0 0      0 0 0 0 0
    La dilatation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Avant          Apres
    0 0 0 0 0      0 1 1 0 0
    0 1 1 0 0      1 1 1 1 0
    0 1 1 1 0      1 1 1 1 1
    0 0 1 0 0      0 1 1 1 0
    A chaque pixel, on pose un "noyau" dessus composé de 0 et de 1. Typiquement, le noyau classique est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    0 1 0
    1 1 1
    0 1 0
    Pour la dilatation,
    On centre le noyau de tel façon à ce qu'il recouvre le pixel de destination (x,y) à changer, si l'un des pixels de l'image d'origine dispose d'un 1 là où il y a un 1 dans le noyau, alors l'image de destination (x,y) vaudra 1.

    On fait l'inverse pour l'érosion.

    On suppose que l'on dispose d'un objet Kernel qui dispose des opérations suivantes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    getWidth() : donne la largeur
    getHeight() : donne la hauteur
    getLeftPadding() : donne le nombre de pixel à gauche à partir du centre (ici, c'est 1)
    getRightPadding() : idem mais pour la droite
    getBottomPadding() : idem mais pour en bas
    getTopPadding() : idem mais pour en haut
    getOriginX() : donne le centre horizontal du noyau en commencant à 0 (donc ici 1)
    getOriginY() : donne le centre vertical
    L'algorithme naif pour une image binaire va s'écrire comme ça :
    Pour la dilatation par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    fonction dilatation(Image in, Kernel k)
     /*on ne traite pas les bords*/
     Image out de taille : largeur -(k.getRightPadding() + k.getLeftPadding()
                                 hauteur - (k.getTopPadding() + k.getBottomPadding())
     
     Pour chaque canaux de out et de in faire :
       Pour j = k.getTopPadding() à  hauteur - k.getBottomPadding()-1
        Pour  i = leftpadding à largeur - k.getRightPadding()-1  
        {
         float value = 0; 
         Pour kj = 0 à k.getHeight()-1 
           Pour ki =0 à k.getWidth()-1
           {        
               out.setPixel(  i - leftpadding, j - toppadding, 0);
     
               /*si l'un des pixels du noyau à 1 correspond à un pixel à 1 de l'image, la futur valeur sera égale à 1*/
               Si kernel(ki, kj) * image.getPixel(i + ki - kernel.getXOrigin(), j+ kj - kernel.getYOrigin()) == 1
               Alors value = 1;
                out.setPixel(i - leftpadding, j - toppadding,
                                 value);
            }
     
          }

    Cette méthode fonctionne bien pour des images binaires, mais pas pour des images qui dispose de plusieurs niveaux de gris, la méthode général est la suivante :

    Pour l'érosion :
    1. Pour chaque pixel de la source, placer le noyau sur l'image centré sur le pixel (i,j)
    2. Pour chaque pixel du noyau (positionné), soustraire la valeur du noyau * le pixel décalé au pixel central (i,j)
    3. Déterminer le minimum de toutes ces valeurs
    4. Ajouter le minimum au pixel central (i,j)

    Algorithme avec une notation C++ :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
      out.resize(largeur - (rightpadding + leftpadding), hauteur - (toppadding+bottompadding));
     
        for(int j = toppadding; j< hauteur - bottompadding; j++)
        {
          for(int i = leftpadding; i< largeur - rightpadding; i++)
          {
            for(int kj = 0; kj< khauteur; kj++)
              for(int ki = 0; ki< klargeur; ki++)
              {
                buffer[klargeur * kj + ki] =  image.getPixel(i,j, canal) - kernel(ki, kj) * image.getPixel(i + ki - kernel.getXOrigin(), j+ kj - kernel.getYOrigin(), canal);
              }
     
                float mini = getMinimum(buffer);
     
                out.setPixel(i - leftpadding, j - toppadding,
                                 canal, mini + image.getPixel(i,j, canal));
     
          }
    Pour la dilatation :
    1. Pour chaque pixel de la source (i,j), placer le noyau sur l'image centré sur le pixel
    2. Pour chaque pixel du noyau (positionné), soustraire la valeur du pixel central (i,j) au produit noyau * le pixel décalé
    3. Déterminer le maximum de toutes ces valeurs
    4. Ajouter le maximum au pixel central (i,j)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     out.resize(largeur - (rightpadding + leftpadding), hauteur - (toppadding+bottompadding));
     
        for(int j = toppadding; j< hauteur - bottompadding; j++)
        {
          for(int i = leftpadding; i< largeur - rightpadding; i++)
          {
            for(int kj = 0; kj< khauteur; kj++)
              for(int ki = 0; ki< klargeur; ki++)
              {
                buffer[klargeur * kj + ki] =  -image.getPixel(i,j, canal) + kernel(ki, kj) * image.getPixel(i + ki - kernel.getXOrigin(), j+ kj - kernel.getYOrigin(), canal);
              }
     
                float maxi = getMaximum(buffer);
     
                out.setPixel(i - leftpadding, j - toppadding,
                                 canal, maxi + image.getPixel(i,j, canal));
     
          }

    Classiquement, on utilise le noyau :
    Voici un exemple :

    Source :


    Erosion :


    Dilatation :

  2. #2
    Membre émérite
    Avatar de parp1
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    829
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Calvados (Basse Normandie)

    Informations forums :
    Inscription : Mai 2005
    Messages : 829
    Par défaut
    Je ne suis pas d'accord avec toi, et je me trompe peux être mais quand tu dis que pour la dilatation, tu prends la valeur max du voisinage que tu ajoutes au pixel central.... Pour moi le dilaté d'un voisinage, c'est remplacé le pixel central par le max du voisinage...

    Dans mon tutoriel j'explique l'erosion et la dilatation en suivant mes cours de Maths morphos...


    Peut être que j'ai tort. Mais ca n'empeche que tu as fais du bon boulot pour cette algo.

    Ca mérite peut être d'autre avis...
    [SIZE="2"]Dis moi qui tu suis, je te dirais qui je Hais!
    Heureux est l'étudiant, qui comme la rivière suit son cours sans sortir de son lit

    Mon premier Tutoriel


    A 80% des cas je résouts mon problème en rédigeant une nouvelle discussion, du coup je ne poste que 20% de mes problèmes...

  3. #3
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Par défaut
    Le max du voisinage, pas tout à fait, c'est le max des valeurs du genre :

    -image.getPixel(i,j, canal) + kernel(ki, kj) * image.getPixel(i + ki - kernel.getXOrigin(), j+ kj - kernel.getYOrigin(), canal);

    2. Pour chaque pixel du noyau (positionné), soustraire la valeur du noyau * le pixel décalé au pixel central (i,j)
    3. Déterminer le minimum de toutes ces valeurs
    4. Ajouter le minimum au pixel central (i,j)
    J'ai parlé donc du minimum (ou du maximum) de : chaque pixel du noyai auquel on soustrait la valeur du noyau * le pixel décalé (pas simple à expliquer avec des mots, plus simple ce serait avec un schéma)

    Dans le cas d'image binaire, c'est équivalent à ta méthode.

  4. #4
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Par défaut
    Bon, a priori, il y aurait plusieurs stratégies :

    J'avais choisi celle là :
    http://developer.apple.com/documenta...section_2.html

    Ici : http://www.tsi.enst.fr/~bloch/ANIM/morpho.pdf

    Ce qu'ils appelent l'érosion fonctionelle, c'était ta méthode. Mais ils ont également la dilatation par fonction, ce qui serait plus proche de ma méthode.

  5. #5
    Membre émérite
    Avatar de parp1
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    829
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Calvados (Basse Normandie)

    Informations forums :
    Inscription : Mai 2005
    Messages : 829
    Par défaut
    OK Je suis donc d'accord avec toi! dslé pour le dérangement mais je préféré me renseigner, Comme ca je sais qu'il existe plus facon d'erodé...
    [SIZE="2"]Dis moi qui tu suis, je te dirais qui je Hais!
    Heureux est l'étudiant, qui comme la rivière suit son cours sans sortir de son lit

    Mon premier Tutoriel


    A 80% des cas je résouts mon problème en rédigeant une nouvelle discussion, du coup je ne poste que 20% de mes problèmes...

  6. #6
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Par défaut
    Je viens d'implémenter la méthode avec juste le minimum (il faut un peu modifier l'algorithme) :

    La première image, c'est avec l'algo du haut, la deuxième image c'est juste avec le minimum. J'ai une préférence pour la première qui a tendance à rendre moins flou (enfin, ce n'est que visuel ma remarque)



  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 15
    Par défaut
    Bonjour,


    ton algo a l air pas mal pour les images en plusieurs niveau de gris, mais j ai beau le relire, et je conçois que c est un peu dur à expliquer avec des mots, mais je suis pas sur de l avoir compris!

    donc dis moi si je me trompe ( ce qui est fortement possible!)

    si je prends une matrice du genre

    2 6 7 9
    9 8 12 4
    6 7 3 7
    2 7 11 1

    admettons que je veuille appliquer l érosion au pixel de valeur 12 avec le masque
    0 1 0
    1 1 1
    0 1 0

    mon pixel aura pour valeur le minimum parmi :

    12 - 7 ; 12 - 4 ; 12 - 3; 12 - 8 ? ou pas du tout lol

    et pour la dilatation, on prend le maximum?

    merci de m éclaircir un peu

  8. #8
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Par défaut
    Citation Envoyé par boksikos
    Bonjour,


    ton algo a l air pas mal pour les images en plusieurs niveau de gris, mais j ai beau le relire, et je conçois que c est un peu dur à expliquer avec des mots, mais je suis pas sur de l avoir compris!

    donc dis moi si je me trompe ( ce qui est fortement possible!)

    si je prends une matrice du genre

    2 6 7 9
    9 8 12 4
    6 7 3 7
    2 7 11 1

    admettons que je veuille appliquer l érosion au pixel de valeur 12 avec le masque
    0 1 0
    1 1 1
    0 1 0

    mon pixel aura pour valeur le minimum parmi :

    12 - 7 ; 12 - 4 ; 12 - 3; 12 - 8 ? ou pas du tout lol

    et pour la dilatation, on prend le maximum?

    merci de m éclaircir un peu
    En fait, il va falloir calculer ça à chaque position : buffer[klargeur * kj + ki] = image.getPixel(i,j, canal) - kernel(ki, kj) * image.getPixel(i + ki - kernel.getXOrigin(), j+ kj - kernel.getYOrigin(), canal);

    Ca donne un buffer avec ça comme valeur :
    12 - 0 * 6 = 12
    12 - 1 * 7 = 5
    12 - 0 * 9 = 12
    12 - 1 * 8 = 4
    12 - 1 * 12 = 0
    12 - 1 - 4 = 8
    12 - 0 * 7 = 12
    12 - 1 * 3 = 9
    12 - 0 * 7 = 12

    Tu prends le minimum : 0
    Tu l'ajoutes au pixel central : 12 + 0 = 12
    Pas de chance, c'est le pixel le plus important, donc il n'y a pas de différence sur celui là

    Pour la dilatation, il faut prendre le maximum des valeurs suivantes : buffer[klargeur * kj + ki] = -image.getPixel(i,j, canal) + kernel(ki, kj) * image.getPixel(i + ki - kernel.getXOrigin(), j+ kj - kernel.getYOrigin(), canal);

    C'est à dire :
    -12 + 0 * 6
    - 12 + 1* 7 = -5
    .....

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 15
    Par défaut
    j étais effectivement à coté de la plaque !

    merci beaucoup pour ton eclaircissement!

  10. #10
    Membre averti
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 15
    Par défaut
    finalement j ai besoin d encore un ou 2 petits eclaircissements supplémentaires

    en fait, donc quand on effectue l érosion, on va forcément se retrouver avec des pixels négatifs, si j ai bien compris, car si dans l exemple précédent, si la valeur du pixel était 2 et pas 12, le minimum choisi aurait été : 2- 1*8=-6 et donc la valeur de ce pixel apres érosion aurait été 2-6=-4. bon ça à la limite vu que je suis novice en "traitement d'image", je trouvais ça bizarre mais pourquoi pas apres tout!

    de plus, à la base, je voulais faire une ouverture ( dilatation de l'érodé) dans le but d 'éliminer des "artéfacts", mais j'ai l impression qu en appliquant ton algo, ça ressemblerait plus à une fermeture, ça aurait plutot tendance à "combler les fossés", en comparaison avec l autre algo où on prend le voisin minmum pour l érosion et le maximum pour la dilatation et qui a l air de mieux fonctionner.

    désolé si j ai mal compris ou alos que les erreurs viennent de moi

  11. #11
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Par défaut
    Citation Envoyé par boksikos
    finalement j ai besoin d encore un ou 2 petits eclaircissements supplémentaires

    en fait, donc quand on effectue l érosion, on va forcément se retrouver avec des pixels négatifs, si j ai bien compris, car si dans l exemple précédent, si la valeur du pixel était 2 et pas 12, le minimum choisi aurait été : 2- 1*8=-6 et donc la valeur de ce pixel apres érosion aurait été 2-6=-4. bon ça à la limite vu que je suis novice en "traitement d'image", je trouvais ça bizarre mais pourquoi pas apres tout!
    Si c'est négatif, ça devient noir à la fin (donc 0)
    Ca arrive fréquemment d'avoir dans des filtres qui dépassent les bornes, il faut juste tout remettre dans 0-255 au moment de l'enregistrement.

    de plus, à la base, je voulais faire une ouverture ( dilatation de l'érodé) dans le but d 'éliminer des "artéfacts", mais j'ai l impression qu en appliquant ton algo, ça ressemblerait plus à une fermeture, ça aurait plutot tendance à "combler les fossés", en comparaison avec l autre algo où on prend le voisin minmum pour l érosion et le maximum pour la dilatation et qui a l air de mieux fonctionner.
    Bah, fais comme tu le sens

  12. #12
    Expert confirmé
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Par défaut
    de plus, à la base, je voulais faire une ouverture ( dilatation de l'érodé) dans le but d 'éliminer des "artéfacts", mais j'ai l impression qu en appliquant ton algo, ça ressemblerait plus à une fermeture, ça aurait plutot tendance à "combler les fossés", en comparaison avec l autre algo où on prend le voisin minmum pour l érosion et le maximum pour la dilatation et qui a l air de mieux fonctionner.
    Si tu veux éliminer les artefacts, il faut bien une ouverture, si tu utilises le même élément structurant, ça élimine les zones qui sont plus petites que cet élément structurant.

  13. #13
    Membre éclairé
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2008
    Messages
    289
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2008
    Messages : 289
    Par défaut erosion et dilatation
    bonjour,
    merci pour ces discussions qui éclairent bien ma lanterne.
    Avez vous l'expérience de la meilleure méthode à utiliser pour traiter les bords de l'image? Ou les avantages et les inconvénients des plus classiques?

    Merci.

  14. #14
    Membre expérimenté
    Inscrit en
    Mars 2008
    Messages
    209
    Détails du profil
    Informations forums :
    Inscription : Mars 2008
    Messages : 209
    Par défaut
    une question à Millie : pour une image couleur tu fait le même traitement pour chaque canal ?

  15. #15
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Par défaut
    Citation Envoyé par benDelphic Voir le message
    une question à Millie : pour une image couleur tu fait le même traitement pour chaque canal ?
    Oui, c'est ce que j'ai fait pour mes images d'exemple.

  16. #16
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Par défaut
    Citation Envoyé par rdtech Voir le message
    bonjour,
    merci pour ces discussions qui éclairent bien ma lanterne.
    Avez vous l'expérience de la meilleure méthode à utiliser pour traiter les bords de l'image? Ou les avantages et les inconvénients des plus classiques?

    Merci.
    Ce qui est souvent fait, c'est d'étendre le bord de l'image avec les mêmes valeurs que sur les bords afin d'appliquer le filtre. Il faut augmenter la taille de l'image afin que l'application du filtre à cette nouvelle image donne la taille de l'image initiale (ce qui semble logique).


    (code du genre :

    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    public void extend(Image out, Image in, int toppadding, int leftpadding,
    			int rightpadding, int bottompadding) {
    		if (out.getNumComponents() != in.getNumComponents())
    			throw new IllegalArgumentException("BorderExtenderCopy::extend");
     
    		if (toppadding < 0 || leftpadding < 0 || rightpadding < 0
    				|| bottompadding < 0)
    			throw new IllegalArgumentException("BorderExtenderCopy::extend");
     
    		out.resize(in.getWidth() + leftpadding + rightpadding, in.getHeight()
    				+ bottompadding + toppadding);
     
    		for (int canal = 0; canal < out.getNumComponents(); canal++) {
    			/* coin haut gauche */
    			for (int j = 0; j < toppadding; j++)
    				for (int i = 0; i < leftpadding; i++)
    					out.setPixel(i, j, canal, in.getPixel(0, 0, canal));
     
    			/* ligne supérieur */
    			for (int j = 0; j < toppadding; j++)
    				for (int i = leftpadding; i < (in.getWidth() + leftpadding); i++)
    					out.setPixel(i, j, canal, in.getPixel(i - leftpadding, 0,
    							canal));
     
    			/* coin supérieur droite */
    			for (int j = 0; j < toppadding; j++)
    				for (int i = (in.getWidth() + leftpadding); i < out.getWidth(); i++)
    					out.setPixel(i, j, canal, in.getPixel(in.getWidth() - 1, 0,
    							canal));
     
    			/* ligne gauche */
    			for (int j = toppadding; j < (in.getHeight() + toppadding); j++)
    				for (int i = 0; i < leftpadding; i++)
    					out.setPixel(i, j, canal, in.getPixel(0, j - toppadding,
    							canal));
     
    			/* ligne droite */
    			for (int j = toppadding; j < (in.getHeight() + toppadding); j++)
    				for (int i = (in.getWidth() + leftpadding); i < out.getWidth(); i++)
    					out.setPixel(i, j, canal, in.getPixel(in.getWidth() - 1, j
    							- toppadding, canal));
     
    			/* coin bas gauche */
    			for (int j = (in.getHeight() + toppadding); j < out.getHeight(); j++)
    				for (int i = 0; i < leftpadding; i++)
    					out.setPixel(i, j, canal, in.getPixel(0,
    							in.getHeight() - 1, canal));
     
    			/* coin bas droit */
    			for (int j = (in.getHeight() + toppadding); j < out.getHeight(); j++)
    				for (int i = (in.getWidth() + leftpadding); i < out.getWidth(); i++)
    					out.setPixel(i, j, canal, in.getPixel(in.getWidth() - 1, in
    							.getHeight() - 1, canal));
     
    			/* ligne bas */
    			for (int j = (in.getHeight() + toppadding); j < out.getHeight(); j++)
    				for (int i = leftpadding; i < (in.getWidth() + leftpadding); i++)
    					out.setPixel(i, j, canal, in.getPixel(i - leftpadding, in
    							.getHeight() - 1, canal));
     
    			/* centre */
    			for (int j = toppadding; j < (in.getHeight() + toppadding); j++)
    				for (int i = leftpadding; i < (in.getWidth() + leftpadding); i++)
    					out.setPixel(i, j, canal, in.getPixel(i - leftpadding, j
    							- toppadding, canal));
     
    		}
    	}

    Une autre méthode va être de combler les bords par du noir, ce qui donne souvent des petites imperfections sur les bords.


    L'avantage de ces techniques et qu'il n'est pas nécessaire de modifier le code existant.


    Ce qui est parfois fait également, c'est d'ajouter du code dans le filtre pour ne pas prendre en compte les pixels qui dépassent.
    Ce que fait par exemple pseudocode dans sa contribution : http://www.developpez.net/forums/d41...ture-features/ avec les lignes :
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    for(int y0=0;y0<height;y0++) {
    			for(int x0=0;x0<width;x0++) {
    				// pour chaque pixel
    				int v0 = (int)(MSIZE*this.image.getValue(x0,y0)/256.0);
     
    				// on cherche le voisin
    				int x1 = x0 + dx;
    				if (x1<0 || x1>=width) continue; //on continue
    				int y1 = y0 + dy;
    				if (y1<0 || y1>=height) continue;

    Mais sur certains types de filtre (erosion, convolution etc.), il est facilement possible d'éviter cette astuce qui est plutôt utilisé dans les filtres difficile à écrire ou dans les filtres avec des itérations.

  17. #17
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Par défaut
    Citation Envoyé par millie Voir le message
    Ce qui est parfois fait également, c'est d'ajouter du code dans le filtre pour ne pas prendre en compte les pixels qui dépassent.
    Ce que fait par exemple pseudocode dans sa contribution
    En réalité j'ai fait cela car
    1. Le code du BorderExtender aurait compléxifié la contrib
    2. J'ai eu la flemme d'ecrire le BorderExtender ()

    L'avantage de ces techniques et qu'il n'est pas nécessaire de modifier le code existant.
    On peut aussi déplacer les tests de "dépassement" dans le BorderExtender. Cela évite de dupliquer l'image en mémoire, au détriment de la consommation CPU.
    ALGORITHME (n.m.): Méthode complexe de résolution d'un problème simple.

  18. #18
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 3
    Par défaut
    Bonjour à tous.

    Je souhaite faire une érosion pour une image en couleur, or je n'arrive pas a avoir un résultat correcte.

    Comment dois-je faire??

    Si ma matrice est :
    [0 1 0
    1 1 1
    0 1 0 ]

    Et que les voisins du pixel que je traite ont pour valeurs rouge-vert-bleu suivante (pixel traité en gras) :
    [126 12 15 ; 174 187 30 ; 255 0 0
    126 112 115 ; 108 112 115 ; 13 18 125
    100 100 100 ; 150 150 90 ; 26 155 15
    ]

    il faut que je fasse le traitement composante par composante comme ça :

    108-0*(126) = 0
    108-1*(174) = 108-174= -66
    108-0*(255) = 0
    108-1*(126) = 108-126=-18
    108-1*(108) = 108-108=0
    108-1*(13) = 108-13 = 95
    108-0*(100) = 0
    108-1*(150) = 108-150 = -42
    108-0*(26) = 0

    ... idem pour le vert (avec 112-.....) et le bleu (avec 115-........)

    et ensuite je prend le min (-66 dans le cas du rouge) que j'aditionne à 108 ce qui fait 42 que je stock dans la coposante rouge du pixel traité?? (idem pour vert et bleu).

    C'est comme cela qu'il faut faire ???

    Merci par avance.

  19. #19
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Par défaut
    Citation Envoyé par okay_91 Voir le message
    Bonjour à tous.

    Je souhaite faire une érosion pour une image en couleur, or je n'arrive pas a avoir un résultat correcte.

    Comment dois-je faire??

    Si ma matrice est :
    [0 1 0
    1 1 1
    0 1 0 ]

    Et que les voisins du pixel que je traite ont pour valeurs rouge-vert-bleu suivante (pixel traité en gras) :
    [126 12 15 ; 174 187 30 ; 255 0 0
    126 112 115 ; 108 112 115 ; 13 18 125
    100 100 100 ; 150 150 90 ; 26 155 15
    ]

    il faut que je fasse le traitement composante par composante comme ça :

    108-0*(126) = 0
    108-1*(174) = 108-174= -66
    108-0*(255) = 0
    108-1*(126) = 108-126=-18
    108-1*(108) = 108-108=0
    108-1*(13) = 108-13 = 95
    108-0*(100) = 0
    108-1*(150) = 108-150 = -42
    108-0*(26) = 0

    ... idem pour le vert (avec 112-.....) et le bleu (avec 115-........)

    et ensuite je prend le min (-66 dans le cas du rouge) que j'aditionne à 108 ce qui fait 42 que je stock dans la coposante rouge du pixel traité?? (idem pour vert et bleu).

    C'est comme cela qu'il faut faire ???

    Merci par avance.
    Oui

  20. #20
    Modérateur
    Avatar de ToTo13
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Janvier 2006
    Messages
    5 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 793
    Par défaut
    Bonjour,

    Citation Envoyé par millie Voir le message
    Bon, a priori, il y aurait plusieurs stratégies :
    Euh... non désolé, il n'y en a qu'une seule.

    Si on regarde le cours de Jean Serra page 16 (un des fondateurs de la morphomath) ou le cours que tu cites d'Isabelle Bloch (dont la réputation n'est plus à faire en traitement d'image) page 101 équation 6.9, tu vois que c'est le sup qu'il faut prendre.



    Citation Envoyé par millie Voir le message
    Ce qu'ils appelent l'érosion fonctionelle, c'était ta méthode. Mais ils ont également la dilatation par fonction, ce qui serait plus proche de ma méthode.
    Dans le cours d'Isabelle Bloch, c'est la même chose ;-)



    Voici un code java pour des images binaires ou en niveaux de gris. Pour un gain de rapidité, les coordonnées des pixels non nuls de l'élément structurant ont été placées dans un tableau à une dimension.
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
     
    public Image Filter(Image Original)
    	{
    	int i, j, l ;
    	int largeur = Original.getWidth() ;
    	int hauteur = Original.getHeight() ;
    	int order = ES.getOrder() ;
    	int length = ES.getList().size() ;
    	Image image = new Image(largeur, hauteur, Original.getType()) ;
    	Coordinates coord = null ;
    	Coordinates[] se = ES.getSE() ;
     
    	for (i=0 ; i < hauteur ; i++)
    		for (j=0 ; j < largeur ; j++) image.Pixel(i, j, 0) ;
     
    	switch ( Original.getType() )
    		{
    		case Image.TYPE_BYTE_BINARY :
    			for (i=0 ; i < hauteur ; i++)
    				for (j=0 ; j < largeur ; j++)
    					if ( Original.Pixel(i,j) == 1 )
    						for (l=0 ; l < length ; l++)
    							{
    							coord = se[l] ;
    							if ( i+coord.Y >= 0 && i+coord.Y < hauteur && j+coord.X >= 0 && j+coord.X < largeur ) image.Pixel(i+coord.Y, j+coord.X, 1) ;
    							}
    			break ;
    		case Image.TYPE_USHORT_GRAY :
    		case Image.TYPE_BYTE_GRAY :
    			for (i=0 ; i < hauteur ; i++) // On traite les bords.
    				for (j=0 ; j < largeur ; j++)
    					for (l=0 ; l < length ; l++)
    						{
    						coord = se[l] ;
    						if ( i+coord.Y >= 0 && i+coord.Y < hauteur && j+coord.X >= 0 && j+coord.X < largeur )
    							if ( image.Pixel(i+coord.Y,j+coord.X) < Original.Pixel(i,j) ) image.Pixel(i+coord.Y, j+coord.X, Original.Pixel(i,j)) ;
    						}
    			break ;
    		default : throw new Error("Default.") ;
    		}
     
    	return image ;
    	}
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

Discussions similaires

  1. Dilatation et érosion de courbes
    Par sovitec dans le forum Traitement d'images
    Réponses: 16
    Dernier message: 27/05/2015, 15h13
  2. Meilleur algorithme d'érosion/dilatation
    Par Gwindor dans le forum Traitement d'images
    Réponses: 19
    Dernier message: 17/06/2011, 01h28
  3. Dilatation d'une image.
    Par sisiniya dans le forum Images
    Réponses: 4
    Dernier message: 20/06/2009, 00h27
  4. Traitement images erosion dilatation
    Par mahdouch1 dans le forum Débuter
    Réponses: 1
    Dernier message: 20/03/2009, 15h41
  5. [Image] Opérateur de Nagao
    Par millie dans le forum Contribuez
    Réponses: 3
    Dernier message: 09/04/2008, 11h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo