Functie voor het creëren van kleur wielen

stemmen
63

Dit is iets wat ik heb-pseudo opgelost vele malen geweest en heb nooit echt een oplossing voor gevonden.

Het probleem is om te komen met een manier om het genereren van Nkleuren, die zo onderscheiden als mogelijk wanneer Neen parameter.

De vraag is gesteld op 01/08/2008 om 19:42
bron van user
In andere talen...                            


8 antwoorden

stemmen
1

Ik heb ergens gelezen het menselijk oog kan geen onderscheid maken tussen minder dan 4 waarden uit elkaar. Dus dit is iets om in gedachten te houden. De volgende algoritme niet compenseren.

Ik weet niet of dit is precies wat je wilt, maar dit is een manier om willekeurig te genereren niet-herhalende kleurwaarden:

(Let op, inconsistent pseudo-code vooruit)

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

Een manier kon je dit voor een betere zichtbaarheid te optimaliseren zou zijn om de afstand te vergelijken tussen elke nieuwe kleuren en met alle kleuren in de array:

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

Maar deze aanpak zou aanzienlijk vertragen uw algoritme.

Een andere manier zou zijn om de willekeur schroot en systematisch gaan door elke 4 waarden en voeg een kleur aan een array in het bovenstaande voorbeeld.

antwoordde op 01/08/2008 om 20:36
bron van user

stemmen
3

Is het niet ook een factor welke volgorde je het opzetten van de kleuren?

Net als je Dillie-Os idee gebruiken, moet u de kleuren zo veel mogelijk te mengen. 0 64 128 256 is van de ene naar de volgende. maar 0 256 64 128 in een rolstoel zou meer "apart" zijn

Is dit zinvol?

antwoordde op 02/08/2008 om 19:16
bron van user

stemmen
23

Mijn eerste gedachte hierover is "hoe N-vectoren in een ruimte die afstand te maximaliseren van elkaar te genereren."

Je kunt zien dat de RGB (of een andere schaal die u gebruikt die een basis in kleurruimte vormt) zijn slechts vectoren. Neem een kijkje op Random Point Picking . Zodra u een set van vectoren die uit elkaar worden gemaximaliseerd, kunt u ze opslaan in een hash tabel of iets voor later, en alleen het uitvoeren van willekeurige rotaties op hen om alle kleuren die u wenst die maximaal uit elkaar te krijgen!

Het denken over dit probleem, zou het beter zijn om de kleuren in kaart op een lineaire manier, eventueel (0,0,0) → (255255255) lexicografisch, en vervolgens verspreiden ze gelijkmatig.

Ik weet echt niet hoe goed dit zal werken, maar het moet, omdat, laten we zeggen:

n = 10

we weten dat we hebben 16777216 kleuren (256 ^ 3).

We kunnen gebruik maken van Buckles algoritme 515 naar de lexicografisch geïndexeerde kleur te vinden. \ Frac {\ Binom {256 ^ 3} {3}} {n} * i. U zult waarschijnlijk moeten het algoritme om overflow te vermijden en waarschijnlijk doe er wat kleine snelheidsverbeteringen bewerken.

antwoordde op 02/08/2008 om 20:03
bron van user

stemmen
17

Het beste zou zijn om kleuren maximaal verre in een "perceptueel uniform" kleurruimte, zoals CIELAB (met behulp van Euclidische afstand tussen de L *, a *, b * coördinaten als je afstand metric) en vervolgens converteren naar de kleurruimte van uw keuze. Perceptuele uniformiteit wordt verkregen door het instellen van de kleurruimte van de niet-lineariteiten benaderen in het menselijke visuele systeem.

antwoordde op 12/09/2008 om 20:00
bron van user

stemmen
7

Sommige gerelateerde bronnen:

ColorBrewer - Sets van kleuren ontworpen om maximaal te onderscheiden voor gebruik op kaarten zijn.

Escaping RGBland: Kleuren selecteren voor de Statistiek Graphics - een technisch rapport beschrijven van een set van algoritmen voor het genereren van goede (dat wil zeggen maximaal te onderscheiden) kleur sets in de hcl kleurruimte.

antwoordde op 18/09/2008 om 17:01
bron van user

stemmen
6

Hier is een code om RGB-kleuren gelijkmatig verdelen rond een HSL kleurenwiel van gespecificeerde helderheid.

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;
}
antwoordde op 27/09/2008 om 17:39
bron van user

stemmen
1

Ik weet dat dit een oud bericht, maar ik vond het terwijl op zoek naar een PHP oplossing voor het onderwerp en uiteindelijk kwam met een eenvoudige oplossing:

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

Dus gewoon bellen met de functie random_color (), waar $ i identificeert de kleur, $ n het aantal mogelijke kleuren, $ zat de verzadiging en $ BR de helderheid.

antwoordde op 19/10/2011 om 02:58
bron van user

stemmen
0

Om dat te bereiken "meest onderscheiden" moeten we een perceptuele kleurruimte zoals Lab (of een andere perceptuele lineaire kleurruimte) en niet RGB gebruiken. Ook kunnen we deze ruimte quantiseren om de grootte van de ruimte te verminderen.

Genereer de volledige 3D-ruimte met alle mogelijke gekwantiseerde data en uitvoeren van de K-means algoritme k=N. De resulterende centra / "betekent" moet ongeveer meeste distinguishabl van elkaar.

antwoordde op 07/02/2014 om 18:43
bron van user

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