Précédent   Forum du club des développeurs et IT Pro > 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
 
Outils de la discussion
Publicité
'
Vieux 16/12/2009, 11h32   #1
ToTo13
Modérateur
 
Avatar de ToTo13
 
Homme Guillaume
Ingénieur de Recherche
Inscription : janvier 2006
Messages : 4 807
Détails du profil
Informations personnelles :
Nom : Homme Guillaume
Âge : 34
Localisation : Etats-Unis

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

Informations forums :
Inscription : janvier 2006
Messages : 4 807
Points : 7 052
Points : 7 052
Par défaut [Image/Java] Etiquetage des Composantes Connexes (FIFO, Itérative, Récursive, Union-Find)

Bonjour,

voilà trois classes permettant d'étiqueter des composantes connexes à l'aide de plusieurs méthodes :
- Itérative => Classique et rapide.
- Récursive => Le plus rapide, mais avec un TRES gros risque de StackOverFlow, donc a éviter.
- Fifo => La version récursive implémentée avec une file.
- Union-Find (la version de PseudoCode dans ma plate-forme).

J'ai fait des tests et la méthode la plus rapide est FiFo dans la TRES grande majorité des cas. Il faut éviter la récursive pour les problèmes de débordement, elle n'est là que pour le coté pédagogique.
De même la version Union-Find est très belle, mais très lente : environ 5 à 8 fois plus lente que la FiFo (calculé de manière empirique).



Voici un petit exemple d'utilisation :
Code java :
1
2
3
4
5
6
 
EightConnex = true ; // On travaille en 8-connexité.
ConnectedComponentLabeling ccl = new FifoCcl() ;
ccl.Label(image, 0, EightConnex, null) ; // On calcule (étiquette) les composantes connexes.  On ne prend pas en compte la couleur noire car c'est le fond. Mettre -1 pour caractériser TOUTE la texture.
int[][] Carte = ccl.Labels() ; // la carte contenant la numérotation de chaque composante.
int[] Sizes = ccl.Sizes() ; // Le tableau contenant les tailles de composantes.





Tout d'abord, voici l'interface permettant de s'abstraire un peu de la méthode :
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
69
70
71
72
73
74
75
76
 
import java.awt.image.BufferedImage;
import java.util.List;
 
import utils.times.Chronometer;
 
/**
 * <p>Description : Interface qui permet de savoir si une classe peut calculer le nombre de composantes connexes
 * presentes dans une image. Il est conseille d'utiliser FifoCcl ou IterativeCcl.<br>
 * UnionFindCcl est tres lent et RecursiveCcl genere un StackOverFlow si une composante est trop grande.</p>
 * <p>Package(s) required: imageTiTi, utils.</p>
 * <p>Copyright: Copyright (c) 2007-2011.</p>
 * <p>Laboratories/Teams: CMM (Mines-ParisTech/ENSMP), I&M (ex LXAO) LSIS.</p>
 * <p>Updates:<br>
 * 11 Avril 2010 => Modification des methodes Separate* afin de pouvoir eventuellement passer une image a decouper.<br>
 * 19 Janvier 2010, 1.1 => Ajout des methodes Label(*) avec pour types d'entree : DV, int[][] et int[][][].<br>
 * 06 Aout 2009 => Creation.</p>
 * 
 * @author Guillaume THIBAULT
 * @version 1.1
 */
 
public interface ConnectedComponentLabeling
{
 
 
/** Calcule le nombre de composantes connexes dans l'image.
 * @param Original L'image dans laquelle on doit compter les composantes connexes.
 * @param Fond Couleur du fond, donc a ne pas prendre en compte.
 * @param HuitConnexe Booleen qui permet de savoir si le calcul se fait en quatre ou huit connexites.
 * @param Chrono Le chronometre pour mesurer la duree.
 * @return Le nombre de composantes connexes de l'image.*/
public int Label(BufferedImage Original, int Fond, boolean HuitConnexe, Chronometer Chrono) ;
 
/** Calcule le nombre de composantes connexes dans l'image.
 * @param Original Le tableau dans lequel on doit compter les composantes connexes.
 * @param Fond Couleur du fond, donc a ne pas prendre en compte.
 * @param HuitConnexe Booleen qui permet de savoir si le calcul se fait en quatre ou huit connexites.
 * @param Chrono Le chronometre pour mesurer la duree.
 * @return Le nombre de composantes connexes de l'image.*/
public int Label(int[][] Original, int Fond, boolean HuitConnexe, Chronometer Chrono) ;
 
/** Calcule le nombre de composantes connexes dans l'image.
 * @param Original Le tableau dans lequel on doit compter les composantes connexes.
 * @param Fond Couleur du fond, donc a ne pas prendre en compte.
 * @param TwentySixConnex Booleen qui permet de savoir si le calcul se fait en six ou vingt six connexites.
 * @param Chrono Le chronometre pour mesurer la duree.
 * @return Le nombre de composantes connexes de l'image.*/
public int Label(int[][][] Original, int Fond, boolean TwentySixConnex, Chronometer Chrono) ;
 
/** Calcule le nombre de composantes connexes dans l'image mais ne compte que les composantes ayant une surface superieure a
 *  Threshold.
 * @param Threshold Surface minimum que doit avoir une composante connexe afin d'etre comptabilisee. 
 * @return Le nombre de composantes connexes de l'image.*/
public int NumberOfConnectedComponent(int Threshold) ;
 
 
/** Methode qui renvoit le nombre de composantes connexes denombrees lors du dernier appel de la methode Label.
 * @return Le nombre de composantes.*/
public int NumberOfConnectedComponent() ;
 
 
/** Method which return array of labels.
 * @return Array.*/
public int[][] Labels() ;
 
/** Method which return 3D array of labels.
 * @return Array 3D.*/
public int[][][] Labels3D() ;
 
 
/** Method which return sizes of connected components.
 * @return Array.*/
public int[] Sizes() ;
 
}
__________________
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 actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/12/2009, 11h34   #2
ToTo13
Modérateur
 
Avatar de ToTo13
 
Homme Guillaume
Ingénieur de Recherche
Inscription : janvier 2006
Messages : 4 807
Détails du profil
Informations personnelles :
Nom : Homme Guillaume
Âge : 34
Localisation : Etats-Unis

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

Informations forums :
Inscription : janvier 2006
Messages : 4 807
Points : 7 052
Points : 7 052
Par défaut FIFO

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.util.List;
import java.util.Vector;
 
import utils.arrays.ArraysOperations;
import utils.times.Chronometer;
 
/**
 * <p>Description : Cette classe propose des methodes qui permettent de calculer le nombre de trous et de composantes connexes dans une image.
 *  Cette classe utilise un algorithme iteratif contenant une file.</p>
 * <p>Package(s) required: imageTiTi, utils.</p>
 * <p>Copyright: Copyright (c) 2007-2011.</p>
 * <p>Laboratories/Teams: CMM (Mines-ParisTech/ENSMP), I&M (ex LXAO) LSIS.</p>
 * <p>Updates:<br>
 * 19 Janvier 2010 => Ajout des methodes Label(*) avec pour types d'entree : DV, int[][] et int[][][].<br>
 * 12 Octobre 2009 => Creation.</p>
 * 
 * @author Guillaume THIBAULT
 * @version 1.0
 */
 
public class FifoCcl implements ConnectedComponentLabeling
{
 
/** La dernier image sur laquelle on a compte le nombre de composantes.*/
protected BufferedImage source = null ;
 
/** Le tableau contenant la numerotation des composantes.*/
protected int[][] Labels = null ;
 
/** Le tableau contenant la numerotation des composantes.*/
protected int[][][] Labels3D = null ;
 
/** Tableau contenant la taille des composantes connexes.*/
protected int[] Sizes = null ;
 
/** Nombre de composantes connexes denombrees lors du dernier appel de la methode Label.*/
protected int Counter = -1 ;
 
/** La file contenant les pixels a traiter.*/
protected List<Coordinates> fifo = new Vector<Coordinates>() ;
 
 
/** Classe permettant de stocker les coordonnees des pixels/voxels. Classe minimale, moins lourde qu'un point.
 * @author FiReTiTi*/
private class Coordinates
	{
	int X, Y, Z ;
 
	public Coordinates(int X, int Y)
		{
		this.X = X ;
		this.Y = Y ;
		}
 
