Funkce pro vytváření barevných kola

hlasů
63

To je něco, co jsem pseudo-vyřešil mnohokrát a nikdy zcela našel řešení.

Problém je přijít na způsob, jak generovat Nbarvy, které jsou jako rozlišitelné jak je to možné, pokud Nje parametr.

Položena 01/08/2008 v 19:42
zdroj uživatelem
V jiných jazycích...                            


8 odpovědí

hlasů
23

Moje první myšlenka na to, „jak generovat N vektorů v prostoru, které maximalizují vzdálenost od sebe.“

Můžete vidět, že RGB (nebo jakékoliv jiné měřítko použít, která tvoří základ v barevném prostoru) jsou jen vektorů. Podívejte se na Random Point vybírání . Jakmile budete mít sadu vektorů, které jsou od sebe maximalizované, můžete je uložit do tabulky hash, nebo něco na později, a právě provádět náhodné rotace na ně získat všechny barvy, které si přejí, aby se maximálně od sebe!

Přemýšlení o tomto problému více, bylo by lepší, aby zmapovat barvy lineárně, případně (0,0,0) → (255,255,255) lexikograficky, a pak je rovnoměrně.

Já opravdu nevím, jak dobře to bude fungovat, ale to by mělo, protože řekněme:

n = 10

Víme, že máme 16777216 barvy (256 ^ 3).

Můžeme použít přezky algoritmus 515 najít lexikograficky indexované barvy. \ Frac {\ Binom {256 ^ 3} {3}} {n} * i, Pravděpodobně budete muset upravit algoritmus, aby se zabránilo přetečení a zřejmě přidat některé drobné vylepšení rychlosti.

Odpovězeno 02/08/2008 v 20:03
zdroj uživatelem

hlasů
17

To by bylo nejlepší najít barvy, maximálně vzdálené do „perceptuálně jednotném barevném“, např CIELAB (pomocí Euklidovské vzdálenosti mezi L *, a *, b * koordinuje jako vzdálenost metrický) a následné převedení na barevném podle svého výběru. Perceptual uniformita je dosaženo laděním barevný sblížení nelinearity v lidského oka.

Odpovězeno 12/09/2008 v 20:00
zdroj uživatelem

hlasů
7

Některé příbuzné zdroje:

ColorBrewer - Sady barev, které mají být maximálně rozeznatelný pro použití na mapách.

Unikající RGBland: Výběr barvy pro statistické grafiky - technické zprávy popisující sadu algoritmů pro generování dobře (tj maximálně rozeznatelné) barevné sady v HCl barevném prostoru.

Odpovězeno 18/09/2008 v 17:01
zdroj uživatelem

hlasů
6

Tady je nějaký kód přidělit barvy RGB rovnoměrně kolem HSL barevného kola určeného světelnosti.

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;
}
Odpovězeno 27/09/2008 v 17:39
zdroj uživatelem

hlasů
3

Není to také faktor, který objednat nastavit barvy?

Stejně jako v případě použití Dillie-OS představu je třeba míchat barvy co nejvíce. 0 64 128 256 je od jednoho k druhému. ale 0 256 64 128 v kole bude více „od sebe“

Dává tohle smysl?

Odpovězeno 02/08/2008 v 19:16
zdroj uživatelem

hlasů
1

Vím, že to starý příspěvek, ale jsem zjistil, že při hledání řešení PHP k tématu a nakonec přišel s jednoduchým řešením:

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

Takže stačí zavolat funkci random_color (), kde $ i identifikuje barvu, $ n počet možných barev, $ seděl sytost a $ br jasu.

Odpovězeno 19/10/2011 v 02:58
zdroj uživatelem

hlasů
1

Někde jsem četl, lidské oko nedokáže rozlišit mezi méně než 4 hodnot od sebe. tak to je něco, co byste měli mít na mysli. Následující algoritmus nekompenzuje za to.

Nejsem si jist, že to je přesně to, co chcete, ale je to jediný způsob, jak náhodně generovat non-opakující se barevné hodnoty:

(Pozor, nekonzistentní pseudo-kódu dopředu)

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

Jeden způsob, jak byste mohli optimalizovat to pro lepší viditelnost by bylo srovnat vzdálenost mezi každou novou barvu a všechny barvy v poli:

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 tento přístup by výrazně zpomalit váš algoritmus.

Dalším způsobem, jak by bylo zrušit náhodnost a systematicky projít každé 4 hodnoty a přidat barvu do pole ve výše uvedeném příkladu.

Odpovězeno 01/08/2008 v 20:36
zdroj uživatelem

hlasů
0

K dosažení „Nejvíce rozlišitelný“ musíme použít percepční barevný prostor, jako je Lab (nebo jakýkoli jiný perceptuálně lineární barevný prostor) a nikoliv RGB. Také můžeme quantize tento prostor, aby se zmenšila velikost prostoru.

Generovat plnou 3D prostoru se všemi možnými kvantované záznamů a spusťte K-means algoritmus s k=N. Výsledné střediska / „znamená“ by měla být přibližně nejvíce distinguishabl od sebe navzájem.

Odpovězeno 07/02/2014 v 18:43
zdroj uživatelem

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