Vă mulțumim pentru susținere

Funcție pentru crearea de roți colorate

Acesta este un lucru pe care l-am rezolvat de multe ori pseudo-rezolvat și nu am găsit niciodată o soluție. Asta e blocată cu mine. Problema este de a găsi o modalitate de a genera culori N , care să fie cât se poate de distinctă unde N este un parametru.

0
adăugat editat
Ultima dată am verificat JFreeChart are acest algoritm precis și, deoarece este open source, puteți să verificați ce face . Știu că culorile pe care le primesc nu par a fi distanțate aleatoriu de-a lungul unui cerc sau sferă, ci mai degrabă alese mai exact.
adăugat autor Kathy Van Stone

8 răspunsuri

Primul meu gând pe această temă este "cum se generează vectori N într-un spațiu care maximizează distanța unul față de celălalt". Puteți vedea că RGB (sau orice altă scală pe care o utilizați, care formează baza în spațiul de culoare) sunt doar vectori. Aruncati o privire la Colectarea de puncte aleatorii . Sper că este un început bun pentru tine! Odată ce ai un set de vectori care maximizează o parte, poți să le salvezi într-o masă de tip hash sau ceva pentru mai târziu, și doar să efectuezi rotații aleatorii pe ele pentru a obține toate culorile pe care le dorești, care sunt maxim în afară unul de celălalt!

Edit: Thinking about this problem more, it would be better to map the colors in a linear manor, possibly (0,0,0) --> (255,255,255) lexicographically, and then distribute them evenly. I really don't know how well this will work, but it should since, lets say:

n = 10 știm că avem 16777216 culori (256 ^ 3). Putem folosi cataramă algoritmul 515 pentru a găsi culoarea indexată lexicografic . \ frac {\ binom {256 ^ 3} {3}} {n} * i. Probabil că va trebui să editați algoritmul pentru a evita supraîncărcarea și, probabil, să adăugați unele îmbunătățiri minore ale vitezei.

0
adăugat
Sunt de acord că sună logic. RGB face mai ales hibrizi purpuri și portocalii și relativ rar fac hibrizi verzi verzi ... scara de culori este uniformă de la infraroșu la albastru, deci trebuie să alegeți puncte egal distanțate de-a lungul ei. au nevoie de un algo bazat pe curcubeu.
adăugat autor com.prehensible
Vă rugăm să luați în considerare upvoting / urmând site-ul StackExchange Color Theory: area51.stackexchange.com/proposals/110687/color-theory</ a>
adăugat autor Adi Shavit
Acest lucru este incorect deoarece spațiul de culoare RGB nu este perceptiv uniform
adăugat autor adrienlucca.wordpress.com

Am citit undeva ochiul uman nu poate distinge între mai puțin de 4 valori. așa că este ceva de reținut. Următorul algoritm nu compensează acest lucru.

Nu sunt sigur că acest lucru este exact ceea ce doriți, dar acesta este un mod de generare aleatorie a valorilor de culoare care nu se repetă:

(atenție, pseudo-cod inconsistent)

//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);
      }
   }
}

Un mod în care puteți optimiza acest lucru pentru o vizibilitate mai bună ar fi să comparați distanța dintre fiecare culoare nouă și toate culorile din matrice:

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);
}

Dar această abordare ar încetini semnificativ algoritmul tău.

O altă modalitate ar fi să eliminăm întâmplările și să trecem sistematic la fiecare 4 valori și să adăugăm o culoare unei matrice în exemplul de mai sus.

0
adăugat

Nu este, de asemenea, un factor care vă ordonă să configurați culorile?

Ca și cum ați folosi ideea Dillie-Os, trebuie să amestecați culorile cât mai mult posibil. 0 64 128 256 este de la unul la altul. dar 0 256 64 128 într-o roată ar fi mai "îndepărtată"

Are vreun sens?

0
adăugat

Unele resurse conexe:

ColorBrewer - Sets of colours designed to be maximally distinguishable for use on maps.

Escaping RGBland: Selecting Colors for Statistical Graphics - A technical report describing a set of algorithms for generating good (i.e. maximally distinguishable) colour sets in the hcl colour space.