	public Coordinates(int X, int Y, int Z)
		{
		this.X = X ;
		this.Y = Y ;
		this.Z = Z ;
		}
	}
 
 
 
 
 
 
 
/** Calcule le nombre de composantes connexes dans l'image.
 * @param Original L'image dans laquelle on doit compter les composantes connexes.
 * @param BackGround Couleur du fond, donc a ne pas prendre en compte.
 * @param EightConnex Booleen qui permet de savoir si le calcul se fait en quatre ou huit connexites.
 * @param Chrono Le chronometre pour mesurer la duree.
 * @return Le nombre de composantes connexes de l'image.*/
public int Label(BufferedImage Original, int BackGround, boolean EightConnex, Chronometer Chrono)
	{
	int x, y, X, Y, Color, marker = 0 ;
	int height = Original.getHeight() ;
	int width = Original.getWidth() ;
	WritableRaster wr = Original.getRaster() ;
 
	if ( Chrono != null )
		{
		System.out.print("Number of connected components computation with fifo algorithm: ") ;
		marker = Chrono.setMarker() ;
		}
 
	if ( Labels == null || height != Labels.length || width != Labels[0].length ) // Pour éviter de re-allouer chaque fois.
		{
		Labels = null ;
		Labels = new int[height][width] ;
		}
 
	ArraysOperations.SetConstant(Labels, -1) ; // On initialise
 
	source = null ;
	source = Original ;
	fifo.clear() ;
 
	Counter = 0 ;
	for (y=0 ; y < height ; y++)
		for (x=0 ; x < width ; x++)
			if ( Labels[y][x] == -1 ) // Si on a jamais touché à cette case.
				if ( wr.getSample(x, y, 0) == BackGround ) Labels[y][x] = 0 ; // Si on est sur le fond, on met zéro.
				else
					{
					Counter++ ;
					Mark(x, y, Counter) ;
					Color = wr.getSample(x, y, 0) ;
					X = x ;
					Y = y ;
 
					do	{
						x = fifo.get(0).X ;
						y = fifo.get(0).Y ;
						fifo.remove(0) ;
 
						if ( y-1 >= 0 && Labels[y-1][x] == -1 && wr.getSample(x, y-1, 0) == Color ) Mark(x, y-1, Counter) ;
						if ( y+1 < height && Labels[y+1][x] == -1 && wr.getSample(x, y+1, 0) == Color ) Mark(x, y+1, Counter) ;
						if ( x-1 >= 0 && Labels[y][x-1] == -1 && wr.getSample(x-1, y, 0) == Color ) Mark(x-1, y, Counter) ;
						if ( x+1 < width && Labels[y][x+1] == -1 && wr.getSample(x+1, y, 0) == Color ) Mark(x+1, y, Counter) ;
 
						if ( EightConnex )
							{
							if ( y-1 >= 0 && x-1 >= 0 && Labels[y-1][x-1] == -1 && wr.getSample(x-1, y-1, 0) == Color ) Mark(x-1, y-1, Counter) ;
							if ( y-1 >= 0 && x+1 < width && Labels[y-1][x+1] == -1 && wr.getSample(x+1, y-1, 0) == Color ) Mark(x+1, y-1, Counter) ;
							if ( y+1 < height && x-1 >= 0 && Labels[y+1][x-1] == -1 && wr.getSample(x-1, y+1, 0) == Color ) Mark(x-1, y+1, Counter) ;
							if ( y+1 < height && x+1 < width && Labels[y+1][x+1] == -1 && wr.getSample(x+1, y+1, 0) == Color ) Mark(x+1, y+1, Counter) ;
							}
 
						}	while ( !fifo.isEmpty() ) ;
 
					x = X ;
					y = Y ;
					}
 
	Sizes = null ; // On remplit le tableau Sizes.
	Sizes = new int[Counter+1] ;
	for (y=0 ; y < height ; y++)
		for (x=0 ; x < width ; x++)
			if ( Labels[y][x] > 0 )
				Sizes[Labels[y][x]]++ ;
 
	wr = null ;
 
	if ( Chrono != null )
		{
		System.out.println(Chrono.getTimeSinceMarker(marker)) ;
		Chrono.FreeMarker(marker) ;
		}
 
	return Counter ;
	}
 
 
 
 
 
/** Calcule le nombre de composantes connexes dans l'image.
 * @param Original Le tableau 3D dans laquel on doit compter les composantes connexes.
 * @param BackGround Couleur du fond, donc a ne pas prendre en compte.
 * @param EightConnex Booleen qui permet de savoir si le calcul se fait en quatre ou huit connexites.
 * @param Chrono Le chronometre pour mesurer la duree.
 * @return Le nombre de composantes connexes de l'image.*/
public int Label(int[][] Original, int BackGround, boolean EightConnex, Chronometer Chrono)
	{
	int x, y,  X, Y, Color, marker = 0 ;
	int height = Original.length ;
	int width = Original[0].length ;
	this.source = null ;
 
	if ( Chrono != null )
		{
		System.out.print("Number of 3D connected components computation with fifo algorithm: ") ;
		marker = Chrono.setMarker() ;
		}
 
	if ( Labels == null || height != Labels.length || width != Labels[0].length ) // Pour éviter de re-allouer.
		{
		Labels = null ;
		Labels = new int[height][width] ;
		}
 
	fifo.clear() ;
	ArraysOperations.SetConstant(Labels, -1) ;
 
	Counter = 0 ;
	for (y=0 ; y < height ; y++)
		for (x=0 ; x < width ; x++)
			if ( Labels[y][x] == -1 ) // Si on a jamais touché à cette case.
				if ( Original[y][x] == BackGround ) Labels[y][x] = 0 ; // Si on est sur le fond, on met zéro.
				else
					{
					Counter++ ;
					Mark(x, y, Counter) ;
					Color = Original[y][x] ;
					X = x ;
					Y = y ;
 
					do	{
						x = fifo.get(0).X ;
						y = fifo.get(0).Y ;
						fifo.remove(0) ;
 
						if ( y-1 >= 0 && Labels[y-1][x] == -1 && Original[y-1][x] == Color ) Mark(x, y-1, Counter) ;
						if ( y+1 < height && Labels[y+1][x] == -1 && Original[y+1][x] == Color ) Mark(x, y+1, Counter) ;
						if ( x-1 >= 0 && Labels[y][x-1] == -1 && Original[y][x-1] == Color ) Mark(x-1, y, Counter) ;	
						if ( x+1 < width && Labels[y][x+1] == -1 && Original[y][x+1] == Color ) Mark(x+1, y, Counter) ;
 
						if ( EightConnex )
								{
								if ( y-1 >= 0 && x-1 >= 0 && Labels[y-1][x-1] == -1 && Original[y-1][x-1] == Color ) Mark(x-1, y-1, Counter) ;
								if ( y-1 >= 0 && x+1 < width && Labels[y-1][x+1] == -1 && Original[y-1][x+1] == Color ) Mark(x+1, y-1, Counter) ;
								if ( y+1 < height && x-1 >= 0 && Labels[y+1][x-1] == -1 && Original[y+1][x-1] == Color ) Mark(x-1, y+1, Counter) ;
								if ( y+1 < height && x+1 < width && Labels[y+1][x+1] == -1 && Original[y+1][x+1] == Color ) Mark(x+1, y+1, Counter) ;
								}
 
						}	while ( !fifo.isEmpty() ) ;
 
					x = X ;
					y = Y ;
					}
 
	Sizes = null ; // On remplit le tableau Sizes.
	Sizes = new int[Counter+1] ;
	for (y=0 ; y < height ; y++)
		for (x=0 ; x < width ; x++)
			if ( Labels[y][x] > 0 )
				Sizes[Labels[y][x]]++ ;
 
	if ( Chrono != null )
		{
		System.out.println(Chrono.getTimeSinceMarker(marker)) ;
		Chrono.FreeMarker(marker) ;
		}
 
	return Counter ;
	}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/* --------------------------------------------------------------- 3D --------------------------------------------------------------- */
/** Calcule le nombre de composantes connexes dans l'image.
 * @param Original Le tableau 3D dans laquel on doit compter les composantes connexes.
 * @param BackGround Couleur du fond, donc a ne pas prendre en compte.
 * @param TwentySixConnex Booleen qui permet de savoir si le calcul se fait en six ou vingt six connexites.
 * @param Chrono Le chronometre pour mesurer la duree.
 * @return Le nombre de composantes connexes de l'image.*/
public int Label(int[][][] Original, int BackGround, boolean TwentySixConnex, Chronometer Chrono)
	{
	int x, y, z,  X, Y, Z, Color, marker = 0 ;
	int depth = Original.length ;
	int height = Original[0].length ;
	int width = Original[0][0].length ;
	this.source = null ;
 
	if ( Chrono != null )
		{
		System.out.print("Number of 3D connected components computation with fifo algorithm: ") ;
		marker = Chrono.setMarker() ;
		}
 
	if ( Labels3D == null || depth != Labels3D.length || height != Labels3D[0].length || width != Labels3D[0][0].length ) // Pour éviter de re-allouer.
		{
		Labels3D = null ;
		Labels3D = new int[depth][height][width] ;
		}
 
	fifo.clear() ;
	ArraysOperations.SetConstant(Labels3D, -1) ;
 
	Counter = 0 ;
	for (z=0 ; z < depth ; z++)
		for (y=0 ; y < height ; y++)
			for (x=0 ; x < width ; x++)
				if ( Labels3D[z][y][x] == -1 ) // Si on a jamais touché à cette case.
					if ( Original[z][y][x] == BackGround ) Labels3D[z][y][x] = 0 ; // Si on est sur le fond, on met zéro.
					else
						{
						Counter++ ;
						Mark(x, y, z, Counter) ;
						Color = Original[z][y][x] ;
						X = x ;
						Y = y ;
						Z = z ;
 
						do	{
							x = fifo.get(0).X ;
							y = fifo.get(0).Y ;
							z = fifo.get(0).Z ;
							fifo.remove(0) ;
 
							if ( z-1 >= 0 && Labels3D[z-1][y][x] == -1 && Original[z-1][y][x] == Color ) Mark(x, y, z-1, Counter) ;
							if ( z+1 < depth && Labels3D[z+1][y][x] == -1 && Original[z+1][y][x] == Color ) Mark(x, y, z+1, Counter) ;
							if ( y-1 >= 0 && Labels3D[z][y-1][x] == -1 && Original[z][y-1][x] == Color ) Mark(x, y-1, z, Counter) ;
							if ( y+1 < height && Labels3D[z][y+1][x] == -1 && Original[z][y+1][x] == Color ) Mark(x, y+1, z, Counter) ;
							if ( x-1 >= 0 && Labels3D[z][y][x-1] == -1 && Original[z][y][x-1] == Color ) Mark(x-1, y, z, Counter) ;
							if ( x+1 < width && Labels3D[z][y][x+1] == -1 && Original[z][y][x+1] == Color ) Mark(x+1, y, z, Counter) ;
 
							if ( TwentySixConnex )
								{
								if ( y-1 >= 0 && x-1 >= 0 && Labels3D[z][y-1][x-1] == -1 && Original[z][y-1][x-1] == Color ) Mark(x-1, y-1, z, Counter) ;
								if ( y-1 >= 0 && x+1 < width && Labels3D[z][y-1][x+1] == -1 && Original[z][y-1][x+1] == Color ) Mark(x+1, y-1, z, Counter) ;
								if ( y+1 < height && x-1 >= 0 && Labels3D[z][y+1][x-1] == -1 && Original[z][y+1][x-1] == Color ) Mark(x-1, y+1, z, Counter) ;
								if ( y+1 < height && x+1 < width && Labels3D[z][y+1][x+1] == -1 && Original[z][y+1][x+1] == Color ) Mark(x+1, y+1, z, Counter) ;
 
								if ( z-1 >= 0 && y-1 >= 0 && x-1 >= 0 && Labels3D[z-1][y-1][x-1] == -1 && Original[z-1][y-1][x-1] == Color )
									Mark(x-1, y-1, z-1, Counter) ;
								if ( z-1 >= 0 && y-1 >= 0 && x+1 < width && Labels3D[z-1][y-1][x+1] == -1 && Original[z-1][y-1][x+1] == Color )
									Mark(x+1, y-1, z-1, Counter) ;
								if ( z-1 >= 0 && y+1 < height && x-1 >= 0 && Labels3D[z-1][y+1][x-1] == -1 && Original[z-1][y+1][x-1] == Color )
									Mark(x-1, y+1, z-1, Counter) ;
								if ( z-1 >= 0 && y+1 < height && x+1 < width && Labels3D[z-1][y+1][x+1] == -1 && Original[z-1][y+1][x+1] == Color )
									Mark(x+1, y+1, z-1, Counter) ;
 
								if ( z+1 < depth && y-1 >= 0 && x-1 >= 0 && Labels3D[z+1][y-1][x-1] == -1 && Original[z+1][y-1][x-1] == Color )
									Mark(x-1, y-1, z+1, Counter) ;
								if ( z+1 < depth && y-1 >= 0 && x+1 < width && Labels3D[z+1][y-1][x+1] == -1 && Original[z+1][y-1][x+1] == Color )
									Mark(x+1, y-1, z+1, Counter) ;
								if ( z+1 < depth && y+1 < height && x-1 >= 0 && Labels3D[z+1][y+1][x-1] == -1 && Original[z+1][y+1][x-1] == Color )
									Mark(x-1, y+1, z+1, Counter) ;
								if ( z+1 < depth && y+1 < height && x+1 < width && Labels3D[z+1][y+1][x+1] == -1 && Original[z+1][y+1][x+1] == Color )
									Mark(x+1, y+1, z+1, Counter) ;
								}
 
							}	while ( !fifo.isEmpty() ) ;
 
						x = X ;
						y = Y ;
						z = Z ;
						}
 
	Sizes = null ; // On remplit le tableau Sizes.
	Sizes = new int[Counter+1] ;
	for (z=0 ; z < depth ; z++)
		for (y=0 ; y < height ; y++)
			for (x=0 ; x < width ; x++)
				if ( Labels3D[z][y][x] > 0 )
					Sizes[Labels3D[z][y][x]]++ ;
 
	if ( Chrono != null )
		{
		System.out.println(Chrono.getTimeSinceMarker(marker)) ;
		Chrono.FreeMarker(marker) ;
		}
 
	return Counter ;
	}
 
 
 
 
 
 
 
 
 
/* ------------------------------------------------ Marqueurs & Getters ------------------------------------------------ */
/** Petite methode permettant d'ajouter un point dans la liste et de mettre la valeur count dans le tableau Labels.
 * @param x Coordonnee en X.
 * @param y Coordonnee en Y.
 * @param count Le numero de la composante connexe.*/
private void Mark(int x, int y, int count)
	{
	fifo.add(new Coordinates(x, y)) ;
	Labels[y][x] = count ;
	}
 
 
/** Petite methode permettant d'ajouter un point dans la liste et de mettre la valeur count dans le tableau Labels.
 * @param x Coordonnee en X.
 * @param y Coordonnee en Y.
 * @param z Coordonnee en Z.
 * @param count Le numero de la composante connexe.*/
private void Mark(int x, int y, int z, int count)
	{
	fifo.add(new Coordinates(x, y, z)) ;
	Labels3D[z][y][x] = count ;
	}
 
 
 
 
 
/** Calcule le nombre de composantes connexes dans l'image, mais ne compte que les composantes
 *  ayant une surface superieure a Threshold.
 * @param Threshold Surface minimum que doit avoir une composante connexe afin d'etre comptabilisee. 
 * @return Le nombre de composantes connexes de l'image.*/
public int NumberOfConnectedComponent(int Threshold)
	{
	if ( Labels == null ) throw new NullPointerException("Execution of Label method required before this one.") ;
 
	int nbccf = 0 ;
	for (int i=1 ; i <= Counter ; i++)
		if ( Sizes[i] >= Threshold ) nbccf++ ;
 
	return nbccf ;
	}
 
 
/** Methode qui renvoit le nombre de composantes connexes denombrees lors du dernier appel de la methode Label.
 * @return Le nombre de composantes.*/
public int NumberOfConnectedComponent()
	{
	return Counter ;
	}
 
 
 
 
 
 
 
 
/* ----------------------------------------------------- Les getters ----------------------------------------------------- */
/** Method which return sizes of connected components.
 * @return Array.*/
public int[] Sizes()
	{
	return Sizes;
	}
 
 
/** Method which return array of labels.
 * @return Array.*/
public int[][] Labels()
	{
	return Labels ;
	}
 
 
/** Method which return array of labels.
 * @return Array.*/
public int[][][] Labels3D()
	{
	return Labels3D ;
	}
 
 
}
__________________
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 actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/12/2009, 11h36   #3
ToTo13
Modérateur
 
