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):
Partager