Voici un code java qui permet de colorier une zone d'une image qui admet certains caractéristiques communes avec un pixel d'origine. Ceci est souvent utilisé pour sélectionner des zones de même couleur dans un dessin, l'avantage ici est qu'il est possible d'écrire les propres fonctions de comparaisons entre les couleurs.

Code java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
 
public class FuzzyColorization {
 
	private FuzzyComparator comparator;
	public FuzzyColorization(FuzzyComparator comparator) {
		this.comparator = comparator;
	}
 
	public void colorization(Image out, Image in, int origineX, int origineY, double[] colors) {
		colorization(out, in, origineX, origineY, colors, 1);
	}
	public void colorization(Image out, Image in, int origineX, int origineY, double[] colors, int rayon) {
		if(out.getNumComponents()!=in.getNumComponents())
			throw new IllegalArgumentException("Size out != size in");
		if(origineX<0 || origineY<0 || origineX>in.getWidth() || origineY>in.getHeight())
			throw new IllegalArgumentException("Range for x || y");
		if(colors.length!=in.getNumComponents())
			throw new IllegalArgumentException("Canals for Colors");
 
		out.setImage(in);
 
		boolean isVisitedPixels[][] = new boolean[in.getWidth()][in.getHeight()]; //permet de savoir rapidement si
		 // un pixel a été visité
		for(int j=0; j<in.getHeight(); j++)
			for(int i=0; i<in.getWidth(); i++)
				isVisitedPixels[i][j] = false;
 
		LinkedList<Position> visitedPixels = new LinkedList<Position>(); //liste des pixels visités
		LinkedList<Position> toVisit = new LinkedList<Position>(); //liste des pixels restants à visiter
 
		toVisit.add(new Position(origineX, origineY)); //on indique le pixel d'origine
 
		while(!toVisit.isEmpty()) { //on effectue un parcours du graphe
 
			Position p = toVisit.pollFirst();
			if(!isVisitedPixels[p.x][p.y]) {
				isVisitedPixels[p.x][p.y] = true;
				visitedPixels.add(p);
 
				int diametre = 2*rayon+1;  	//on prend en compte l'ensemble des pixels se trouvant autour du pixel courant
						//pour savoir si on doit l'intégrer ou non
 
				for (int kj = 0; kj < diametre; kj++)
					for (int ki = 0; ki < diametre; ki++) {
						int px = p.x + ki - rayon;
						int py = p.y + kj - rayon;
 
						if(px<0 || px>=in.getWidth()||py<0||py>=in.getHeight())
							continue;
						if(isVisitedPixels[px][py]) //si déjà visité, on l'ajoute pas
							continue;
 
						if(!(px==p.x && py==p.y)) {
							//permet de savoir si on doit intégrer dans la futur rechercher
							if(comparator.compareColor(origineX, origineY, px, py)) {
								toVisit.addLast(new Position(px, py));
							}
						}
 
				}
 
 
			}
 
		}
 
		//on colorie les pixels
		for(Position pos : visitedPixels) {
 
			for (int canal = 0; canal < in.getNumComponents(); canal++)
				out.setPixel(pos.x, pos.y, canal, colors[canal]);
		}
		System.err.println("Fin colorization");
	}
}

L'interface FuzzyComparator permet de savoir si le pixel (x2,y2) doit être ajouté au graphe (suivant le pixel d'origine x,y) :
Code java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
 
public interface FuzzyComparator {
 
	public boolean compareColor(int x, int y, int x2, int y2);
}

La méthode classique est de comparer la valeurs des deux pixels :
Code java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class SimpleFuzzyComparator implements FuzzyComparator {
	Image in;
	public SimpleFuzzyComparator(Image in) {
		this.in = in;
	}
	/* (non-Javadoc)
	 * @see millie.photo.FuzzyComparator#compareColor(millie.image.Image, int, int, int, int)
	 */
	@Override
	public boolean compareColor(int x, int y, int x2, int y2) {
		for(int canal = 0; canal<in.getNumComponents(); canal++)
			if(in.getPixel(x, y, canal) != in.getPixel(x2, y2, canal))
				return false;
		return true;
	}
 
}

Des méthodes permettent de comparer la luminance entre les deux pixels :
Code java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 
public class LightnessFuzzyComparator implements FuzzyComparator {
	private ImageHSL hsl = null;
	private double luminanceC;
 
 
       public LightnessFuzzyComparator(ImageRGB rgb, double luminanceC) {
		hsl = ImageHSL.createFromImageRGB(rgb);
		this.luminanceC = luminanceC;
	}
	/* (non-Javadoc)
	 * @see millie.photo.FuzzyComparator#compareColor(millie.image.Image, int, int, int, int)
	 */
	@Override
	public boolean compareColor(int x, int y, int x2, int y2) {
		if(Math.abs(hsl.getLightnessPixel(x, y)-hsl.getLightnessPixel(x2, y2))>luminanceC)
				return false;
 
		return true;
	}
 
}


Exemple :
Code java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
 
FuzzyColorization c = new FuzzyColorization(new HSLFuzzyComparator(in,0.4));
double[] colors = {255,0,0};
 
c.colorization(out, in, 1, 1, colors, 1);


On peut constater que la partie grise entre la colline et le blanc du fond a été supprimé pour ne garder que la colline (du fait que l'on peut mettre des fonctions de comparaison personnalisées) :





Image d'origine où une partie du ciel a été effacée à la main (première image):