Avatar de ToTo13
 
Homme Guillaume
Ingénieur de Recherche
Inscription : janvier 2006
Messages : 4 807
Détails du profil
Informations personnelles :
Nom : Homme Guillaume
Âge : 34
Localisation : Etats-Unis

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

Informations forums :
Inscription : janvier 2006
Messages : 4 807
Points : 7 052
Points : 7 052
Par défaut Récursive

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.util.List;
import java.util.Vector;
 
import utils.arrays.ArraysOperations;
import utils.times.Chronometer;
 
/**
 * <p>Description : Cette classe propose des methodes qui permettent de calculer le nombre de trous et de composantes connexes
 *  dans une image. ATTENTION : cette classe utilise un algorithme recursif pour le calcul => Forts risques de StackOverFlow.</p>
 * <p>Package(s) required: imageTiTi, utils.</p>
 * <p>Copyright: Copyright (c) 2007-2011.</p>
 * <p>Laboratories/Teams: CMM (Mines-ParisTech/ENSMP), I&M (ex LXAO) LSIS.</p>
 * <p>Updates:<br>
 * 6 Aout 2009 => Creation.</p>
 * 
 * @author Guillaume THIBAULT
 * @version 1.0
 */
 
public class RecursiveCcl implements ConnectedComponentLabeling
{
 
/** La dernier image sur laquelle on a compte le nombre de composantes.*/
protected BufferedImage source = null ;
 
/** Le tableau contenant la numerotation des composantes.*/
protected int[][] Labels = null ;
 
/** Tableau contenant la taille des composantes connexes.*/
protected int[] Sizes = null ;
 
/** Nombre de composantes connexes denombrees lors du dernier appel de la methode Label.*/
protected int Counter = -1 ;
 
 
 
 
/** Calcule le nombre de composantes connexes dans l'image.
 * @param Original L'image dans laquelle on doit compter les composantes connexes.
 * @param BackGround Couleur du fond, donc a ne pas prendre en compte.
 * @param EightConnex Booleen qui permet de savoir si le calcul se fait en quatre ou huit connexites.
 * @param Chrono Le chronometre pour mesurer la duree.
 * @return Le nombre de composantes connexes de l'image.*/
public int Label(BufferedImage Original, int BackGround, boolean EightConnex, Chronometer Chrono)
	{
	int x, y, marker = 0 ;
	int height = Original.getHeight() ;
	int width = Original.getWidth() ;
	Labels = null ;
	Labels = new int[height][width] ;
	WritableRaster wr = Original.getRaster() ;
 
	if ( Chrono != null )
		{
		System.out.print("Number of connected components computation with recursive algorithm: ") ;
		marker = Chrono.setMarker() ;
		}
 
	for (y=0 ; y < height ; y++) // On initialise
		for (x=0 ; x < width ; x++)
			Labels[y][x] = -1 ;
 
	Counter = 0 ;
	for (y=0 ; y < height ; y++)
		for (x=0 ; x < width ; x++)
			if ( Labels[y][x] == -1 ) // Si on a jamais touché à cette case.
				if ( wr.getSample(x, y, 0) == BackGround ) Labels[y][x] = 0 ; // Si on est sur le fond, on met zéro.
				else Germ(Original, x, y, wr.getSample(x, y, 0), BackGround, ++Counter, EightConnex) ;
 
	Sizes = null ; // On remplit le tableau Sizes.
	Sizes = new int[Counter+1] ;
	for (y=0 ; y < height ; y++)
		for (x=0 ; x < width ; x++)
			if ( Labels[y][x] > 0 )
				Sizes[Labels[y][x]]++ ;
 
	if ( Chrono != null )
		{
		System.out.println(Chrono.getTimeSinceMarker(marker)) ;
		Chrono.FreeMarker(marker) ;
		}
 
	return Counter ;
	}
 
 
/** Calcule le nombre de composantes connexes dans l'image.
 * @param Original Le tableau dans lequel on doit compter les composantes connexes.
 * @param BackGround Couleur du fond, donc a ne pas prendre en compte.
 * @param EightConnex Booleen qui permet de savoir si le calcul se fait en quatre ou huit connexites.
 * @param Chrono Le chronometre pour mesurer la duree.
 * @return Le nombre de composantes connexes de l'image.*/
public int Label(int[][] Original, int BackGround, boolean EightConnex, Chronometer Chrono)
	{
	int x, y, marker = 0 ;
	int height = Original.length ;
	int width = Original[0].length ;
 
	if ( Chrono != null )
		{
		System.out.print("Number of connected components computation with recursive algorithm: ") ;
		marker = Chrono.setMarker() ;
		}
 
	if ( Labels == null || height != Labels.length || width != Labels[0].length ) // Pour éviter de re-allouer chaque fois.
		{
		Labels = null ;
		Labels = new int[height][width] ;
		}
 
	ArraysOperations.SetConstant(Labels, -1) ; // On initialise
 
	Counter = 0 ;
	for (y=0 ; y < height ; y++)
		for (x=0 ; x < width ; x++)
			if ( Labels[y][x] == -1 ) // Si on a jamais touché à cette case.
				if ( Original[y][x] == BackGround ) Labels[y][x] = 0 ; // Si on est sur le fond, on met zéro.
				else Germ(Original, x, y, Original[y][x], BackGround, ++Counter, EightConnex) ; // Sinon on numérote la composante
 
	Sizes = null ; // On remplit le tableau Sizes.
	Sizes = new int[Counter+1] ;
	for (y=0 ; y < height ; y++)
		for (x=0 ; x < width ; x++)
			if ( Labels[y][x] > 0 )
				Sizes[Labels[y][x]]++ ;
 
	if ( Chrono != null )
		{
		System.out.println(Chrono.getTimeSinceMarker(marker)) ;
		Chrono.FreeMarker(marker) ;
		}
 
	return Counter ;
	}
 
 
 
 
 
 
 
 
 
 
 
 
 
/* ---------------------------------------------------------- 3D ---------------------------------------------------------- */
/** Calcule le nombre de composantes connexes dans l'image.
 * @param Original Le tableau dans lequel on doit compter les composantes connexes.
 * @param Fond Couleur du fond, donc a ne pas prendre en compte.
 * @param TwentySixConnex Booleen qui permet de savoir si le calcul se fait en six ou vingt six connexites.
 * @param Chrono Le chronometre pour mesurer la duree.
 * @return Le nombre de composantes connexes de l'image.*/
public int Label(int[][][] Original, int Fond, boolean TwentySixConnex, Chronometer Chrono)
	{
	// TODO Auto-generated method stub
	throw new Error("Method not yet implemeted.") ;
	}
 
 
 
 
 
 
 
 
 
 
 
 
 
/* --------------------------------------------------------- Le germe --------------------------------------------------------- */
/** Methode qui implemente le germe qui se repand dans la composante.
 * @param source
 * @param x
 * @param y
 * @param Color
 * @param BackGround
 * @param nb
 * @param EightConnex */
protected void Germ(BufferedImage source, int x, int y, int Color, int BackGround, int nb, boolean EightConnex)
	{
	if ( Labels[y][x] != -1 || source.getRaster().getSample(x, y, 0) != Color
		|| source.getRaster().getSample(x, y, 0) == BackGround ) return ;
 
	Labels[y][x] = nb ;
 
	if ( x < source.getWidth()-1 ) Germ(source, x+1, y, Color, BackGround, nb, EightConnex) ;
	if ( y < source.getHeight()-1 ) Germ(source, x, y+1, Color, BackGround, nb, EightConnex) ;
	if ( x > 0 ) Germ(source, x-1, y, Color, BackGround, nb, EightConnex) ;
	if ( y > 0 ) Germ(source, x, y-1, Color, BackGround, nb, EightConnex) ;
 
	if ( EightConnex && x < source.getWidth()-1 && y < source.getHeight()-1 )
		Germ(source, x+1, y+1, Color, BackGround, nb, EightConnex) ;
	if ( EightConnex && x < source.getWidth()-1 && y > 0 ) Germ(source, x+1, y-1, Color, BackGround, nb, EightConnex) ;
	if ( EightConnex && x > 0 && y < source.getHeight()-1 ) Germ(source, x-1, y+1, Color, BackGround, nb, EightConnex) ;
	if ( EightConnex && x > 0 && y > 0 ) Germ(source, x-1, y-1, Color, BackGround, nb, EightConnex) ;
	}
 
 
/** Methode qui implemente le germe qui se repand dans la composante.
 * @param source
 * @param x
 * @param y
 * @param Color
 * @param BackGround
 * @param nb
 * @param EightConnex */
protected void Germ(int[][] source, int x, int y, int Color, int BackGround, int nb, boolean EightConnex)
	{
	if ( Labels[y][x] != -1 || source[y][x] != Color || source[y][x] == BackGround ) return ;
 
	Labels[y][x] = nb ;
 
	if ( x < source[0].length-1 ) Germ(source, x+1, y, Color, BackGround, nb, EightConnex) ;
	if ( y < source.length-1 ) Germ(source, x, y+1, Color, BackGround, nb, EightConnex) ;
	if ( x > 0 ) Germ(source, x-1, y, Color, BackGround, nb, EightConnex) ;
	if ( y > 0 ) Germ(source, x, y-1, Color, BackGround, nb, EightConnex) ;
 
	if ( EightConnex && x < source[0].length-1 && y < source.length-1 ) Germ(source, x+1, y+1, Color, BackGround, nb, EightConnex) ;
	if ( EightConnex && x < source[0].length-1 && y > 0 ) Germ(source, x+1, y-1, Color, BackGround, nb, EightConnex) ;
	if ( EightConnex && x > 0 && y < source.length-1 ) Germ(source, x-1, y+1, Color, BackGround, nb, EightConnex) ;
	if ( EightConnex && x > 0 && y > 0 ) Germ(source, x-1, y-1, Color, BackGround, nb, EightConnex) ;
	}
 
 
 
 
 
 
/* ------------------------------------------------------- Les getters ------------------------------------------------------- */
/** Calcule le nombre de composantes connexes dans l'image mais ne compte que les composantes ayant une surface superieure a
 *  Threshold.
 * @param Threshold Surface minimum que doit avoir une composante connexe afin d'etre comptabilisee. 
 * @return Le nombre de composantes connexes de l'image.*/
public int NumberOfConnectedComponent(int Threshold)
	{
	if ( Labels == null ) throw new NullPointerException("Execution of Label method required before this one.") ;
 
	int nbccf = 0 ;
	for (int i=1 ; i <= Counter ; i++)
		if ( Sizes[i] >= Threshold ) nbccf++ ;
 
	return nbccf ;
	}
 
 
/** Methode qui renvoit le nombre de composantes connexes denombrees lors du dernier appel de la methode Label.
 * @return Le nombre de composantes.*/
public int NumberOfConnectedComponent()
	{
	return Counter ;
	}
 
 
/** Method which return sizes of connected components.
 * @return Array.*/
public int[] Sizes()
	{
	return Sizes;
	}
 
 
/** Method which return array of labels.
 * @return Array.*/
public int[][] Labels()
	{
	return Labels ;
	}
 
 
/** Method which return 3D array of labels.
 * @return Array 3D.*/
public int[][][] Labels3D()
	{
	return null ;
	}
 
}
__________________
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 actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/12/2009, 11h37   #4
ToTo13
Modérateur
 
