67 votes

Fonction permettant de créer des roues de couleur

C'est quelque chose que j'ai des pseudo-résolu de nombreuses fois et jamais tout à fait trouvé une solution qui est coincé avec moi. Le problème est de trouver un moyen de générer de N couleurs, qui sont aussi reconnaissables que possible, où N est un paramètre.

24voto

nlucaroni Points 21502

Ma première pensée est "comment générer des N vecteurs dans un espace qui maximisent la distance les uns des autres." Vous pouvez voir que le RVB (ou toute autre échelle que vous utilisez et qui constitue une base dans l'espace de couleur) sont des vecteurs. Jetez un oeil à Point Aléatoire de la Cueillette. Espérons que c'est un bon début pour vous! Une fois que vous avez un ensemble de vecteurs qui sont agrandie d'une partie, vous pouvez les enregistrer dans une table de hachage ou quelque chose pour plus tard, et seulement effectuer des rotations sur eux pour obtenir toutes les couleurs que vous désirez sont au maximum les uns des autres!

Edit: Réflexion à propos de ce problème de plus, il serait mieux de mapper les couleurs dans un linéaire manoir, peut-être (0,0,0) --> (255,255,255) lexicographiquement, et ensuite les distribuer uniformément. Je ne sais vraiment pas comment cela va fonctionner, mais il faut depuis la, permet de dire que:

n = 10 nous savons que nous avons 16777216 couleurs (256^3). Nous pouvons utiliser les boucles de l'algorithme de 515 à trouver le lexicographiquement couleurs indexées.\frac {\binom {256^3} {3}} {n} * i. Vous devrez probablement modifier l'algorithme pour éviter le débordement et probablement ajouter quelques petites améliorations de la vitesse.

18voto

Liudvikas Bukys Points 3578

Il serait préférable de trouver les couleurs au maximum lointain dans un "perceptuellement uniforme" palette, par exemple CIELAB (à l'aide de la distance Euclidienne entre L*, a*, b* coordonnées comme votre distance métrique) puis la conversion de l'espace colorimétrique de votre choix. En terme de perception de l'homogénéité vient d'optimisation de l'espace colorimétrique de rapprocher les non-linéarités dans le système visuel humain.

8voto

hadley Points 33766

Quelques ressources:

ColorBrewer - Ensembles de couleurs conçues pour être au maximum de distinguer pour une utilisation sur des cartes.

Échapper RGBland: la Sélection des Couleurs pour des Graphiques Statistiques - Un rapport technique décrivant un ensemble d'algorithmes pour générer des bon (c'est à dire au maximum à distinguer) couleur dans la liste de compatibilité matérielle de l'espace couleur.

7voto

ravenspoint Points 8840

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

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( HSV2RGB( 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;
}

3voto

svrist Points 3408

N'est-il pas aussi un facteur de l'ordre dans lequel vous définissez les couleurs?

Si vous utilisez Dillie-Os idée vous avez besoin de mélanger les couleurs autant que possible. 0 64 128 256 est à partir de l'une à l'autre. mais 0 64 128 256 dans une roue serait plus "à part"

Est-il logique?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X