Fonction pour créer des roues de couleur

voix
63

C'est quelque chose que j'ai plusieurs fois résolu pseudo et ne l'ai jamais trouvé une solution tout à fait pour.

Le problème est de trouver un moyen de générer des Ncouleurs, qui sont aussi distinguées que possible où Nest un paramètre.

Créé 01/08/2008 à 19:42
source utilisateur
Dans d'autres langues...                            


8 réponses

voix
23

Ma première pensée à ce sujet est « comment générer des vecteurs N dans un espace qui maximisent la distance les uns des autres. »

Vous pouvez voir que le RVB (ou toute autre échelle que vous utilisez qui forme une base dans l' espace couleur) ne sont que des vecteurs. Jetez un oeil à Picking aléatoire point . Une fois que vous avez un ensemble de vecteurs qui sont maximisée à part, vous pouvez les enregistrer dans une table de hachage ou quelque chose pour plus tard, et juste effectuer des rotations aléatoires sur eux pour obtenir toutes les couleurs que vous désirez qui sont au maximum l'une de l'autre!

En pensant à ce problème plus, il serait préférable de cartographier les couleurs d'une manière linéaire, peut-être (0,0,0) → (255255255) lexicographique, puis les répartir uniformément.

Je ne sais vraiment pas comment cela fonctionne, mais il devrait, car, disons-le:

n = 10

nous savons que nous avons 16777216 couleurs (256 ^ 3).

Nous pouvons utiliser Buckles algorithme 515 pour trouver la couleur indexée lexicographique. \ Frac {\ {binom 256 ^ 3} {3}} {n} * i. Vous devrez probablement modifier l'algorithme pour éviter tout débordement et probablement ajouter quelques améliorations mineures de vitesse.

Créé 02/08/2008 à 20:03
source utilisateur

voix
17

Il serait préférable de trouver des couleurs au maximum lointaines dans un « perceptuellement uniforme », par exemple colorspace CIELAB (en utilisant la distance euclidienne entre L *, a *, b * coordonnées que votre distance métrique), puis la conversion à l'colorspace de votre choix. uniformité de perception est réalisé en ajustant l'espace colorimétrique de rapprocher les non-linéarités dans le système visuel humain.

Créé 12/09/2008 à 20:00
source utilisateur

voix
7

Quelques ressources connexes:

ColorBrewer - Ensembles de couleurs conçus pour être au maximum distinguable pour une utilisation sur les cartes.

Escaping RGBland: Sélection des couleurs pour graphiques statistiques - Un rapport technique décrivant un ensemble d'algorithmes pour générer de bons ( à savoir au maximum distinguer) les jeux de couleurs dans l'espace couleur hcl.

Créé 18/09/2008 à 17:01
source utilisateur

voix
6

Voici un code pour attribuer des couleurs RVB uniformément autour d'une roue de couleur HSL de luminosité spécifiée.

class cColorPicker
{
public:
    void Pick( vector<DWORD>&v_picked_cols, int count, int bright = 50 );
private:
    DWORD HSL2RGB( int h, int s, int v );
    unsigned char ToRGB1(float rm1, float rm2, float rh);
};
/**

  Evenly allocate RGB colors around HSL color wheel

  @param[out] v_picked_cols  a vector of colors in RGB format
  @param[in]  count   number of colors required
  @param[in]  bright  0 is all black, 100 is all white, defaults to 50

  based on Fig 3 of http://epub.wu-wien.ac.at/dyn/virlib/wp/eng/mediate/epub-wu-01_c87.pdf?ID=epub-wu-01_c87

*/

void cColorPicker::Pick( vector<DWORD>&v_picked_cols, int count, int bright )
{
    v_picked_cols.clear();
    for( int k_hue = 0; k_hue < 360; k_hue += 360/count )
        v_picked_cols.push_back( HSL2RGB( k_hue, 100, bright ) );
}
/**

  Convert HSL to RGB

  based on http://www.codeguru.com/code/legacy/gdi/colorapp_src.zip

*/

DWORD cColorPicker::HSL2RGB( int h, int s, int l )
{
    DWORD ret = 0;
    unsigned char r,g,b;

    float saturation = s / 100.0f;
    float luminance = l / 100.f;
    float hue = (float)h;

    if (saturation == 0.0) 
    {
      r = g = b = unsigned char(luminance * 255.0);
    }
    else
    {
      float rm1, rm2;

      if (luminance <= 0.5f) rm2 = luminance + luminance * saturation;  
      else                     rm2 = luminance + saturation - luminance * saturation;
      rm1 = 2.0f * luminance - rm2;   
      r   = ToRGB1(rm1, rm2, hue + 120.0f);   
      g = ToRGB1(rm1, rm2, hue);
      b  = ToRGB1(rm1, rm2, hue - 120.0f);
    }

    ret = ((DWORD)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)));

    return ret;
}