Avatar de ToTo13
 
Homme Guillaume
Ingénieur de Recherche
Inscription : janvier 2006
Messages : 4 807
Détails du profil
Informations personnelles :
Nom : Homme Guillaume
Âge : 34
Localisation : Etats-Unis

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

Informations forums :
Inscription : janvier 2006
Messages : 4 807
Points : 7 052
Points : 7 052
Par défaut Itérative

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.util.List;
import java.util.Vector;
 
import utils.arrays.ArraysOperations;
import utils.times.Chronometer;
 
/**
 * <p>Description : Cette classe propose des methodes qui permettent de calculer le nombre de trous et de composantes connexes dans une image.
 *  Cette classe utilise un algorithme iteratif pour le calcul.</p>
 * <p>Package(s) required: imageTiTi, utils.</p>
 * <p>Copyright: Copyright (c) 2007-2011.</p>
 * <p>Laboratories/Teams: CMM (Mines-ParisTech/ENSMP), I&M (ex LXAO) LSIS.</p>
 * <p>Updates:<br>
 * 17 Janvier 2010, 1.3 => Ajout des methodes Label(DV, ...) et Label(int[][][], ...).<br>
 * 6 Aout 2009, 1.2 => Refonte complete avec la plateforme. Ajout de l'interface ConnectedComponentLabeling et separations des methodes en classes.<br>
 * 13 Avril 2008 => Ajout de la methode IsolerComposantes3.<br>
 * 02 Juillet 2007 => Creation.</p>
 * 
 * @author Guillaume THIBAULT
 * @version 1.3
 */
 
