Annonce

>>> Bienvenue sur codelab! >>> Première visite ? >>> quelques mots sur codelab //// partage de liens //// une carte des membres//// (apéros) codelab


#1 2017-04-05 23:31:46 Détecter quelle couleur est la plus proche d'une autre

AcousticQuantum
membre
Date d'inscription: 2014-11-25
Messages: 29

Détecter quelle couleur est la plus proche d'une autre



Bonjour! big_smile

D'un côté, j'ai une couleur définie, "cible".
De l'autre, une liste de différentes couleurs.

Comment déterminer quelle couleur dans ma liste est la plus proche de la couleur "cible"?

Je suis actuellement en RGB, mais rien ne m'interdit de passer en HSB... wink

J'ai fait un premier test (ci-joint) qui consiste à calculer la valeur absolue de la différence R, la différence G et la différence B entre ma cible et chaque élément de ma liste, puis d'additionner ces résultats obtenus. La plus petite somme obtenue étant sensé donner la couleur la plus proche...  yikes Késako? lol

Voici un exemple qui, je pense, illustre plus simplement mon charabiat: tongue

   - couleur cible => (32, 200, 154);
   - liste => [ (28, 5, 253), (100, 205, 205), (100, 100, 100) ]

   - calcul entre cible et 1er élément de la liste => abs(32 - 28) + abs(200 - 5) + abs(154 - 253) = 298
   - idem avec le 2e élément de la liste => = 94
   - idem avec le 3e => = 222

   - le plus petit étant 94, c'est la deuxième couleur de la liste qui devrait être la plus proche...



Mais je suis très déçu du résultat: certaines couleurs visiblement plus proche de ma cible me donne parfois un résultat très élevé et le plus petit résultat n'est visiblement pas le plus proche de ma cible... sad


Si quelqu'un a une idée, elle est le bienvenue!!! big_smile

Cordialement wink


Voici mon code test:

FloatList myColor; // couleur cible
FloatList red; // liste des rouges
FloatList green; // liste des verts
FloatList blue; // liste des bleus
FloatList difTot; // liste des résultats
int compt; // compteur
float difR, difG, difB;

void setup(){
 
  size(801, 601);
  background(0);
 
  myColor = new FloatList();
  myColor.append(random(0, 255)); // valeur rouge de ma couleur cible
  myColor.append(random(0, 255)); // valeur verte de ma couleur cible
  myColor.append(random(0, 255)); // valeur bleu de ma couleur cible
  fill(myColor.get(0), myColor.get(1), myColor.get(2));
  rect(650, 250, 100, 100); // je dessine un rectangle de ma couleur à droite
 
  red = new FloatList();
  green = new FloatList();
  blue = new FloatList();
  difTot = new FloatList();
 
  // création de 100 couleur RGB aléatoires
  for(int i = 0; i < 100; i++){
    red.append(random(0, 255));
    green.append(random(0, 255));
    blue.append(random(0, 255));
  }
 
  // création d'une grille de 100 carrés avec mes couleurs aléatoires
  for(int x = 0; x < 10; x++){
    for(int y = 0; y < 10; y++){
      fill(red.get(compt), green.get(compt), blue.get(compt));
      rect(x*60, y*60, 60, 60);
      compt++;
    }
  }
 
  // calcul des différences entre ma couleur cible et la couleur de chaque carré
  for(int j = 0; j < red.size(); j++){
    difR = abs(red.get(j) - myColor.get(0));
    difG = abs(green.get(j) - myColor.get(1));
    difB = abs(blue.get(j) - myColor.get(2));
    difTot.append(difR + difG + difB);
  }
  print(difTot); // affiche la liste des résultats obtenus
  println(difTot.min()); // affiche le plus petit résultat de cette liste
}

Dernière modification par AcousticQuantum (2017-04-05 23:33:13)

Hors ligne

 

#2 2017-04-06 18:34:26 Re : Détecter quelle couleur est la plus proche d'une autre

jojolaglaise
membre
Lieu: Basse Normandie
Date d'inscription: 2014-04-20
Messages: 134
Site web

Re: Détecter quelle couleur est la plus proche d'une autre



