Funkcja tworzenia koła kolorów

głosy
63

To jest coś, mam pseudo-rozwiązany wiele razy i nigdy nie znalazł rozwiązanie.

Problem polega na tym, aby wymyślić sposób, aby generować Nkolory, które są tak rozpoznawalne jako możliwe, gdy Njest parametrem.

Utwórz 01/08/2008 o 19:42
źródło użytkownik
W innych językach...                            


8 odpowiedzi

głosy
23

Moja pierwsza myśl na to „jak wygenerować N wektorów w przestrzeni, które maksymalizują odległości od siebie.”

Można zobaczyć, że RGB (lub jakakolwiek inna skala korzystania który tworzy podstawy w przestrzeni kolorów) są tylko wektory. Spójrz na losowo wybranym miejscu Picking . Gdy masz zbiór wektorów, które są największe od siebie, można je zapisać w tabeli mieszania lub coś na później, i po prostu wykonywać losowe obroty na nich, aby dostać wszystkie kolory pragnienie, które są maksymalnie od siebie!

Z myślą o tym problemie więcej, byłoby lepiej odwzorowują kolory w sposób liniowy, ewentualnie (0,0,0) → (255,255,255) leksykograficznie, a następnie rozprowadzić je równomiernie.

I naprawdę nie wiem, jak to będzie działać dobrze, ale powinien od, powiedzmy:

n = 10

wiemy, że mamy 16777216 kolorów (256 ^ 3).

Możemy użyć Buckles Algorithm 515 znaleźć leksykograficznie indeksowane kolor. \ Frac {\ Binom 256 ^ {3}, {3}} {n} * I, Prawdopodobnie będziesz musiał zmodyfikować algorytm, aby uniknąć przepełnienia i prawdopodobnie dodać kilka drobnych ulepszeń prędkości.

Odpowiedział 02/08/2008 o 20:03
źródło użytkownik

głosy
17

Byłoby najlepiej, aby znaleźć kolory maksymalnie odległe w „percepcyjnie jednolitego” przestrzenie kolorów, np CIELAB (przy użyciu odległości euklidesowej między L *, a *, b * koordynuje jako odległości metrycznej), a następnie konwersji do przestrzeni kolorów do wyboru. Percepcyjne jednorodność osiągnąć dostosowując kolorów, zbliżenie nieliniowości ludzkiego systemu wzrokowego.

Odpowiedział 12/09/2008 o 20:00
źródło użytkownik

głosy
7

Niektóre powiązane zasoby:

ColorBrewer - Zestawy kolorów zaprojektowanych być maksymalnie rozróżnialne do stosowania na mapach.

Cytowanie RGBland: Wybór kolorów dla grafiki statystycznych - raport techniczny opisujący zbiór algorytmów generowania dobre (czyli maksymalnie rozróżnialne) Ustawienie kolorów w przestrzeni barw HCl.

Odpowiedział 18/09/2008 o 17:01
źródło użytkownik

głosy
6

Oto kod przeznaczyć kolorów RGB równomiernie wokół koła kolorów HSL o określonej jasności.

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;
}
Odpowiedział 27/09/2008 o 17:39
źródło użytkownik

głosy
3

Nie jest to również czynnik, który kolejności ustawić kolory?

Podobnie jak w przypadku korzystania Dillie-Os pomysł trzeba mieszać kolory jak najwięcej. 0 64 128 256 jest od jednej do drugiej. a 0 256 64 128 w kole będzie bardziej „osobno”

Czy to ma sens?

Odpowiedział 02/08/2008 o 19:16
źródło użytkownik

głosy
1

Wiem, że to stary wpis, ale znalazłem go podczas szuka rozwiązania PHP do tematu i wreszcie przyszedł z prostego rozwiązania:

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

Więc po prostu wywołać funkcję random_color () gdzie $ i identyfikuje kolor, $ n liczbę możliwych kolorów, $ usiadł nasycenie i jasność $ br.

Odpowiedział 19/10/2011 o 02:58
źródło użytkownik

głosy
1

Czytałem gdzieś, że ludzkie oko nie jest w stanie odróżnić mniej niż 4 wartości od siebie. Jest to więc coś, aby pamiętać. Poniższy algorytm nie rekompensuje to.

Nie jestem pewien, że to jest dokładnie to, co chcesz, ale to jest jeden sposób, aby nie generować losowo powtarzające się wartości kolorów:

(Uwaga, niespójne pseudokod naprzód)

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

Jednym ze sposobów, można zoptymalizować to dla lepszej widoczności byłoby porównanie odległości pomiędzy każdym nowym kolorze i wszystkie kolory w tablicy:

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

Ale takie podejście znacznie spowolnić algorytmu.

Innym sposobem byłoby złom przypadkowość i systematycznie przechodzą co 4 wartości i dodać kolor do tablicy w powyższym przykładzie.

Odpowiedział 01/08/2008 o 20:36
źródło użytkownik

głosy
0

Aby osiągnąć „najbardziej odróżnia” musimy użyć percepcji przestrzeni barw jak laboratorium (lub jakiegokolwiek innego percepcyjnie liniowej przestrzeni kolorów), a nie RGB. Ponadto, możemy kwantyzacji tego miejsca, aby zmniejszyć rozmiar przestrzeni.

Generowanie pełnej przestrzeni 3D ze wszystkich możliwych skwantyzowanych wpisów i uruchomić K-oznacza algorytm k=N. Powstałe centra / „oznacza” powinna wynosić około najbardziej distinguishabl od siebie.

Odpowiedział 07/02/2014 o 18:43
źródło użytkownik

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