public class IterativeCcl implements ConnectedComponentLabeling
{
 
/** La derniere image sur laquelle on a compte le nombre de composantes.*/
protected BufferedImage source = null ;
 
/** Le tableau contenant la numerotation des composantes.*/
protected int[][] Labels = null ;
 
/** Le tableau contenant la numerotation des composantes pour les calculs en 3D.*/
protected int[][][] Labels3D = null ;
 
/** Tableau contenant les tailles des composantes connexes.*/
protected int[] Sizes = null ;
 
/** Nombre de composantes connexes denombrees lors du dernier appel de la methode Label.*/
protected int Counter = -1 ;
 
 
protected int[] ComposanteIdentiques ;
protected int Increment = 5000 ;
 
 
 
 
 
 
protected int TrouverEquivalence(int Equi)
	{
	if ( Equi >= ComposanteIdentiques.length ) IncreaseAlloc(Equi) ;
	if ( (Equi == 1) || (ComposanteIdentiques[Equi] == 0) ) return Equi ;
	else return TrouverEquivalence( ComposanteIdentiques[Equi] ) ;
	}
 
 
protected void IncreaseAlloc(int N)
	{
	int[] Tampon = ComposanteIdentiques.clone() ;
	ComposanteIdentiques = null ;
	ComposanteIdentiques = new int[N+Increment] ;
	for (int i=0 ; i < Tampon.length ; i++) ComposanteIdentiques[i] = Tampon[i] ;
	for (int i=Tampon.length ; i < ComposanteIdentiques.length ; i++) ComposanteIdentiques[i] = 0 ;
	Tampon = null ;
	}
 
 
 
 
/** Calcule le nombre de composantes connexes dans l'image binaire.
 * @param Original L'image dans laquelle on doit compter les composantes connexes.
 * @param BackGround Couleur du fond, donc tout ce qui n'est pas des composantes.
 * @param EightConnex Booleen qui permet de savoir si le calcul se fait en quatre ou huit connexites.
 * @param Chrono Le chronometre pour mesurer la duree.
 * @return Le nombre de composantes connexes de l'image.*/
public int Label(BufferedImage Original, int BackGround, boolean EightConnex, Chronometer Chrono)
	{
	if ( ImageTools.isColored(Original) ) throw new IllegalArgumentException("Only binary or gray level images supported.") ;
 
	this.source = Original ;
	int i, j, x, y, Color, marker = 0 ;
	int largeur = Original.getWidth() ;
	int hauteur = Original.getHeight() ;
	int Trouve1, Trouve2, Equi1, Equi2 ;
	boolean Fin = true ;
	WritableRaster wr = Original.getRaster() ;
 
	if ( Chrono != null )
		{
		System.out.print("Number of connected components computation with iterative algorithm: ") ;
		marker = Chrono.setMarker() ;
		}
 
	Labels = null ;
	Labels = new int[hauteur][largeur] ;
 
	ComposanteIdentiques = null ;
	ComposanteIdentiques = new int[Increment] ;
	ArraysOperations.SetConstant(ComposanteIdentiques, 0) ;
 
	for (i=0 ; i < hauteur ; i++)
		for (j=0 ; j < largeur ; j++)
			if ( wr.getSample(j, i, 0) == BackGround ) Labels[i][j] = 0 ;
			else Labels[i][j] = -1 ;
 
	Counter = 0 ;
	for (i=0 ; i < hauteur ; i++)
		for (j=0 ; j < largeur ; j++)
			if ( Labels[i][j] == -1 )
				{
				Color = wr.getSample(j, i, 0) ;
				Trouve1 = Trouve2 = 0 ; // On vérifie les deux voisins
 
				if ( (i > 0) && (wr.getSample(j, i-1, 0) == Color) ) // Au dessus
					Trouve1 = Labels[i-1][j] ;
				if ( (j > 0) && (wr.getSample(j-1, i, 0) == Color) ) // A gauche
					Trouve2 = Labels[i][j-1] ;
 
				if ( EightConnex ) // Si on compte en huit connexité
					{
					if ( (i > 0) && (j > 0) && (Trouve1 == 0) && (wr.getSample(j-1, i-1, 0) == Color) ) Trouve1 = Labels[i-1][j-1] ;
					else if ( (i > 0) && (j > 0) && (Trouve2 == 0) && (wr.getSample(j-1, i-1, 0) == Color) ) Trouve2 = Labels[i-1][j-1] ;
					else if ( (i > 0) && (j < largeur-1) && (Trouve1 ==0) && (wr.getSample(j+1, i-1, 0) == Color) ) Trouve1 = Labels[i-1][j+1] ;
					else if ( (i > 0) && (j < largeur-1) && (Trouve2 ==0) && (wr.getSample(j+1, i-1, 0) == Color) ) Trouve2 = Labels[i-1][j+1] ;
					}
 
				if ( (Trouve1 == 0) && (Trouve2 == 0) ) /* Aucun voisin n'est bon */
					Labels[i][j] = ++Counter ;
 
				if ( (Trouve1 != 0) && (Trouve2 == 0) ) /* Un seul des deux */
					Labels[i][j] = Trouve1 ;
				if ( (Trouve1 == 0) && (Trouve2 != 0) )
					Labels[i][j] = Trouve2 ;
 
				if ( (Trouve1 != 0) && (Trouve2 != 0) && (Trouve1 == Trouve2) ) /* Meme composante voisine */
					Labels[i][j] = Trouve1 ;
 
				if ( (Trouve1 != 0) && (Trouve2 != 0) && (Trouve1 != Trouve2) ) /* Tous les deux differents */
					{
					Fin = false ;
					Equi1 = TrouverEquivalence(Trouve1) ; /* On cherche l'origine de la composante */
					Equi2 = TrouverEquivalence(Trouve2) ;
					if ( (Equi1 < Equi2) || ((Equi1 == Equi2) && (Trouve1 < Trouve2)) )
						{
						Labels[i][j] = Equi1 ;
						ComposanteIdentiques[Trouve2] = Equi1 ;
						}
					else
						{
						Labels[i][j] = Equi2 ;
						ComposanteIdentiques[Trouve1] = Equi2 ;
						}
					}
				}
 
	while ( Fin == false ) /* On reactualise les equivalences */
			{
			Fin = true ;
			if ( Counter > ComposanteIdentiques.length ) IncreaseAlloc(Counter) ;
			for (i=1 ; i <= Counter ; i++)
				if ( ComposanteIdentiques[i] != 0 ) /* Il a un equivalent */
					if ( (ComposanteIdentiques[ComposanteIdentiques[i]] != 0) /* Si le prede...  a aussi un equivalent */
						&& (ComposanteIdentiques[ComposanteIdentiques[i]] != ComposanteIdentiques[i]) )
						{
						Fin = false ;
						ComposanteIdentiques[i] = ComposanteIdentiques[ComposanteIdentiques[i]] ;
						}
			}
 
	for (i=0 ; i < hauteur ; i++) /* On remet les bonnes valeurs */
		for (j=0 ; j < largeur ; j++)
			if ( Labels[i][j] > 0 )
				{
				if ( Labels[i][j] >= ComposanteIdentiques.length ) IncreaseAlloc(Labels[i][j]) ;
				if (ComposanteIdentiques[Labels[i][j]] != 0 )
					Labels[i][j] = ComposanteIdentiques[ Labels[i][j] ] ;
				}
 
	for (i=0 ; i <= Counter ; i++) /* On reinitialise */
		ComposanteIdentiques[i] = 0 ;
 
	for (i=0 ; i < hauteur ; i++) /* On note les composantes trouves */
		for (j=0 ; j < largeur ; j++)
			if ( Labels[i][j] > 0 ) ComposanteIdentiques[ Labels[i][j] ] = 1 ;
 
	Trouve1 = 0 ;
	for (i=1 ; i <= Counter ; i++) /* On renumerote les composantes trouves de maniere consecutive dans l'ordre */
		if ( ComposanteIdentiques[i] == 1 )
			ComposanteIdentiques[i] = ++Trouve1 ;
 
	for (i=0 ; i < hauteur ; i++) /* On les remplaces par les nouveaux numeros */
		for (j=0 ; j < largeur ; j++)
			if ( (Labels[i][j] > 0) && (ComposanteIdentiques[Labels[i][j]] != 0) )
				Labels[i][j] = ComposanteIdentiques[ Labels[i][j] ] ;
 
	Counter = Trouve1 ;
 
 
	Sizes = null ; // On remplit le tableau Sizes.
	Sizes = new int[Counter+1] ;
	for (y=0 ; y < hauteur ; y++)
		for (x=0 ; x < largeur ; x++)
			if ( Labels[y][x] > 0 )
				Sizes[Labels[y][x]]++ ;
 
	if ( Chrono != null )
		{
		System.out.println(Chrono.getTimeSinceMarker(marker)) ;
		Chrono.FreeMarker(marker) ;
		}
 
	return Counter ;
	}
 
 
 
/** Calcule le nombre de composantes connexes dans l'image.
 * @param Original Le tableau dans lequel on doit compter les composantes connexes.
 * @param BackGround Couleur du fond, donc a ne pas prendre en compte.
 * @param EightConnex Booleen qui permet de savoir si le calcul se fait en quatre ou huit connexites.
 * @param Chrono Le chronometre pour mesurer la duree.
 * @return Le nombre de composantes connexes de l'image.*/
public int Label(int[][] Original, int BackGround, boolean EightConnex, Chronometer Chrono)
	{	
	int i, j, x, y, Color, marker = 0 ;
	int largeur = Original[0].length ;
	int hauteur = Original.length ;
	int Trouve1, Trouve2, Equi1, Equi2 ;
	boolean Fin = true ;
 
	if ( Chrono != null )
		{
		System.out.print("Number of connected components computation with iterative algorithm: ") ;
		marker = Chrono.setMarker() ;
		}
 
	Labels = null ;
	Labels = new int[hauteur][largeur] ;
 
	ComposanteIdentiques = null ;
	ComposanteIdentiques = new int[Increment] ;
	ArraysOperations.SetConstant(ComposanteIdentiques, 0) ;
 
	for (i=0 ; i < hauteur ; i++)
		for (j=0 ; j < largeur ; j++)
			if ( Original[i][j] == BackGround ) Labels[i][j] = 0 ;
			else Labels[i][j] = -1 ;
 
	Counter = 0 ;
	for (i=0 ; i < hauteur ; i++)
		for (j=0 ; j < largeur ; j++)
			if ( Labels[i][j] == -1 )
				{
				Color = Original[i][j] ;
				Trouve1 = Trouve2 = 0 ; // On vérifie les deux voisins
 
				if ( (i > 0) && (Original[i-1][j] == Color) ) // Au dessus
					Trouve1 = Labels[i-1][j] ;
				if ( (j > 0) && (Original[i][j-1] == Color) ) // A gauche
					Trouve2 = Labels[i][j-1] ;
 
				if ( EightConnex ) // Si on compte en huit connexité
					{
					if ( (i > 0) && (j > 0) && (Trouve1 == 0) && (Original[i-1][j-1] == Color) ) Trouve1 = Labels[i-1][j-1] ;
					else if ( (i > 0) && (j > 0) && (Trouve2 == 0) && (Original[i-1][j-1] == Color) ) Trouve2 = Labels[i-1][j-1] ;
					else if ( (i > 0) && (j < largeur-1) && (Trouve1 ==0) && (Original[i-1][j+1] == Color) ) Trouve1 = Labels[i-1][j+1] ;
					else if ( (i > 0) && (j < largeur-1) && (Trouve2 ==0) && (Original[i-1][j+1] == Color) ) Trouve2 = Labels[i-1][j+1] ;
					}
 
				if ( (Trouve1 == 0) && (Trouve2 == 0) ) /* Aucun voisin n'est bon */
					Labels[i][j] = ++Counter ;
 
				if ( (Trouve1 != 0) && (Trouve2 == 0) ) /* Un seul des deux */
					Labels[i][j] = Trouve1 ;
				if ( (Trouve1 == 0) && (Trouve2 != 0) )
					Labels[i][j] = Trouve2 ;
 
				if ( (Trouve1 != 0) && (Trouve2 != 0) && (Trouve1 == Trouve2) ) /* Meme composante voisine */
					Labels[i][j] = Trouve1 ;
 
				if ( (Trouve1 != 0) && (Trouve2 != 0) && (Trouve1 != Trouve2) ) /* Tous les deux differents */
					{
					Fin = false ;
					Equi1 = TrouverEquivalence(Trouve1) ; /* On cherche l'origine de la composante */
					Equi2 = TrouverEquivalence(Trouve2) ;
					if ( (Equi1 < Equi2) || ((Equi1 == Equi2) && (Trouve1 < Trouve2)) )
						{
						Labels[i][j] = Equi1 ;
						ComposanteIdentiques[Trouve2] = Equi1 ;
						}
					else
						{
						Labels[i][j] = Equi2 ;
						ComposanteIdentiques[Trouve1] = Equi2 ;
						}
					}
				}
 
	while ( Fin == false ) /* On reactualise les equivalences */
			{
			Fin = true ;
			if ( Counter > ComposanteIdentiques.length ) IncreaseAlloc(Counter) ;
			for (i=1 ; i <= Counter ; i++)
				if ( ComposanteIdentiques[i] != 0 ) /* Il a un equivalent */
					if ( (ComposanteIdentiques[ComposanteIdentiques[i]] != 0) /* Si le prede...  a aussi un equivalent */
						&& (ComposanteIdentiques[ComposanteIdentiques[i]] != ComposanteIdentiques[i]) )
						{
						Fin = false ;
						ComposanteIdentiques[i] = ComposanteIdentiques[ComposanteIdentiques[i]] ;
						}
			}
 
	for (i=0 ; i < hauteur ; i++) /* On remet les bonnes valeurs */
		for (j=0 ; j < largeur ; j++)
			if ( Labels[i][j] > 0 )
				{
				if ( Labels[i][j] >= ComposanteIdentiques.length ) IncreaseAlloc(Labels[i][j]) ;
				if (ComposanteIdentiques[Labels[i][j]] != 0 )
					Labels[i][j] = ComposanteIdentiques[ Labels[i][j] ] ;
				}
 
	for (i=0 ; i <= Counter ; i++) /* On reinitialise */
		ComposanteIdentiques[i] = 0 ;
 
	for (i=0 ; i < hauteur ; i++) /* On note les composantes trouves */
		for (j=0 ; j < largeur ; j++)
			if ( Labels[i][j] > 0 ) ComposanteIdentiques[ Labels[i][j] ] = 1 ;
 
	Trouve1 = 0 ;
	for (i=1 ; i <= Counter ; i++) /* On renumerote les composantes trouves de maniere consecutive dans l'ordre */
		if ( ComposanteIdentiques[i] == 1 )
			ComposanteIdentiques[i] = ++Trouve1 ;
 
	for (i=0 ; i < hauteur ; i++) /* On les remplaces par les nouveaux numeros */
		for (j=0 ; j < largeur ; j++)
			if ( (Labels[i][j] > 0) && (ComposanteIdentiques[Labels[i][j]] != 0) )
				Labels[i][j] = ComposanteIdentiques[ Labels[i][j] ] ;
 
	Counter = Trouve1 ;
 
 
	Sizes = null ; // On remplit le tableau Sizes.
	Sizes = new int[Counter+1] ;
	for (y=0 ; y < hauteur ; y++)
		for (x=0 ; x < largeur ; x++)
			if ( Labels[y][x] > 0 )
				Sizes[Labels[y][x]]++ ;
 
	if ( Chrono != null )
		{
		System.out.println(Chrono.getTimeSinceMarker(marker)) ;
		Chrono.FreeMarker(marker) ;
		}
 
	return Counter ;
	}
 
 
 
 
 
 
 
/* --------------------------------------------------------------- 3D --------------------------------------------------------------- */
/** Calcule le nombre de composantes connexes dans l'image.
 * @param Original Le tableau dans lequel on doit compter les composantes connexes.
 * @param Fond Couleur du fond, donc a ne pas prendre en compte.
 * @param TwentySixConnex Booleen qui permet de savoir si le calcul se fait en six ou vingt six connexites.
 * @param Chrono Le chronometre pour mesurer la duree.
 * @return Le nombre de composantes connexes de l'image.*/
public int Label(int[][][] Original, int Fond, boolean TwentySixConnex, Chronometer Chrono)
	{
	throw new Error("Method not yet implemeted.") ;
	}
 
 
 
 
 
 
 
 
/* --------------------------------------------------------------------- Les getters --------------------------------------------------------------------- */
/** Calcule le nombre de composantes connexes dans l'image mais ne compte que les composantes ayant une surface superieure a Threshold.
 * @param Threshold Surface minimum que doit avoir une composante connexe afin d'etre comptabilisee. 
 * @return Le nombre de composantes connexes de l'image.*/
public int NumberOfConnectedComponent(int Threshold)
	{
	if ( Labels == null ) throw new NullPointerException("Execution of Label method required before this one.") ;
 
	int nbccf = 0 ;
	for (int i=1 ; i <= Counter ; i++)
		if ( Sizes[i] >= Threshold ) nbccf++ ;
 
	return nbccf ;
	}
 
 
/** Methode qui renvoit le nombre de composantes connexes denombrees lors du dernier appel de la methode Label.
 * @return Le nombre de composantes.*/
public int NumberOfConnectedComponent()
	{
	return Counter ;
	}
 
 
/** Method which return sizes of connected components.
 * @return Array.*/
public int[] Sizes()
	{
	return Sizes;
	}
 
 
/** Method which return array of labels.
 * @return Array.*/
public int[][] Labels()
	{
	return Labels ;
	}
 
/** Method which return array of labels.
 * @return Array.*/
public int[][][] Labels3D()
	{
	return Labels3D ;
	}
 
}
__________________
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 actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/12/2009, 11h38   #5
ToTo13
Modérateur
 
Avatar de ToTo13
 