unsigned char cColorPicker::ToRGB1(float rm1, float rm2, float rh)
{
  if      (rh > 360.0f) rh -= 360.0f;
  else if (rh <   0.0f) rh += 360.0f;

  if      (rh <  60.0f) rm1 = rm1 + (rm2 - rm1) * rh / 60.0f;   
  else if (rh < 180.0f) rm1 = rm2;
  else if (rh < 240.0f) rm1 = rm1 + (rm2 - rm1) * (240.0f - rh) / 60.0f;      

  return static_cast<unsigned char>(rm1 * 255);
}

int _tmain(int argc, _TCHAR* argv[])
{
    vector<DWORD> myCols;
    cColorPicker colpick;
    colpick.Pick( myCols, 20 );
    for( int k = 0; k < (int)myCols.size(); k++ )
        printf("%d: %d %d %d\n", k+1,
        ( myCols[k] & 0xFF0000 ) >>16,
        ( myCols[k] & 0xFF00 ) >>8,
        ( myCols[k] & 0xFF ) );

    return 0;
}
Créé 27/09/2008 à 17:39
source utilisateur

voix
3

Est-il pas aussi un facteur que vous commandez définir les couleurs?

Comme si vous utilisez idée Darlie-Os vous devez mélanger les couleurs autant que possible. 0 64 128 256 est de l'un à l'autre. mais 0 256 64 128 dans une roue serait plus « à part »

Est-ce que ça a du sens?

Créé 02/08/2008 à 19:16
source utilisateur

voix
1

Je sais que ce vieux poste, mais je l'ai trouvé tout en recherchant une solution PHP au sujet et, enfin, est venu avec une solution simple:

function random_color($i = null, $n = 10, $sat = .5, $br = .7) {
    $i = is_null($i) ? mt_rand(0,$n) : $i;
    $rgb = hsv2rgb(array($i*(360/$n), $sat, $br));
    for ($i=0 ; $i<=2 ; $i++) 
        $rgb[$i] = dechex(ceil($rgb[$i]));
    return implode('', $rgb);
}

function hsv2rgb($c) { 
    list($h,$s,$v)=$c; 
    if ($s==0) 
        return array($v,$v,$v); 
    else { 
        $h=($h%=360)/60; 
        $i=floor($h); 
        $f=$h-$i; 
        $q[0]=$q[1]=$v*(1-$s); 
        $q[2]=$v*(1-$s*(1-$f)); 
        $q[3]=$q[4]=$v; 
        $q[5]=$v*(1-$s*$f); 
        return(array($q[($i+4)%6]*255,$q[($i+2)%6]*255,$q[$i%6]*255)); //[1] 
    } 
}

Donc, il suffit d'appeler la fonction random_color () où i identifie $ la couleur, $ n le nombre de couleurs possibles, $ assis la saturation et la luminosité $ br.

Créé 19/10/2011 à 02:58
source utilisateur

voix
1

Je l'ai lu quelque part l'œil humain ne peut distinguer entre moins de 4 valeurs en dehors. C'est donc quelque chose à garder à l'esprit. L'algorithme suivant ne compense pas pour cela.

Je ne suis pas sûr que ce soit exactement ce que vous voulez, mais c'est un moyen de générer au hasard des valeurs de couleur non-répétition:

(Attention, pseudo-code incompatible à l'avance)

//colors entered as 0-255 [R, G, B]
colors = []; //holds final colors to be used
rand = new Random();

//assumes n is less than 16,777,216
randomGen(int n){
   while (len(colors) < n){
      //generate a random number between 0,255 for each color
      newRed = rand.next(256);
      newGreen = rand.next(256);
      newBlue = rand.next(256);
      temp = [newRed, newGreen, newBlue];
      //only adds new colors to the array
      if temp not in colors {
         colors.append(temp);
      }
   }
}

Une façon vous pouvez optimiser ce pour une meilleure visibilité serait de comparer la distance entre chaque nouvelle couleur et toutes les couleurs du tableau:

for item in color{
   itemSq = (item[0]^2 + item[1]^2 + item[2]^2])^(.5);
   tempSq = (temp[0]^2 + temp[1]^2 + temp[2]^2])^(.5);
   dist = itemSq - tempSq;
   dist = abs(dist);
}
//NUMBER can be your chosen distance apart.
if dist < NUMBER and temp not in colors {
   colors.append(temp);
}

Mais cette approche serait considérablement ralentir votre algorithme.

Une autre façon serait de supprimer le caractère aléatoire et aller systématiquement à travers toutes les 4 valeurs et ajouter une couleur à un tableau dans l'exemple ci-dessus.

Créé 01/08/2008 à 20:36
source utilisateur

voix
0

Pour atteindre « plus distinguables » nous avons besoin d'utiliser un espace couleur perceptuel comme Lab (ou tout autre espace couleur perceptuel linéaire) et non RGB. Aussi, nous pouvons quantifier cet espace pour réduire la taille de l'espace.

Générer le plein espace 3D avec toutes les entrées possibles et exécuter le quantifiées K-means avec k=N. Les centres résultants / « signifie » devrait être à peu près les plus distinguishabl les uns des autres.

Créé 07/02/2014 à 18:43
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more