Funktion zum Erstellen von Farbrad

stimmen
63

Das ist etwas, was ich habe pseudo-gelöst oft und sind nie ganz eine Lösung gefunden.

Das Problem ist , einen Weg zu kommen zu erzeugen NFarben, die als unterscheidbar wie möglich sind , wo Nein Parameter ist.

Veröffentlicht am 01/08/2008 um 19:42
quelle vom benutzer
In anderen Sprachen...                            


8 antworten

stimmen
23

Mein erster Gedanke dazu ist „wie N-Vektoren in einem Raum zu erzeugen, den Abstand voneinander zu maximieren.“

Sie können sehen , dass die RGB (oder eine andere Skala Sie verwenden , die eine Basis im Farbraum bilden) sind nur Vektoren. Werfen Sie einen Blick auf beliebigen Punkt Picking . Sobald Sie eine Reihe von Vektoren, die auseinander maximiert sind, können Sie sie in einer Hash - Tabelle oder etwas für später speichern, und führen nur zufällige Drehungen auf sie alle Farben bekommen Sie wünschen , dass maximal voneinander entfernt sind!

Das Nachdenken über dieses Problem mehr, wäre es besser, die Farben in linearer Weise abzubilden, möglicherweise (0,0,0) → (255,255,255) lexikographisch und sie dann gleichmäßig verteilen.

Ich weiß wirklich nicht, wie gut das funktioniert, aber es sollte da, sagen wir:

n = 10

wir wissen, dass wir 16777216 Farben (256 ^ 3).

Wir können verwenden Buckles Algorithmus 515 die lexikographisch indiziert Farbe zu finden. \ Frac {\ binom {256 ^ 3} {3}} {n} i *. Sie werden wahrscheinlich den Algorithmus bearbeiten müssen , um Überlauf zu vermeiden und wahrscheinlich einige kleinere Verbesserungen in der Geschwindigkeit hinzuzufügen.

Beantwortet am 02/08/2008 um 20:03
quelle vom benutzer

stimmen
17

Es wäre am beste Farben maximal entfernten in einem „einheitlichen Eindruck vermittelt“ Farbraum, zB CIELAB (mit euklidischem Abstand zwischen L *, a *, b * Koordinaten als Abstand metric) zu finden und dann zu dem Farbraum Ihrer Wahl konvertieren. Perceptual Gleichförmigkeit wird durch Zwicken den Farb erreicht, die die Nichtlinearitäten in dem menschlichen Sehsystem zu nähern.

Beantwortet am 12/09/2008 um 20:00
quelle vom benutzer

stimmen
7

Einige verwandte Quellen an:

ColorBrewer - Sets von Farben für den Einsatz auf Karten maximal unterscheidbar zu sein.

Flüchten RGBland: Auswahl von Farben für Statistical Graphics - Einen technischen Bericht eine Reihe von Algorithmen zur Erzeugung von guten (dh maximal unterscheidbar) Farbsätzen in dem HCL Farbraum beschreibt.

Beantwortet am 18/09/2008 um 17:01
quelle vom benutzer

stimmen
6

Hier ist ein Code RGB-Farben gleichmäßig um ein HSL-Farbrad spezifizierter Helligkeit zuzuordnen.

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;
}
Beantwortet am 27/09/2008 um 17:39
quelle vom benutzer

stimmen
3

Ist es nicht auch ein Faktor, der Sie die Farben eingerichtet bestellen?

Wie, wenn Sie verwenden Dillie-O Idee müssen Sie die Farben so viel wie möglich mischen. 0 64 128 256 ist von einem zum nächsten. aber 0 256 64 128 in einem Rad wäre „apart“

Macht das Sinn?

Beantwortet am 02/08/2008 um 19:16
quelle vom benutzer

stimmen
1

Ich weiß, das eine alte Post, aber ich fand es während für eine PHP-Lösung zum Thema suchen und schließlich kam mit einer einfachen Lösung:

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

So rufen Sie die random_color () Funktion, wobei $ i die Farbe identifiziert, $ n die Anzahl der möglichen Farben, setzte $ die Sättigung und $ br die Helligkeit.

Beantwortet am 19/10/2011 um 02:58
quelle vom benutzer

stimmen
1

Ich habe irgendwo gelesen das menschliche Auge nicht auseinander zwischen weniger als 4 Werten unterscheiden kann. Das ist also etwas im Auge zu behalten. Der folgende Algorithmus sieht keinen Ausgleich dafür.

Ich bin mir nicht sicher, dass dies genau das ist, was Sie wollen, aber das ist ein Weg, um statistisch nicht wiederholende Farbwerte zu erzeugen:

(Vorsicht, inkonsistenten Pseudo-Code voraus)

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

Eine Möglichkeit, dies für eine bessere Sichtbarkeit optimieren könnte, wäre der Abstand zwischen jeder neuen Farbe zu vergleichen und alle Farben in der Reihe:

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

Aber dieser Ansatz würde Ihren Algorithmus deutlich verlangsamen.

Eine weitere Möglichkeit wäre die Zufälligkeit verschrotten und systematisch durch alle 4 Werte gehen und eine Farbe auf ein Array in dem obigen Beispiel hinzuzufügen.

Beantwortet am 01/08/2008 um 20:36
quelle vom benutzer

stimmen
0

Um das zu erreichen „die meisten unterscheidbar“ Wir brauchen einen wahrnehmbaren Farbraum wie Lab verwenden (oder anderen wahrnehmungs linearen Farbraum) und nicht RGB. Außerdem können wir diesen Raum quantisieren die Größe des Raumes zu verringern.

Generieren Sie den vollen 3D - Raum mit allen möglichen quantisiert Einträge und führen die K-Means - Algorithmus mit k=N. Die resultierenden Zentren / „bedeutet“ sollte etwa die meisten distinguishabl voneinander sein.

Beantwortet am 07/02/2014 um 18:43
quelle vom benutzer

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