Homme Guillaume
Ingénieur de Recherche
Inscription : janvier 2006
Messages : 4 807
Détails du profil
Informations personnelles :
Nom : Homme Guillaume
Âge : 34
Localisation : Etats-Unis

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

Informations forums :
Inscription : janvier 2006
Messages : 4 807
Points : 7 052
Points : 7 052
Par défaut Union-Find

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
import imageTiTi.ImageTools;
 
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.util.List;
import java.util.Vector;
 
import utils.arrays.ArraysOperations;
import utils.arrays.ArraysTools;
import utils.times.Chronometer;
 
/**
 * <p>Description: Cette classe etiquette les composantes connexes d'une image a l'aide de l'algorithme Union-Find.<br>
 * ATTENTION : meme le fond est etiquette, quelque soit sa couleur.</p>
 * <p>Package(s) required: dv, imageTiTi, utils.</p>
 * <p>Copyright: Copyright (c) 2007-2011.</p>
 * <p>Laboratories/Teams: CMM (Mines-ParisTech/ENSMP), I&M (ex LXAO) LSIS.</p>
 * <p>Updates:<br>
 * 18 Janvier 2010, 1.1 => Utilisation de la nouvelle version qui supprime la classe UFClass.<br>
 * 5 Aout 2009 => Ajout de la gestion du fond.<br>
 * 9 Avril 2008 => Creation.</p>
 * 
 * @author Xavier Philippeau pour developpez.net, code modifie par Guillaume THIBAULT.
 * @version 1.1
 */
 
public class UnionFindCcl implements ConnectedComponentLabeling
{
 
/** Les dimensions de l'image ou du tableau traite.*/
private int width, height, size = -1 ;
/** Le tableau contenant la numerotation des composantes.*/
private int[][] Labels = null ;
 
/** La derniere image sur laquelle on a compte le nombre de composantes.*/
private BufferedImage source = null ;
 
/** Tableau contenant la taille des composantes connexes.*/
private int[] Sizes = null ;
 
/** Nombre de composantes connexes denombrees lors du dernier appel de la methode Label.*/
private int Counter = -1 ;
 
/** Tableau qui contient les valeurs des racines.*/
private int[] roots = null ;
/** Constante du fond.*/
private final int BACKGROUND = -2 ;
/** Constante de l'absence de racine.*/
private final int NOROOT = -1 ;
 
 
 
 
 
 
 
 
/** Calcule le nombre de composantes connexes dans l'image.
 * @param Original L'image dans laquelle on doit compter les composantes connexes.
 * @param Background Couleur du fond, donc a ne pas prendre en compte.
 * @param EightConnex Booleen qui permet de savoir si le calcul se fait en quatre ou huit connexites.
 * @param Chrono Le chronometre pour mesurer la duree.
 * @return Le nombre de composantes connexes de l'image.*/
public int Label(BufferedImage Original, int Background, boolean EightConnex, Chronometer Chrono)
	{
	int x, y, pos, root, marker = 0 ;
	WritableRaster wr = Original.getRaster() ;
	width = Original.getWidth() ;
	height = Original.getHeight() ;
	size = width * height ;
	source = Original ;
 
	if ( Chrono != null )
		{
		System.out.print("Number of connected components computed with union-find algorithm: ") ;
		marker = Chrono.setMarker() ;
		}
 
	if ( ImageTools.isColored(Original) ) throw new IllegalArgumentException("Only gray level or binary image supported.") ;
 
	if ( roots == null || roots.length != size )
		{
		roots = null ;
		roots = new int[size] ;
		}
 
	if ( Labels == null || Labels.length != height || Labels[0].length != width)
		{
		Labels = null ;
		Labels = new int[height][width] ; // copy label to new array
		}
 
	ArraysOperations.SetConstant(roots, 0) ;
	ArraysOperations.SetConstant(Labels, 0) ;
 
	for (y=pos=0 ; y < height ; y++)
		for (x=0 ; x < width ; x++, pos++)
			if ( wr.getSample(x, y, 0) == Background ) add(pos, BACKGROUND) ;
			else
				{
				root = NOROOT ;
 
				if ( (x > 0) && (wr.getSample(x-1, y, 0) == wr.getSample(x, y, 0)) ) root = union(find(pos-1), root) ;
				if ( (y > 0) && (wr.getSample(x, y-1, 0) == wr.getSample(x, y, 0)) ) root = union(find(pos-width), root) ;
 
				if ( EightConnex )
					{
					if ( (x > 0 && y > 0) && (wr.getSample(x-1, y-1, 0) == wr.getSample(x, y, 0)) )
						root = union(find(pos-1-width), root) ;
					if ( (x < width-1 && y > 0) && (wr.getSample(x+1, y-1, 0) == wr.getSample(x, y, 0)) )
						root = union(find(pos+1-width), root) ;
					}
 
				add(pos, root) ;
				}
 
	buildLabelArray() ;
 
	if ( Chrono != null )
		{
		System.out.println(Chrono.getTimeSinceMarker(marker)) ;
		Chrono.FreeMarker(marker) ;
		}
 
	Counter = Sizes.length-1 ; 
	return Counter ;
	}
 
 
 
/** Calcule le nombre de composantes connexes dans l'image.
 * @param Original Le tableau dans lequel on doit compter les composantes connexes.
 * @param Background Couleur du fond, donc a ne pas prendre en compte.
 * @param EightConnex Booleen qui permet de savoir si le calcul se fait en quatre ou huit connexites.
 * @param Chrono Le chronometre pour mesurer la duree.
 * @return Le nombre de composantes connexes de l'image.*/
public int Label(int[][] Original, int Background, boolean EightConnex, Chronometer Chrono)
	{
	int x, y, pos, root, marker = 0 ;
	width = Original[0].length ;
	height = Original.length ;
	size = width * height ;
 
	if ( Chrono != null )
		{
		System.out.print("Number of connected components computed with union-find algorithm: ") ;
		marker = Chrono.setMarker() ;
		}
 
	if ( roots == null || roots.length != size )
		{
		roots = null ;
		roots = new int[size] ;
		}
 
	if ( Labels == null || Labels.length != height || Labels[0].length != width)
		{
		Labels = null ;
		Labels = new int[height][width] ; // copy label to new array
		}
 
	ArraysOperations.SetConstant(roots, 0) ;
	ArraysOperations.SetConstant(Labels, 0) ;
 
	for (y=pos=0 ; y < height ; y++)
		for (x=0 ; x < width ; x++, pos++)
			if ( Original[y][x] == Background ) add(pos, BACKGROUND) ;
			else
				{
				root = NOROOT ;
 
				if ( (x > 0) && (Original[y][x-1] == Original[y][x]) ) root = union(find(pos-1), root) ;
				if ( (y > 0) && (Original[y-1][x] == Original[y][x]) ) root = union(find(pos-width), root) ;
 
				if ( EightConnex )
					{
					if ( (x > 0 && y > 0) && (Original[y-1][x-1] == Original[y][x]) ) root = union(find(pos-1-width), root) ;
					if ( (x < width-1 && y > 0) && (Original[y-1][x+1] == Original[y][x]) ) root = union(find(pos+1-width), root) ;
					}
 
				add(pos, root) ;
				}
 
	buildLabelArray() ;
 
	if ( Chrono != null )
		{
		System.out.println(Chrono.getTimeSinceMarker(marker)) ;
		Chrono.FreeMarker(marker) ;
		}
 
	Counter = Sizes.length-1 ; 
	return Counter ;
	}
 
 
 
 
 
 
 
 
 
/* ----------------------------------------------------- 3D ----------------------------------------------------- */
/** Calcule le nombre de composantes connexes dans l'image.
 * @param Original Le tableau dans lequel on doit compter les composantes connexes.
 * @param Background Couleur du fond, donc a ne pas prendre en compte.
 * @param TwentySixConnex Booleen qui permet de savoir si le calcul se fait en six ou vingt six connexites.
 * @param Chrono Le chronometre pour mesurer la duree.
 * @return Le nombre de composantes connexes de l'image.*/
public int Label(int[][][] Original, int Background, boolean TwentySixConnex, Chronometer Chrono)
	{
	throw new Error("Method not yet implemented.") ;
	}
 
 
 
 
 
 
 
 
 
 
/* ----------------------------------------------------- Méthodes utiles ----------------------------------------------------- */
/** Find the root of the node at position pos. 
 * @param pos
 * @return .*/
private int find(int pos)
	{
	while ( roots[pos] != pos ) pos = roots[pos] ;
	return pos ;
	}
 
/** Union of the 2 path formed by the 2 roots.
 * @param root0
 * @param root1
 * @return .*/
private int union(int root0, int root1)
	{
	if ( root0 == root1 ) return root0 ;
	if ( root0 == NOROOT ) return root1 ;
	if ( root1 == NOROOT ) return root0 ;
	if ( root0 < root1 )
		{
		roots[root1] = root0 ;
		return root0 ;
		}
	else
		{
		roots[root0] = root1 ;
		return root1 ;
		}
	}
 
 
/** Set the root of the node at position pos.  
 * @param pos
 * @param root */
private void add(int pos, int root)
	{
	if ( root == NOROOT ) roots[pos] = pos ;
	else roots[pos] = root ;
	}
 
 
/** Build the connected component labels array.*/
private void buildLabelArray()
	{
	int x, y, pos, max ;
 
	for (pos=0 ; pos < size ; pos++) // remove indirections
		if ( roots[pos] != BACKGROUND )
			roots[pos] = find(pos) ;
 
	int label = 1 ; // relabel the root
	for (y=pos=0 ; y < height ; y++)
		for (x=0 ; x < width ; x++, pos++)
			if ( roots[pos] == BACKGROUND ) Labels[y][x] = 0 ;
			else
				{
				if ( roots[pos] == pos ) roots[pos] = label++ ;
				else roots[pos] = roots[roots[pos]] ;
 
				Labels[y][x] = roots[pos] ;
				}
 
	max = ArraysTools.MaxValue(Labels) ;
	if ( Sizes == null || max+1 != Sizes.length )
		{
		Sizes = null ;
		Sizes = new int[max+1] ;
		}
 
	ArraysOperations.SetConstant(Sizes, 0) ;
	for (y=0 ; y < height ; y++)
		for(x=0 ; x < width ; x++)
			if ( Labels[y][x] > 0 )
				Sizes[Labels[y][x]]++ ;
	}
 
 
 
 
 
 
/** Calcule le nombre de composantes connexes dans l'image, mais ne compte que les composantes
 *  ayant une surface superieure a Threshold.
 * @param Threshold Surface minimum que doit avoir une composante connexe afin d'etre comptabilisee. 
 * @return Le nombre de composantes connexes de l'image.*/
public int NumberOfConnectedComponent(int Threshold)
	{
	if ( Labels == null ) throw new NullPointerException("Execution of Label method required before this one.") ;
 
	int nbccf = 0 ;
	for (int i=1 ; i < Sizes.length ; i++)
		if ( Sizes[i] >= Threshold ) nbccf++ ;
 
	return nbccf ;
	}
 
 
/** Methode qui renvoit le nombre de composantes connexes denombrees lors du dernier appel de la methode Label.
 * @return Le nombre de composantes.*/
public int NumberOfConnectedComponent()
	{
	return Sizes.length-1 ;
	}
 
 
 
 
 
 
 
 
 
/* ----------------------------------------------------- Les getters ----------------------------------------------------- */
/** Method which return sizes of connected components.
 * @return Array.*/
public int[] Sizes()
	{
	return Sizes ;
	}
 
 
/** Method which return array of labels.
 * @return Array.*/
public int[][] Labels()
	{
	return Labels ;
	}
 
 
/** Method which return array of labels.
 * @return Array.*/
public int[][][] Labels3D()
	{
	return null ;
	}
 
}
__________________
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 actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/12/2009, 14h51   #6
pseudocode
Rédacteur/Modérateur
 