Pour ma part, j'opterai justement pour le mode HSB!
J'ai bricolé ce truc: ça affiche une image, on récupère la couleur pointée en haut à droite, et en haut à gauche on affiche les couleurs de la liste.

color[] palette = {color(28, 5, 253), 
                   color(100, 205, 205), 
                   color(100, 100, 100),
                   color(250, 5, 40),
                   color(0, 255, 0),
                   color(255, 255, 0)
                 };
color cible;
int proche;
int index;
PImage img; // image colore pour tester le code

void setup(){
  size(300, 400);
  colorMode(HSB, 360, 100, 100);
  noStroke();
  img = loadImage("image.png");
}

void draw(){
  proche = 360;
  index = 0;
  image(img, 0, 0, width, height);
  dessinerPalette(); // affiche les couleurs palettes
  couleurCible(get(mouseX, mouseY)); // couleur comparee
  
  //COMPARER
  for(int i = 0; i < palette.length; i++){
   int c = int(hue(palette[i]));
   int distance = abs(c - int(hue(cible)));
    if(distance < proche){
      proche = distance;
      index = i;
    }
  }
  //POINTEUR
  ellipse(index * 20 + 10, 10, 10, 10);
}

void dessinerPalette(){
  for(int i = 0; i < palette.length; i++){
    fill(palette[i]);
    rect(i * 20, 0, 20, 20);
  }
}

void couleurCible(color c_){
  cible = c_;
  fill(c_);
  rect(width - 20, 0, 20, 20);
}

Ça semble long, il y a des petites fonctions pour afficher les couleurs et tout le tralala, mais en réalité tout le propos se situe uniquement dans la boucle for.

La variable locale "c" ne fait que contenir successivement la valeur numérique de la teinte des couleurs de la liste. Ensuite on calcule la "distance", soit la différence entre la couleur pointée et la couleur courante de la liste. Plus on tend vers 0, plus la couleur sera proche.

Nous avons pris soin de déclarer une variable "proche" globale qui enregistre la valeur la plus petite (par défaut la valeur est à 360, car c'est le maximum de distance qu'il puisse y avoir entre deux couleurs):

Si et seulement si la distance courante est inférieur à la variable "proche", c'est-à-dire seulement quand la couleur courante de la liste est plus proche de la cible que les précédentes, alors le seuil de comparaison se rabaissera à la valeur de la sus-dite amélioration. À la fin du tour de boucle, il ne reste alors que le meilleur des résultats. Il ne reste plus qu'à enregistrer l'indice du tour de boucle (et donc de la couleur de la liste correspondante) dans une variable à l'intérieur de la condition ou le seuil de ressemble se resserre et tend vers la correspondance idéale: 0.

Je prend soin de réinitialiser les variables de seuillage à chaque tour de draw()…

Hors ligne

 

#3 2017-04-06 19:14:52 Re : Détecter quelle couleur est la plus proche d'une autre

jojolaglaise
membre
Lieu: Basse Normandie
Date d'inscription: 2014-04-20
Messages: 134
Site web

Re: Détecter quelle couleur est la plus proche d'une autre



Pardon pardon ce que j'ai présenté là ↑ n'est pas très beau:
Voici une solution qui opte —excuse-moi tu avais raison— pour le mode RGB.

L'idée est de spatialiser toutes les couleurs RVB dans un espace en 3D, un cube. Le noir est le point d'origine (0, 0, 0), soit un vecteur qui n'a pas de direction, un point. Ensuite, l'axe des X est celui du rouge, celui des Y celui du bleu, et celui de la profondeur, Z, le vert. Ainsi le blanc est un vecteur u = (1, 1, 1) tel que la distance maximale entre deux points de cet espace vectoriel est √3 (la diagonale du cube). J'ai tout normalisé juste pour faire ressurgir notre irrationnel racine de 3, mais j'aurais pu choisir un espace non-normé, balayant de 0 à 255.

J'ai ci-dessous juste fait une fonction qui convertit une couleur en vecteur. Ensuite il n'y a plus qu'à comparer la distance euclidienne entre deux point de l'espace. On remarquera qu'effectivement la distance entre le noir et le blanc est égale à √3 environ égale à 1.73205………

