Funzione per la creazione di ruote di colore

Questo è qualcosa che ho pseudo-risolto molte volte e non ho mai trovato una soluzione.

Il problema è quello di trovare un modo per generare N colori, che sono distinguibili dove N è un parametro.

  • Ultimo ho controllato JFreeChart ha questo preciso algoritmo e come è open source, è possibile controllare ciò che fa. So che i colori non sembrano essere distribuite casualmente lungo il cerchio o una sfera, ma piuttosto la scelta più specifico.
InformationsquelleAutor Louis Brandy | 2008-08-01



8 Replies
  1. 24

    Il mio primo pensiero è “come generare N vettori in uno spazio di massimizzare la distanza dagli altri”.

    Si può vedere che la RGB (o qualsiasi altra scala che si utilizza, che costituisce una base in spazio colore) sono solo vettori. Date un’occhiata a Casuale Punto Di Raccolta. Una volta che si dispone di un insieme di vettori che sono massimizzati a parte, si possono salvare in una tabella hash o qualcosa per dopo, e solo eseguire rotazioni casuali su di loro per ottenere tutti i colori che volete che siano massimamente distanti l’uno dall’altro!

    A pensare a questo problema di più, sarebbe meglio per mappare i colori in modo lineare, forse (0,0,0) → (255,255,255) lexicographically, e poi distribuirli in modo uniforme.

    Io davvero non so come funzioni, ma dovrebbe in quanto, diciamo:

    n = 10
    

    sappiamo di avere 16777216 colori (256^3).

    Possiamo utilizzare Fibbie Algoritmo 515 per trovare il lexicographically in scala di colore.Funzione per la creazione di ruote di colore. Probabilmente dovrete modificare l’algoritmo per evitare overflow e probabilmente aggiungere alcuni piccoli miglioramenti di velocità.

    • Questo è sbagliato perché lo spazio colore RGB non è percettivamente uniforme
    • Sono d’accordo che logico. RGB soprattutto rende il viola e l’arancione ibridi e relativamente rarey rende, blu, verde, ibridi… la scala di colore è uniforme, infra rosso al blu profondo, in modo da scegliere i punti equidistanti lungo di esso. bisogno di un arcobaleno in base algo.
    • Si prega di considerare upvoting/dopo la StackExchange Teoria del Colore il sito: area51.stackexchange.com/proposals/110687/color-theory
  2. 18

    Sarebbe meglio trovare colori al massimo lontane in un “percettivamente uniforme” spazio colore, ad esempio CIELAB (utilizzando la distanza Euclidea tra L*, a*, b* coordinate come la distanza metrica) e quindi la conversione di spazio colore della vostra scelta. Percettivi l’uniformità è ottenuto modificando lo spazio per approssimare la non-linearità del sistema visivo umano.

    • Questa è probabilmente la migliore soluzione è abbastanza semplice. Tuttavia ci sono altri colori-differenza formule da considerare, come CIE2000 o anche CIECAM
  3. 8

    Alcune risorse:

    ColorBrewer – Set di colori progettato per essere al massimo distinguibili per l’uso su maps.

    La fuga RGBland: Selezione di Colori per Grafici Statistici – Una relazione tecnica che descrive un insieme di algoritmi per la generazione di buono (cioè al massimo distinguibili) colore imposta in hcl spazio colore.

    • La fuga RGBland è un must da leggere di riferimento per la raccolta di percettivamente distinguibili tavolozze di colori.
  4. 7

    Qui è un po ‘ di codice per assegnare i colori RGB in modo uniforme intorno ad una ruota di colori HSL specificato di 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( 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;
    }
    
    • AFAIK è semplice porting del codice da C++ a Java
    • non quando non capisco tutta l’spostamento di bit di roba, tra le altre cose :/
    • Ho fornito Url spiegazioni di quello che fa il codice.
    • cosa succede se voglio comprendere che i colori essere distinto da un colore di sfondo ho a disposizione?
    • Calcolare la distanza tra le generata colori e il colore di sfondo. Non utilizzare il colore che più si avvicina al vostro sfondo.
    • Che sarà forse un po ‘ di lavoro, ma questo darà scarsi risultati, CIELAB è meglio

  5. 3

    Non è anche un fattore che fine hai impostato i colori?

    Come se si utilizzano Dillie-Os idea è bisogno di mescolare i colori, per quanto possibile.
    0 64 128 256 è da uno all’altro. ma 0 64 128 256 in una ruota sarebbe più “oltre”

    Questo ha senso?

  6. 1

    Ho letto da qualche parte che l’occhio umano non può distinguere tra meno di 4 valori oltre. quindi, Questo è qualcosa da tenere a mente. Il seguente algoritmo non compensare questo.

    Io non sono sicuro che questo è esattamente ciò che si vuole, ma questo è un modo per generare in modo casuale senza ripetizione valori di colore:

    (attenzione, incoerente pseudo-codice in avanti)

    //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 modo per ottimizzare questo per una migliore visibilità sarebbe quello di confrontare la distanza tra ogni nuovo colore e tutti i colori a 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);
    }
    

    Questo approccio, però, rallentare in modo significativo il proprio algoritmo.

    Un altro modo sarebbe quello di rottami di casualità e sistematicamente passare attraverso ogni 4 valori e aggiungere un colore a una matrice a dell’esempio precedente.

  7. 1

    So che questo vecchio post, ma l’ho trovato mentre cercavo una soluzione PHP per l’argomento e, infine, è venuto con una soluzione semplice:

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

    Quindi basta chiamare il random_color funzione() dove $mi identifica il colore, $n il numero di colori possibili, $sat la saturazione e $br luminosità.

    • Si può spiegare ciò che “io” è in questo caso? La domanda per N numeri. Che cosa è l ‘ “io” parametro?
    • Su random_color(), $i il “seme” per generare la tonalità, dovrebbe essere un numero da 0 a $n, se si ingresso semi (NULL), la funzione preleva uno casuale. $n è la quantità di colori possibili per un dato saturazione e la luminosità, cioè il numero di colori nella tavolozza. Siamo fondamentalmente la suddivisione 360 tonalità gradi in $n e l’utilizzo di $i come moltiplicatore. In altre parole, più $n vi darà più colori, inferiore $n avrà meno colori, ma più diverse l’una dall’altra. $i identificare il colore e sarà sempre la stessa, se si continua a utilizzare questa funzione. Spero che aiuta.
    • Io vedo! Grazie per la spiegazione. Ancora una cosa…qualche suggerimento su cosa fare, se ho un colore di sfondo e voglio essere lontano da quella possibile per tutti i colori?
    • È necessario aggiungere 180 gradi per la tonalità del tuo colore di mantenere la saturazione e valore. Postare una nuova domanda per questo, incolla il link qui e ti spiego di più!
  8. 0

    Per ottenere “più distinguibili” abbiamo bisogno di usare un percettiva dello spazio colore come Laboratorio (o qualsiasi altro percettivamente spazio colore lineare) e non RGB. Inoltre, siamo in grado di quantizzare questo spazio per ridurre le dimensioni dello spazio.

    Generare l’intero spazio 3D con tutti i possibili quantizzati voci ed eseguire l’algoritmo K-medie con k=N. La risultante centri/”significa” dovrebbe essere di circa più distinguishabl l’una dall’altra.

Lascia un commento