Précédent   Forum des professionnels en informatique > Autres langages > Algorithmes > Contribuez
Contribuez Proposez vos articles, cours, tutoriels, FAQ, sources, etc.
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 23/04/2007, 20h21   #1
Rédacteur/Modérateur
 
Avatar de millie
 
Inscription : juin 2006
Messages : 6 929
Détails du profil
Informations personnelles :
Localisation : Luxembourg

Informations forums :
Inscription : juin 2006
Messages : 6 929
Points : 6 714
Points : 6 714
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 :
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 :
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 :
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 :
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 :
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 :
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 :
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 :
__________________
Je ne répondrai à aucune question technique en privé
millie est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/04/2007, 15h41   #2
Membre chevronné
 
Avatar de parp1
 
Inscription : mai 2005
Messages : 818
Détails du profil
Informations personnelles :
Âge : 28
Localisation : France, Calvados (Basse Normandie)

Informations forums :
Inscription : mai 2005
Messages : 818
Points : 692
Points : 692
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...
__________________
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

You are safe in Parp1City .... (AC DC)
Ensemble luttons contre le chômage de parp1City!



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...
parp1 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/04/2007, 16h44   #3
Rédacteur/Modérateur
 
Avatar de millie
 
Inscription : juin 2006
Messages : 6 929
Détails du profil
Informations personnelles :
Localisation : Luxembourg

Informations forums :
Inscription : juin 2006
Messages : 6 929
Points : 6 714
Points : 6 714
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);

Citation:
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.
__________________
Je ne répondrai à aucune question technique en privé
millie est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/04/2007, 16h57   #4
Rédacteur/Modérateur
 
Avatar de millie
 
Inscription : juin 2006
Messages : 6 929
Détails du profil
Informations personnelles :
Localisation : Luxembourg

Informations forums :
Inscription : juin 2006
Messages : 6 929
Points : 6 714
Points : 6 714
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.
__________________
Je ne répondrai à aucune question technique en privé
millie est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/04/2007, 17h13   #5
Membre chevronné
 
Avatar de parp1
 
Inscription : mai 2005
Messages : 818
Détails du profil
Informations personnelles :
Âge : 28
Localisation : France, Calvados (Basse Normandie)

Informations forums :
Inscription : mai 2005
Messages : 818
Points : 692
Points : 692
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é...
__________________
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

You are safe in Parp1City .... (AC DC)
Ensemble luttons contre le chômage de parp1City!



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...
parp1 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/04/2007, 17h45   #6
Rédacteur/Modérateur
 
Avatar de millie
 
Inscription : juin 2006
Messages : 6 929
Détails du profil
Informations personnelles :
Localisation : Luxembourg

Informations forums :
Inscription : juin 2006
Messages : 6 929
Points : 6 714
Points : 6 714
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)


__________________
Je ne répondrai à aucune question technique en privé
millie est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/07/2007, 12h06   #7
Invité régulier
 
Inscription : avril 2007
Messages : 15
Détails du profil
Informations forums :
Inscription : avril 2007
Messages : 15
Points : 9
Points : 9
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
boksikos est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/07/2007, 09h58   #8
Rédacteur/Modérateur
 
Avatar de millie
 
Inscription : juin 2006
Messages : 6 929
Détails du profil
Informations personnelles :
Localisation : Luxembourg

Informations forums :
Inscription : juin 2006
Messages : 6 929
Points : 6 714
Points : 6 714
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
.....
__________________
Je ne répondrai à aucune question technique en privé
millie est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/07/2007, 14h34   #9
Invité régulier
 
Inscription : avril 2007
Messages : 15
Détails du profil
Informations forums :
Inscription : avril 2007
Messages : 15
Points : 9
Points : 9
j étais effectivement à coté de la plaque !

merci beaucoup pour ton eclaircissement!
boksikos est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/07/2007, 15h59   #10
Invité régulier
 
Inscription : avril 2007
Messages : 15
Détails du profil
Informations forums :
Inscription : avril 2007
Messages : 15
Points : 9
Points : 9
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
boksikos est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/07/2007, 16h25   #11
Rédacteur/Modérateur
 
Avatar de millie
 
Inscription : juin 2006
Messages : 6 929
Détails du profil
Informations personnelles :
Localisation : Luxembourg

