2008-08-01 7 views
61

これは私が何度も擬似的に解決したことであり、決して解決策を見いださなかったものです。それは私と一緒に固執しています。問題は、Nをパラメータとして可能な限り区別できるように、Nの色を生成する方法を考え出すことです。カラーホイールを作成する機能

+0

最後に私は[JFreeChart](http://www.jfree.org/jfreechart/)にこの正確なアルゴリズムがあることを確認しました。オープンソースなので、それが何であるかチェックすることができます。私が得た色は、円や球に沿ってランダムに配置されているのではなく、より具体的に選択されていることがわかります。 –

答えて

22

私が最初に考えたのは、「互いに距離を最大化空間でのNベクトルを生成する方法」です。 RGB(または色空間で基礎を形成する他のスケール)は単なるベクトルであることがわかります。 Random Point Pickingをご覧ください。これはあなたにとって良いスタートだと思っています!部品が最大化されたベクトルのセットを取得したら、それらをハッシュテーブルなどで後で保存し、無作為に回転させて、お互いに最大限離れているすべての色を得ることができます。

編集:もっとこの問題を考え、(0,0,0)おそらく、線形荘園の色をマップする方が良いだろう - 辞書順>(255,255,255)、その後、均等に分配します。

n = 10 私たちは16777216色(256^3)を持っていることを知っています。 buckles algorithm 515を使用して、辞書編集的に索引付けされた色を見つけることができます。 \frac {\binom {256^3} {3}} {n} * i。おそらくオーバーフローを避けるためにアルゴリズムを編集しなければならないかもしれませんし、恐らく軽度の改善がいくつか追加されるでしょう。

+1

RGB色空間が知覚的に一様ではないので、これは間違っています –

+0

私はそれが論理的に聞こえることに同意します。 RGBは主に紫とオレンジのハイブリッドを作り、比較的希少なものは青緑のハイブリッドを作ります...カラースケールは赤外線から濃い青まで均一ですので、それに沿って等間隔の点を選ぶ必要があります。虹をベースにした孤独が必要です。 –

+0

StackExchange Color Theoryサイトをアップアップ/フォローすることを検討してください。https://area51.stackexchange.com/proposals/110687/color-theory –

1

人間の目では4つ以下の値を区別することができません。そう、これは心に留めておくべきことです。次のアルゴリズムは、これを補償しません。

私は、これは正確に何をしたいですわからないんだけど、これはランダムに非反復カラー値を生成するための一つの方法である:

(先に、一貫性のない擬似コードを注意してください)

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

あなたがより良い可視性のためにこれを最適化する可能性が一つの方法は、それぞれの新しい色と、アレイ内のすべての色の間の距離を比較するために、次のようになります。

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

しかし、このアプローチは、significaうアルゴリズムの速度が低下することはありません。

別の方法は、ランダム性をスクラップし、体系毎に4つの値を通過し、上記の例では、アレイに色を追加することであろう。

3

色を設定する要素でもありませんか?

あなたはDillie-OSのアイデアを使用する場合は、可能な限り色をミックスする必要がありますように。 0 64 128 256は、次から次へと変化します。ホイール内の0 256 64 128はより離れているはずです

これは意味がありますか?この上

17

"知覚的に一様な"色空間、例えば、色空間で最も遠くにある色を見つけることが最もよいでしょう。 CIELAB(距離メトリックとしてL *、a *、b *座標の間のユークリッド距離を使用)し、選択した色空間に変換します。知覚的一様性は、人間の視覚系の非線形性を近似するために色空間を調整することによって達成される。

+0

これはおそらく最も簡単な解決策です。しかし、CIE2000やCIECAMのような他の色差式もあります。 –

7

いくつかの関連リソース:

ColorBrewer - マップ上での使用のために最大限に区別できるように設計された色のセット。

Escaping RGBland: Selecting Colors for Statistical Graphics - hcl色空間で良好な(すなわち、最大限に区別可能な)カラーセットを生成するための一連のアルゴリズムを説明する技術レポート。

+1

エスケープするRGBランドは、知覚的に区別できるカラーパレットを選ぶためのリファレンスを読むために必要です。 – Drake

6

指定された明るさのHSLカラーホイールの周りにRGBカラーを均等に割り当てるためのコードです。

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; 
} 
+2

AFAIK C++のコードをJava – ravenspoint

+0

に移植するのは簡単ですが、他のものの中でビットシフトのすべてを理解していないときではありません。/ – CodeGuy

+0

コードの説明にリンクするURLを提供しました。 – ravenspoint

1

私はこれに古いポストを知っているが、私はトピックにPHPソリューションを探している間にそれを発見し、最終的にはシンプルなソリューションに付属している:

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

は、だからどこrandom_color()関数を呼び出します$ iは色を、$ nは色の数を、$ satは彩度を、$ brは明るさをそれぞれ表します。

+0

"i"が何であるか説明できますか?質問はN個の数字を求めた。 "私"のパラメタは何ですか? – CodeGuy

+0

'random_color()'では、 '$ i'は色相を生成する"シード "で、0から' $ n'までの数値でなければなりません。シード(NULL)を入力しないと、関数はランダムなものを選択します。 '$ n 'は与えられた彩度と明るさ、すなわちパレット内の色数に対する可能な色の量である。基本的に、360度の色相度を '$ n'に分割し、' $ i'を乗数として使用しています。言い換えれば、 '$ n'を高くすると色が増え、' $ n'を小さくすると色は少なくなりますが、色はお互いに大きくなります。 '$ i'は色を識別し、この関数を使い続けると常に同じ色になります。私はそれが助けて欲しい – Mauro

+0

私は見る!説明ありがとう。もう一つは...私は背景色を持っていて、私は可能な限りすべての色のために遠くにいたい場合、何をすべきかについて何か提案しますか? – CodeGuy

0

「最も区別可能」を実現するには、Labではなく、RGB以外の知覚的に線形な色空間を使用する必要があります。また、この空間を量子化して空間のサイズを小さくすることもできます。

可能なすべての量子化されたエントリで完全な3D空間を生成し、k=NでK平均アルゴリズムを実行します。結果として生じる中心/「手段」は、お互いにほとんど区別されるべきである。

関連する問題