Avatar de pseudocode
 
Homme Xavier Philippeau
Architecte système
Inscription : décembre 2006
Messages : 9 837
Détails du profil
Informations personnelles :
Nom : Homme Xavier Philippeau
Âge : 40
Localisation : France, Hérault (Languedoc Roussillon)

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

Informations forums :
Inscription : décembre 2006
Messages : 9 837
Points : 16 517
Points : 16 517
Citation:
Envoyé par ToTo13 Voir le message
De même la version Union-Find est très belle, mais très lente : environ 5 à 8 fois plus lente que la FiFo (calculé de manière empirique).
Il faut dire aussi que cette version (la 1ere que j'avais postée) n'était pas du tout optimisée car elle utilisait un tableau Width*Height instances de la classe "UFClass".

La dernière version en date utilise un tableau de int[], ce qui devrait être plus rapide. Cela dit, je ne pense pas que ca batte la version FIFO.
__________________
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 16/12/2009, 17h20   #7
ToTo13
Modérateur
 
Avatar de ToTo13
 
Homme Guillaume
Ingénieur de Recherche
Inscription : janvier 2006
Messages : 4 807
Détails du profil
Informations personnelles :
Nom : Homme Guillaume
Âge : 34
Localisation : Etats-Unis

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

Informations forums :
Inscription : janvier 2006
Messages : 4 807
Points : 7 052
Points : 7 052
Ok, merci.
Je ferai un petit Update dès que j'aurai un moment.
__________________
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 actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/05/2010, 16h00   #8
Anis99
Candidat au titre de Membre du Club
 
Inscription : mai 2010
Messages : 15
Détails du profil
Informations forums :
Inscription : mai 2010
Messages : 15
Points : 13
Points : 13
Bonsoir;
Je ne sais pas si vous pouvez me passer le package meseaures pour que je puisse tester le code fifo.

Cordialment.
Anis99 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/05/2010, 02h19   #9
Anis99
Candidat au titre de Membre du Club
 
Inscription : mai 2010
Messages : 15
Détails du profil
Informations forums :
Inscription : mai 2010
Messages : 15
Points : 13
Points : 13
Citation:
Envoyé par ToTo13 Voir le message
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
 
package measures.cclh;
 
import java.util.List;
import java.util.Vector;
 
import imageTiTi.Image;
import imageTiTi.SubImage;
import utils.chronometer.Chronometer;
 
/**
 * <p>Description : Cette classe propose des methodes qui permettent de calculer le nombre de trous et de composantes connexes dans une image.
 *  Cette classe utilise un algorithme iteratif contenant une file.</p>
 * <p>Packages necessaires : imageTiTi, utils.</p>
 * <p>Dernieres modifications :<br>
 * 12 Octobre 2009 => Creation.</p>
 * <p>Copyright : Copyright (c) 2007.</p>
 * <p>Laboratoire : LSIS.</p>
 * <p>Equipe : Image et Modele, I&M (ex LXAO).</p>
 * 
 * @author Guillaume THIBAULT
 * @version 1.0
 */
 
public class FifoCcl implements ConnectedComponentLabeling
{
 
/** La dernier image sur laquelle on a compte le nombre de composantes.*/
protected Image source = null ;
 
/** Le tableau contenant la numerotation des composantes.*/
protected int[][] Labels = null ;
 
/** Tableau contenant la taille des composantes connexes.*/
protected int[] Sizes = null ;
 
/** Nombre de composantes connexes denombrees lors du dernier appel de la methode Label.*/
protected int Counter = -1 ;
 
/** La file contenant les pixels a traiter.*/
protected List<Coordinates> fifo = new Vector<Coordinates>() ;
 
 
/** Classe permettant de stocker les coordonnees des pixels. Classe minimale, moins lourde qu'un point.
 * @author FiReTiTi*/
private class Coordinates
	{
	int X, Y ;
	public Coordinates(int X, int Y)
		{
		this.X = X ;
		this.Y = Y ;
		}
	}
 
 
 
 
/** Calcule le nombre de composantes connexes dans l'image.
 * @param Original L'image dans laquelle on doit compter les composantes connexes.
 * @param BackGround Couleur du fond, donc a ne pas prendre en compte.
 * @param EightConnex Booleen qui permet de savoir si le calcul se fait en quatre ou huit connexites.
 * @param Chrono Le chronometre pour mesurer la duree.
 * @return Le nombre de composantes connexes de l'image.*/
public int Label(Image Original, int BackGround, boolean EightConnex, Chronometer Chrono)
	{
	int x, y, X, Y, Color ;
	int height = Original.Height() ;
	int width = Original.Width() ;
 
	if ( Chrono != null )
		{
		System.out.print("Number of connected components computation with fifo algorithm: ") ;
		Chrono.setMarqueur() ;
		}
 
	if ( Labels == null || height != Labels.length || width != Labels[0].length ) // Pour éviter de re-allouer chaque fois.
		{
		Labels = null ;
		Labels = new int[height][width] ;
		}
 
	source = null ;
	source = Original ;
	fifo.clear() ;
 
	for (y=0 ; y < height ; y++) // On initialise
		for (x=0 ; x < width ; x++)
			Labels[y][x] = -1 ;
 
	Counter = 0 ;
	for (y=0 ; y < height ; y++)
		for (x=0 ; x < width ; x++)
			if ( Labels[y][x] == -1 ) // Si on a jamais touché à cette case.
				if ( Original.Pixel(y, x) == BackGround ) Labels[y][x] = 0 ; // Si on est sur le fond, on met zéro.
				else
					{
					Counter++ ;
					Mark(x, y, Counter) ;
					Color = Original.Pixel(y, x) ;
					X = x ;
					Y = y ;
 
					do	{
						x = fifo.get(0).X ;
						y = fifo.get(0).Y ;
						fifo.remove(0) ;
 
						if ( y-1 >= 0 && Labels[y-1][x] == -1 && Original.Pixel(y-1, x) == Color ) Mark(x, y-1, Counter) ;
						if ( y+1 < height && Labels[y+1][x] == -1 && Original.Pixel(y+1, x) == Color ) Mark(x, y+1, Counter) ;
						if ( x-1 >= 0 && Labels[y][x-1] == -1 && Original.Pixel(y, x-1) == Color ) Mark(x-1, y, Counter) ;
						if ( x+1 < width && Labels[y][x+1] == -1 && Original.Pixel(y, x+1) == Color ) Mark(x+1, y, Counter) ;
 
						if ( EightConnex )
							{
							if ( y-1 >= 0 && x-1 >= 0 && Labels[y-1][x-1] == -1 && Original.Pixel(y-1, x-1) == Color ) Mark(x-1, y-1, Counter) ;
							if ( y-1 >= 0 && x+1 < width && Labels[y-1][x+1] == -1 && Original.Pixel(y-1, x+1) == Color ) Mark(x+1, y-1, Counter) ;
							if ( y+1 < height && x-1 >= 0 && Labels[y+1][x-1] == -1 && Original.Pixel(y+1, x-1) == Color ) Mark(x-1, y+1, Counter) ;
							if ( y+1 < height && x+1 < width && Labels[y+1][x+1] == -1 && Original.Pixel(y+1, x+1) == Color ) Mark(x+1, y+1, Counter) ;
							}
 
						}	while ( !fifo.isEmpty() ) ;
 
					x = X ;
					y = Y ;
					}
 
	Sizes = null ; // On remplit le tableau Sizes.
	Sizes = new int[Counter+1] ;
	for (y=0 ; y < height ; y++)
		for (x=0 ; x < width ; x++)
			if ( Labels[y][x] > 0 )
				Sizes[Labels[y][x]]++ ;
 
	if ( Chrono != null ) System.out.println(Chrono.getTimeSinceMarqueurSecondes()) ;
 
	return Counter ;
	}
 
 
 
/** Petite methode permettant d'ajouter un point dans la liste et de mettre la valeur count dans le tableau Labels.
 * @param x Coordonnee en X.
 * @param y Coordonnee en Y.
 * @param count Le numero de la composante connexe.*/
private void Mark(int x, int y, int count)
	{
	fifo.add(new Coordinates(x, y)) ;
	Labels[y][x] = count ;
	}
 
 
 
 
 
 
/** Calcule le nombre de composantes connexes dans l'image mais ne compte que les composantes ayant une surface superieure a Threshold.
 * @param Threshold Surface minimum que doit avoir une composante connexe afin d'etre comptabilisee. 
 * @return Le nombre de composantes connexes de l'image.*/
public int NumberOfConnectedComponent(int Threshold)
	{
	if ( Labels == null ) throw new NullPointerException("Execution of Label method required before this one.") ;
 
	int nbccf = 0 ;
	for (int i=1 ; i <= Counter ; i++)
		if ( Sizes[i] >= Threshold ) nbccf++ ;
 
	return nbccf ;
	}
 
 
/** Methode qui renvoit le nombre de composantes connexes denombrees lors du dernier appel de la methode Label.
 * @return Le nombre de composantes.*/
public int NumberOfConnectedComponent()
	{
	return Counter ;
	}
 
 
/** Methode qui trouve les composantes connexes d'une image, puis les isole en les placant separemment dans un vector d'image.
 *  ATTENTION : Prend en compte les composantes sur les bords, donc potentiellement partiellement presentes. 
 * @param Threshold Surface minimum que doit avoir une composante connexe afin d'etre comptabilisee.
 * @param Marge Marge a laisser autour des composantes a isoler.
 * @return Une liste d'image qui contiend toutes les composantes separees.*/
public List<Image> SeparateAllComponents(int Threshold, int Marge)
	{
	if ( Labels == null ) throw new NullPointerException("Execution of Label method required before this one.") ;
 
	Image image ;
	List<Image> liste = new Vector<Image>() ;
	int largeur = source.getWidth() ;
	int hauteur = source.getHeight() ;
	int nbim, i, x, y ;
	int[] minx = new int[Counter+1] ; // Va contenir les mins et max
	int[] maxx = new int[Counter+1] ;
	int[] miny = new int[Counter+1] ;
	int[] maxy = new int[Counter+1] ;
 
	for (i=1 ; i <= Counter ; i++) // On initialise 
		{
		minx[i] = largeur ;
		miny[i] = hauteur ;
		maxx[i] = maxy[i] = 0 ;
		}
 
	for (y=0 ; y < hauteur ; y++) // On trouve les min et max pour toutes les composantes en un seul passage.
		for (x=0 ; x < largeur ; x++)
			if ( Labels[y][x] > 0 )
				{
				if ( x < minx[Labels[y][x]] ) minx[Labels[y][x]] = x ;
				if ( x > maxx[Labels[y][x]] ) maxx[Labels[y][x]] = x ;
				if ( y < miny[Labels[y][x]] ) miny[Labels[y][x]] = y ;
				if ( y > maxy[Labels[y][x]] ) maxy[Labels[y][x]] = y ;
				}
 
	nbim = 0 ;
	for (i=1 ; i <= Counter ; i++)
		{
		if ( Sizes[i] < Threshold ) continue ;
		liste.add(new Image(maxx[i]-minx[i]+2*Marge+1, maxy[i]-miny[i]+2*Marge+1, source.getType())) ;
		image = liste.get(nbim++) ;
		for (y=miny[i] ; y <= maxy[i] ; y++)
			for (x=minx[i] ; x <= maxx[i] ; x++)
				if ( Labels[y][x] == i )
					image.Pixel(y-miny[i]+Marge, x-minx[i]+Marge, source.Pixel(y, x)) ;
		}
 
	minx = null ;
	miny = null ;
	maxx = null ;
	maxy = null ;
 
	return liste ;
	}
 
 
/** Methode qui trouve les composantes connexes d'une image, puis les isole en les placant separemment dans un vector d'image.
 *  ATTENTION : Ne prend pas en compte les composantes sur les bords. 
 * @param Threshold Surface minimum que doit avoir une composante connexe afin d'etre comptabilisee.
 * @param Marge Marge a laisser autour des composantes a isoler.
 * @return Une liste d'image qui contiend toutes les composantes separees.*/
public List<Image> SeparateComponents(int Threshold, int Marge)
	{
	if ( Labels == null ) throw new NullPointerException("Execution of Label method required before this one.") ;
 
	Image image ;
	List<Image> liste = new Vector<Image>() ;
	int largeur = source.getWidth() ;
	int hauteur = source.getHeight() ;
	int i, x, y, nbim ;
	int[] minx = new int[Counter+1] ; // Va contenir les mins et max
	int[] maxx = new int[Counter+1] ;
	int[] miny = new int[Counter+1] ;
	int[] maxy = new int[Counter+1] ;
 
	for (i=1 ; i <= Counter ; i++) // On initialise 
		{
		minx[i] = largeur ;
		miny[i] = hauteur ;
		maxx[i] = maxy[i] = 0 ;
		}
 
	for (y=0 ; y < hauteur ; y++) // On trouve les min et max pour toutes les composantes en un seul passage.
		for (x=0 ; x < largeur ; x++)
			if ( Labels[y][x] > 0 )
				{
				if ( x < minx[Labels[y][x]] ) minx[Labels[y][x]] = x ;
				if ( x > maxx[Labels[y][x]] ) maxx[Labels[y][x]] = x ;
				if ( y < miny[Labels[y][x]] ) miny[Labels[y][x]] = y ;
				if ( y > maxy[Labels[y][x]] ) maxy[Labels[y][x]] = y ;
				}
 
	nbim = 0 ;
	for (i=1 ; i <= Counter ; i++)
		{
		if ( Sizes[i] < Threshold ) continue ;
		if ( (minx[i] == 0) || (miny[i] == 0) || (maxx[i] == largeur-1) || (maxy[i] == hauteur-1) ) continue ; // On ne prend pas sur les bords
		liste.add(new Image(maxx[i]-minx[i]+2*Marge+1, maxy[i]-miny[i]+2*Marge+1, source.getType())) ;
		image = liste.get(nbim++) ;
		for (y=miny[i] ; y <= maxy[i] ; y++)
			for (x=minx[i] ; x <= maxx[i] ; x++)
				if ( Labels[y][x] == i )
					image.Pixel(y-miny[i]+Marge, x-minx[i]+Marge, source.Pixel(y, x)) ;
		}
 
	minx = null ;
	miny = null ;
	maxx = null ;
	maxy = null ;
 
	return liste ;
	}
 
 
 
/** Method which return sizes of connected components.
 * @return Array.*/
public int[] Sizes()
	{
	return Sizes;
	}
 
 
/** Method which return array of labels.
 * @return Array.*/
public int[][] Labels()
	{
	return Labels ;
	}
 
 
 
}
J e vous demander si c'est possible de me passer "package measures.cclh" pour que je puisse tester votre code FiFo est l'implementé a mon application!

pouvez vous me faire passer le codejava des methodes "chronometre" et "pixel(x,y)"
Anis99 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/06/2010, 04h13   #10
ToTo13
Modérateur
 
Avatar de ToTo13
 
Homme Guillaume
Ingénieur de Recherche
Inscription : janvier 2006
Messages : 4 807
Détails du profil
Informations personnelles :
Nom : Homme Guillaume
Âge : 34
Localisation : Etats-Unis

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

Informations forums :
Inscription : janvier 2006
Messages : 4 807
Points : 7 052
Points : 7 052
Par défaut [Reponse made in Vietnam]

Bonjour,

les classes que je propose ici sont dans le package measures. Le plus simple est que vous supprimiez cette ligne et que vous plassiew les classes dans votre propre package.

La classe chronometre n'est pas utile pour le fonctionnement, supprimez donc les lignes qui l'utlise.

Pour la classe image, utilisez la votre. si vous n'en avez pas, utilisez les BufferedImage de Java.
__________________
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 actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/01/2011, 15h01   #11
ToTo13
Modérateur
 
Avatar de ToTo13
 
Homme Guillaume
Ingénieur de Recherche
Inscription : janvier 2006
Messages : 4 807
Détails du profil
Informations personnelles :
Nom : Homme Guillaume
Âge : 34
Localisation : Etats-Unis

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

Informations forums :
Inscription : janvier 2006
Messages : 4 807
Points : 7 052
Points : 7 052
Bonjour,

je viens de faire une mise à jour de ces algorithmes, qui n'utilisent plus ma classe image. Il y a également la dernière version Union-Find de pseudo-code.

Vous trouverez également les sources dans les archives de code de dvp.


Citation:
Envoyé par pseudocode Voir le message
La dernière version en date utilise un tableau de int[], ce qui devrait être plus rapide. Cela dit, je ne pense pas que ca batte la version FIFO.
Et bien SI !!!
Après de nombreux tests :
- Union-Find est en moyenne deux fois plus rapide que Fifo (qui utilise une FAH).
- Cela augmente avec la taille des images.
- Dans les pires des cas, les résultats sont comparables (quelques dixièmes).

Je pense que cela vient du fait que Fifo utilise une liste qui contient des instances de "Coordinates".
Si quelqu'un a une solution...
__________________
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 actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/10/2012, 15h38   #12
carton99
Membre du Club
 
Inscription : avril 2010
Messages : 158
Détails du profil
Informations forums :
Inscription : avril 2010
Messages : 158
Points : 45
Points : 45
Bonjour,

Je trouve votre étude très intéressante mais j'aimerais quelque précision.

Je ne comprend pas très bien le type exact des algorithmes que vous utilisé à par Union-Find.
Quand vous parlez d'une méthode Itérative utilisez vous l'algorithme de remplissage par diffusion?
Quand vous parlez de méthode récursive utilisez aussi l'algorithme de remplissage par diffusion?
Je suis tres intéressé par l'algorithme qui fait référence à une file pour traiter la l'étiquetage.
Pour finir vous dite que Union find est moin gourmande que l'algorithme utilisant une liste Fifo surtout quand la taille de l'image grandit.

J'en déduit que la complexité de l'algorithme utilisant la liste fifo et bien plus grande que pour Union find?

Cordialement,
christophe
carton99 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/10/2012, 20h27   #13
pseudocode
Rédacteur/Modérateur
 
Avatar de pseudocode
 
Homme Xavier Philippeau
Architecte système
Inscription : décembre 2006
Messages : 9 837
Détails du profil
Informations personnelles :
Nom : Homme Xavier Philippeau
Âge : 40
Localisation : France, Hérault (Languedoc Roussillon)

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

Informations forums :
Inscription : décembre 2006
Messages : 9 837
Points : 16 517
Points : 16 517
Citation:
Envoyé par carton99 Voir le message
J'en déduit que la complexité de l'algorithme utilisant la liste fifo et bien plus grande que pour Union find?
Les implémentations "naives" de Fifo et UnionFind ont le même ordre de complexité. Si on commence à ajouter des optimisations, UnionFind a généralement une meilleure complexité amortie.

Ici, la différence de performance vient surtout de l'implémentation. En Java les collections stockent des instances de classe, et c'est relativement couteux de créer ces instances.

Rien qu'en remplacant la classe "Coordinates" par la Classe "Integer", ca améliore déjà les choses. Ca serait encore mieux avec un type natif (int), mais il n'existe pas de collections de type natif en Java.

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
/**
 * @param input image as a 2D array of integers
 * @param background background value
 * @return the regionmap of the connected components
 */
public int[][] computeLabel(int[][] input, int background) {
	int width = input.length;
	int height = input[0].length;
 
	int[][] regionmap = new int[width][height];
	int label = 0;
	List<Integer> fifo = new LinkedList<Integer>();
 
	// for each pixels in the image
	for (int y = 0; y < height; y++) {
		for (int x = 0; x < width; x++) {
			// ignore background
			if (input[x][y]==background) continue;
 
			// pixel is already labeled -> next
			if (regionmap[x][y]>0) continue;
 
			// set a new label for the current pixel
			label++;
			regionmap[x][y]=label;
 
			// put the pixel in the fifo
			fifo.add(x);
			fifo.add(y);
 
			// for each pixel in the fifo
			while (!fifo.isEmpty()) {
				int x0 = fifo.remove(0);
				int y0 = fifo.remove(0);
 
				// visit the 8 connected neighborhood
				int ymin = (y0==0)?(0):(y0-1), ymax = (y0==height-1)?(height-1):(y0+1);
				int xmin = (x0==0)?(0):(x0-1), xmax = (x0==width-1)?(width-1):(x0+1);
				for (int yn=ymin;yn<=ymax;yn++){
					for (int xn=xmin;xn<=xmax;xn++){
						// ignore background
						if (input[xn][yn]==background) continue;
						// the connected pixel is already labeled -> next
						if (regionmap[xn][yn]>0) continue;
						// the connected pixel is already visited -> next
						if (regionmap[xn][yn]==-label) continue;
						// the connected pixel does not match the origin -> next
						if (input[xn][yn]!=input[x][y]) {
							regionmap[xn][yn]=-label; // mark as visited
							continue;
						}
						// set the label for the connected pixel
						regionmap[xn][yn]=label;
						// put the connected pixel in the fifo
						fifo.add(xn);
						fifo.add(yn);
				}	}
			}
 
	}	}
 
	System.out.println("number of components:"+label);
	return regionmap;
}
__________________
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 28/12/2012, 18h24   #14
carton99
Membre du Club
 
Inscription : avril 2010
Messages : 158
Détails du profil
Informations forums :
Inscription : avril 2010
Messages : 158
Points : 45
Points : 45
bonjour,
je confirme Union-find est plus rapide (j'ai testé en AS3).
Mais effectivement Union-find est assez dur à coder corectement pour ne pas perdre du temps autre par que sur l'algo lui même.

Enfait non voir http://www.developpez.net/forums/d12...s/#post7047471
carton99 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 14h54.


 
 
 
 
Partenaires

Hébergement Web