Informations forums :
Inscription : juin 2006
Messages : 6 929
Points : 6 714
Points : 6 714
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.

Citation:
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
__________________
Je ne répondrai à aucune question technique en privé
millie est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/07/2007, 22h49   #12
Responsable Algorithmes
 
Avatar de PRomu@ld
 
Homme Romuald Perrot
Attaché Temporaire d'Enseignement et de Recherche (ATER)
Inscription : avril 2005
Messages : 4 144
Détails du profil
Informations personnelles :
Nom : Homme Romuald Perrot
Âge : 26
Localisation : France

Informations professionnelles :
Activité : Attaché Temporaire d'Enseignement et de Recherche (ATER)
Secteur : Enseignement

Informations forums :
Inscription : avril 2005
Messages : 4 144
Points : 5 301
Points : 5 301
Citation:
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.
__________________
http://rperrot.developpez.com
http://phos-graphein.fr

Vous désirez contribuer à la rubrique algorithmique, n'hésitez pas à me contacter.
PRomu@ld est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/09/2008, 17h24   #13
Candidat au titre de Membre du Club
 
Développeur informatique
Inscription : février 2008
Messages : 17
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 : 17
Points : 10
Points : 10
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.
rdtech est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/09/2008, 23h34   #14
Membre actif
 
Inscription : mars 2008
Messages : 209
Détails du profil
Informations forums :
Inscription : mars 2008
Messages : 209
Points : 193
Points : 193
une question à Millie : pour une image couleur tu fait le même traitement pour chaque canal ?
benDelphic est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/09/2008, 14h53   #15
Rédacteur/Modérateur
 
Avatar de millie
 
Inscription : juin 2006
Messages : 6 929
Détails du profil
Informations personnelles :
Localisation : Luxembourg

Informations forums :
Inscription : juin 2006
Messages : 6 929
Points : 6 714
Points : 6 714
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.
__________________
Je ne répondrai à aucune question technique en privé
millie est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/09/2008, 14h59   #16
Rédacteur/Modérateur
 
Avatar de millie
 
Inscription : juin 2006
Messages : 6 929
Détails du profil
Informations personnelles :
Localisation : Luxembourg

Informations forums :
Inscription : juin 2006
Messages : 6 929
Points : 6 714
Points : 6 714
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 :
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 :
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.
__________________
Je ne répondrai à aucune question technique en privé
millie est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/09/2008, 10h40   #17
Rédacteur/Modérateur
 
Avatar de pseudocode
 
Homme Xavier Philippeau
Architecte système
Inscription : décembre 2006
Messages : 9 424
Détails du profil
Informations personnelles :
Nom : Homme Xavier Philippeau
Âge : 39
Localisation : France, Hérault (Languedoc Roussillon)

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

Informations forums :
Inscription : décembre 2006
Messages : 9 424
Points : 14 133
Points : 14 133
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 ()

Citation:
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.
pseudocode est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/03/2010, 16h02   #18
Invité de passage
 
okay_91 okay_91
Inscription : mars 2010
Messages : 3
Détails du profil
Informations personnelles :
Nom : okay_91 okay_91

Informations forums :
Inscription : mars 2010
Messages : 3
Points : 4
Points : 4
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.
okay_91 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/03/2010, 17h55   #19
Rédacteur/Modérateur
 
Avatar de millie
 
Inscription : juin 2006
Messages : 6 929
Détails du profil
Informations personnelles :
Localisation : Luxembourg

Informations forums :
Inscription : juin 2006
Messages : 6 929
Points : 6 714
Points : 6 714
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
__________________
Je ne répondrai à aucune question technique en privé
millie est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/03/2010, 09h43   #20
Modérateur
 
Avatar de ToTo13
 
Homme Guillaume
Chercheur en informatique
Inscription : janvier 2006
Messages : 4 404
Détails du profil
Informations personnelles :
Nom : Homme Guillaume
Âge : 33
Localisation : France

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

Informations forums :
Inscription : janvier 2006
Messages : 4 404
Points : 5 267
Points : 5 267
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 :
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 correcteur orthographique pour FiReFox), mettre les ACCENTS et les BALISES => ECRIRE clairement et en Français tu DOIS.
- Le coté obscur je sens dans le MP => Tous tes MP 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.
ToTo13 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 10h35.


 
 
 
 
Partenaires

Hébergement Web