color[] palette = {color(28, 5, 253), 
                   color(100, 205, 205), 
                   color(100, 100, 100),
                   color(250, 5, 40),
                   color(0, 255, 0),
                   color(255, 255, 0),
                   color(255, 255, 255) // BLANC
                  };
color cible = color(0, 0, 0);  //NOIR

void setup(){
  size(400, 400);
  
  //on Compare 2 couleurs, en l'occurence du noir et du blanc
  println(dist(couleurEnVecteur(palette[6]).x, couleurEnVecteur(palette[6]).y, couleurEnVecteur(palette[6]).z,
               couleurEnVecteur(cible).x, couleurEnVecteur(cible).y, couleurEnVecteur(cible).z));

void draw(){
}

PVector couleurEnVecteur(color c){
  PVector u = new PVector(norm(int(red(c)), 0, 255), 
                          norm(int(blue(c)), 0, 255),
                          norm(int(green(c)), 0, 255));
  return u;
}

edit: je corrige ma racine de 2 par racine de 3… petite faute d'inattention……

Dernière modification par jojolaglaise (2017-04-06 19:35:11)

Hors ligne

 

#4 2017-04-09 20:21:24 Re : Détecter quelle couleur est la plus proche d'une autre

jojolaglaise
membre
Lieu: Basse Normandie
Date d'inscription: 2014-04-20
Messages: 134
Site web

Re: Détecter quelle couleur est la plus proche d'une autre



Au cas où:

à gauche les couleurs de la liste, à droite, la couleur "cible" qui change à chaque itération de draw.
J'ai gardé la fonction qui convertissait les couleurs en vecteur, et créé une fonction qui compare une liste de couleur avec une couleur "cible".
ça fonctionne plutôt bien avec les vecteurs il me semble !

//COULEUR et ESPACE VECTORIEL
color[] palette = {color(28, 5, 253), 
                   color(100, 205, 205), 
                   color(250, 5, 40),
                   color(0, 255, 0),
                   color(255, 255, 0),
                   color(255, 135, 25),
                   color(200, 30, 100)
                  };
color cible;

void setup(){
  size(400, 400);
}

void draw(){
  cible = color(random(255), random(255), random(255));
  fill(palette[comparerCouleurListe(palette, cible)]);
  rect(0, 0, width/2, height);
  fill(cible);
  rect(width/2, 0, width/2, height);
  delay(1000);
}

int comparerCouleurListe(color[] entree, color cible_){
  int indexListe = 0;
  float proche = sqrt(3) + pow(10, -1);
  float distance;
  entree = palette;
  for(int i = 0; i < entree.length; i++){
    distance = dist(couleurEnVecteur(entree[i]).x, couleurEnVecteur(entree[i]).y, couleurEnVecteur(entree[i]).z,
               couleurEnVecteur(cible_).x, couleurEnVecteur(cible_).y, couleurEnVecteur(cible_).z);
    if(distance < proche){
      proche = distance;
      indexListe = i;
    }
  }
  return indexListe;
}

PVector couleurEnVecteur(color c){
  PVector u = new PVector(norm(int(red(c)), 0, 255), 
                          norm(int(blue(c)), 0, 255),
                          norm(int(green(c)), 0, 255));
  return u;
}

Dernière modification par jojolaglaise (2017-04-09 20:23:26)

Hors ligne

 

#5 2017-05-02 18:25:14 Re : Détecter quelle couleur est la plus proche d'une autre

AcousticQuantum
membre
Date d'inscription: 2014-11-25
Messages: 29

Re: Détecter quelle couleur est la plus proche d'une autre



Désolé, je n'avais pas vu tes messages, mais merci pour cet effort smile ! En fait j'avais également trouvé la solution moi-même peu de temps après avoir posté ce message... J'ai également utilisé le système du cube RGB, et le vecteur le plus petit reliant la couleur cible aux couleurs de ma liste correspond à la couleur la Plus proche... J'espère que cela pourra être utile à l'avenir si jamais quelqu'un cherche une solution à ce problème...

Hors ligne

 

fil rss de cette discussion : rss

Pied de page des forums

Powered by FluxBB

codelab, graphisme & code : emoc / 2008-2017