0
adăugat
Escaping RGBland este o necesitate de citire a referințelor pentru alegerea paletelor de culori perceptual distincte.
adăugat autor Drake Guan

Iată câteva coduri pentru alocarea uniformă a culorilor RGB în jurul unei roți de culoare HSL cu luminozitate specificată.

class cColorPicker
{
public:
    void Pick( vector&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&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(rm1 * 255);
}

int _tmain(int argc, _TCHAR* argv[])
{
    vector 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;
}
0
adăugat
nu când nu înțeleg toate lucrurile care schimbă biții, printre altele:
adăugat autor CodeGuy
dacă aș vrea să menționez că culorile sunt distincte de culoarea de fundal pe care o furnizez?
adăugat autor CodeGuy
AFAIK este simplu să codul de port de la C la Java
adăugat autor ravenspoint
Am furnizat adrese URL care se leagă de explicațiile privind codul.
adăugat autor ravenspoint
Calculați distanța dintre culorile generate și culoarea de fundal. Nu utilizați culoarea cea mai apropiată de fundal.
adăugat autor ravenspoint
Acest lucru poate funcționa puțin, dar acest lucru va da rezultate slabe, CIELAB este mai bun
adăugat autor adrienlucca.wordpress.com

Ar fi mai bine să găsim culori la distanță maximă într-un spațiu de culori "perceptual uniform", de ex. CIELAB (folosind distanța Euclidiană între L *, a *, b * coordonează ca metrică a distanței) și apoi convertiți la spațiul de culori la alegere. Perceperea uniformității se realizează prin reglarea spațiului de culori pentru a aproxima non-linearitățile din sistemul vizual vizual uman.

0
adăugat
Aceasta este probabil cea mai bună soluție deoarece este destul de simplă. Cu toate acestea, există și alte formule de diferențiere de culoare, cum ar fi CIE2000 sau chiar CIECAM
adăugat autor adrienlucca.wordpress.com

Pentru a realiza "cele mai distinse" trebuie să folosim un spațiu de culoare perceptual ca Lab (sau orice alt spațiu de culoare liniar perceptual) și nu RGB. De asemenea, putem cuantifica acest spațiu pentru a reduce dimensiunea spațiului.

Generați spațiul 3D complet cu toate intrările cantitative posibile și executați algoritmul K-means cu k = N . Centrele / "mijloacele" rezultate ar trebui să fie aproximativ cele mai distincte.

0
adăugat

Știu acest lucru un post vechi, dar l-am găsit în timp ce caută o soluție PHP la subiect și în cele din urmă a venit cu o soluție simplă:

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] 
    } 
}

Așa că apelați funcția random_color () unde $ i identifică culoarea, $ n numărul de culori posibile, $ saturația saturației și $ br luminozitatea.

0
adăugat
Puteți să explicați ce este "i" în acest caz? Întrebarea a cerut numere N. Care este paramaterul "i"?
adăugat autor CodeGuy
Văd! Multumesc pentru explicatie. Încă un lucru ... orice sugestie pentru ce să fac dacă am o culoare de fundal și vreau să fiu la fel de departe de cât posibil pentru toate culorile?
adăugat autor CodeGuy
Pe random_color () , $ i este "semințele" pentru a genera nuanța, ar trebui să fie un număr de la 0 la $ n . introducerea fără sămânță (NULL), funcția alege una aleatoare. $ n reprezintă cantitatea de culori posibile pentru o anumită saturație și luminozitate, adică numărul de culori din paletă. De fapt, divizăm gradele de nuanță 360 în $ n și folosim $ i ca multiplicator. Cu alte cuvinte, $ n mai mare vă va oferi mai multe culori, mai mici $ n vă va oferi mai puține cu
adăugat autor Mauro
Trebuie să adăugați 180 de grade la nuanța culorii dvs., menținând saturația și valoarea. Postați o nouă întrebare pentru aceasta, lipiți linkul aici și vă voi explica mai departe!
adăugat autor Mauro