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

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

Contribuez Discussion :

[Image] Baguette Magique (fuzzy selection)


Sujet :

Contribuez

  1. #1
    Rédacteur

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

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut [Image] Baguette Magique (fuzzy selection)
    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):
    Je ne répondrai à aucune question technique en privé

  2. #2
    Rédacteur

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

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut
    Autre exemple pour traiter l'avant-plan au lieu de l'arrière plan :




    Et permet de réhausser la saturation de manière automatique uniquement sur l'arrière-plan :
    Je ne répondrai à aucune question technique en privé

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 2
    Points : 2
    Points
    2
    Par défaut
    Très bon code bien expliqué, serait-il toutefois possible que quelqu'un m'indique les différents imports à réaliser car j'ai voulu essayer ce code mais des erreurs subsistent et je dois rendre vendredi une baguette magique fonctionnelle

    Encore bravo à Millie en tout cas

  4. #4
    Rédacteur

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

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut
    Salut,

    Le problème est que j'utilise une bibliothèque perso (Image, ImageHSL) pour donner plus une syntaxe Algo.

    Tu pourras la trouver là : (ainsi que le GUI) : http://www.developpez.net/forums/d60...tement-images/

    Le jar Millie.jar contient tout ce qu'il faut normalement
    Je ne répondrai à aucune question technique en privé

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 2
    Points : 2
    Points
    2
    Par défaut
    Et bien que dire à part un grand merci pour cette réponse rapide et un grand bravo, je n'avais pas vu le sujet sur le projet Millie et je dois dire que je suis bluffé. Merci Millie

Discussions similaires

  1. [UI] Garder l'image affichée après le select sur selectMenu
    Par Pelote2012 dans le forum jQuery
    Réponses: 3
    Dernier message: 13/01/2015, 10h36
  2. Algo [baguette magique] en Java
    Par rilou dans le forum Graphisme
    Réponses: 2
    Dernier message: 04/08/2010, 11h38
  3. [Photoshop CS3] Ou est "Baguette magique"
    Par byloute dans le forum Imagerie
    Réponses: 1
    Dernier message: 12/10/2008, 14h33

Partager

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