66


23

カラーホイール作成機能

これは私が何度も疑似的に解いたものであり、そのための解決策を全く見つけたことがない。

問題は、「N」がパラメータである場合に可能な限り区別可能な「N」色を生成する方法を思いつくことである。

8 Answer


24


これについて私が最初に考えたのは、「お互いの距離を最大にするような空間にN個のベクトルを生成する方法」です。

あなたは、RGB(あるいは色空間の基礎を形成するあなたが使う他のスケール)が単なるベクトルであることがわかります。 ランダムポイントピッキングをご覧ください。 最大化された一連のベクトルを取得したら、後でそれらをハッシュテーブルなどに保存して、ランダムに回転させて、相互に最大限離れた色をすべて取得できます。

この問題についてさらに考えてみると、おそらく(0,0,0)→(255,255,255)の辞書式に、線形的に色をマッピングしてから均等に配色することをお勧めします。

これがどの程度うまくいくのか私には本当にわかりませんが、それ以来、私たちに言わせてください:

n = 10

16777216色(256 ^ 3)あります。

辞書的に索引付けされたcolor.imageを見つけるために Buckles Algorithm 515を使うことができます。 stack.imgur.com/gEuCs.gif[\frac \ {\ binom \ {256 ^ 3} \ {3}} \ {n} * i] あなたはおそらくオーバーフローを避けるためにアルゴリズムを編集しなければならないでしょう、そしておそらく若干のマイナーなスピード改善を追加するでしょう。


17


「知覚的に均一な」色空間において最大に離れた色を見つけることが最良であろう。 CIELAB(L *、a *、b *座標間のユークリッド距離を距離メトリックとして使用)してから、選択した色空間に変換します。 知覚的均一性は、人間の視覚系における非線形性に近似するように色空間を微調整することによって達成される。


7


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

http://colorbrewer.org[ColorBrewer]  - 地図上で使用するために最大限に区別できるように設計された色のセット。
http://epub.wu-wien.ac.at/dyn/openURL?id=oai:epub.wu-wien.ac.at:epub-wu-01_c87[RGBランドの統計化:統計的グラフィックスの色の選択]  - テクニカル財を生み出すための一連のアルゴリズム(すなわち、 hcl色空間の中で最大に識別可能な)色セット。


6


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

クラスcColorPicker {public:void Pick(vector

HSLカラーホイールの周りに均等にRGBカラーを割り当てる

@param [out] v_picked_cols RGB形式の色ベクトル@param [in]必要な色の数を数える@param [in]明るい0はすべて黒、100はすべて白、デフォルトは50

http://epub.wu-wien.ac.at/dyn/virlib/wp/eng/mediate / epub-wu-01_c87.pdf?ID = epub-wu-01_c87のFig 3に基づく

* /

void cColorPicker :: Pick(vector

HSLからRGBに換算

http://www.codeguru.com/code/legacy/gdi/colorapp_src.zipに基づいて

* /

DWORD cColorPicker :: HSL2RGB(int h、int s、int l){DWORD ret = 0;符号なしchar r、g、b。

フロート飽和= s / 100.0f。フロート輝度= 1 / 100.f。 float hue =(float)h;

if(彩度== 0.0){r = g = b =符号なしchar(輝度* 255.0)。 } else {float rm1、rm2;}

(輝度≦0.5f)rm2 =輝度輝度×彩度の場合。そうでなければ、rm2 =輝度彩度 - 輝度×彩度。 rm1 = 2.0f×輝度−rm2。 r = ToRGB1(rm1、rm2、色相120.0f)。 g = ToRGB1(rm1、rm2、色相)。 b = ToRGB1(rm1、rm2、色相−120.0f)。 }

ret =((DWORD)(((BYTE)(r)|(WORD)((BYTE)(g))<< 8))|((((DWORD)(BYTE)(b))<< 16)) ;

retを返す。 }

unsigned char cColorPicker :: ToRGB1(float rm1、float rm2、float rh){if(rh> 360.0f)rh  -  = 360.0f;そうでなければ(rh <0.0f)rh = 360.0fである。

rh <60.0fの場合、rm1 = rm1(rm2 − rm1)* rh / 60.0fである。そうでない場合(rh <180.0f)、rm1 = rm2。そうでない場合(rh <240.0f)、rm1 = rm1(rm2 − rm1)*(240.0f − rh)/ 60.0fである。

static_cast(rm1 * 255)を返します。 }

int _tmain(int argc、_ TCHAR * argv []){vector myCols; cColorPicker colpick; colpick.Pick(myCols、20); (int k = 0; k <(int)myCols.size(); k)printf( "%d:%d%d%d \ n"、k 1、(myCols [k]

0を返します。 }


5


それはあなたが色を設定する順序も要因ではないですか?

Dillie-Osのアイデアを使うのと同じように、できるだけ色を混ぜる必要があります。 0 64 128 256は1から次へです。 しかし、ホイールの0 256 64 128はもっと「離れて」いるでしょう

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


2


私は、人間の目では4つ以下の値を区別できないところを読んでいます。 これは覚えておくべきことです。 次のアルゴリズムはこれを補正しません。

これがまさにあなたが望むものであるかどうか私にはわかりませんが、これは非繰り返しカラー値をランダムに生成するための一つの方法です:

(注意してください、先に矛盾する疑似コード)

//colors entered as 0-255 [R, G, B]
colors = []; //使用する最終色を保持します。rand = new Random();

//assumes n is less than 16,777,216
randomGen(int n){while(len(colors)<n){//各色について0,255の間の乱数を生成する。newRed = rand.next(256); newGreen = rand.next(256); newBlue = rand.next(256); temp = [newRed、newGreen、newBlue]; // tempがcolorsにない場合にのみ、新しい色を配列に追加します。{colors.append(temp);} }}}

より見やすくするためにこれを最適化できる1つの方法は、新しい各色と配列内のすべての色の間の距離を比較することです。

カラーアイテム{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.
dist <NUMBERで温度が色ではない場合{colors.append(temp);} }

しかし、この方法ではアルゴリズムが大幅に遅くなります。

もう1つの方法は、ランダムさを無視し、4つの値ごとに体系的に調べて、色を配列に追加することです。


1


私はこれが古い記事であることを知っていますが、このトピックに対するPHPの解決策を探している間に見つけました。そして最後に簡単な解決策を思いついたのです。

関数random_color($ i = null、$ n = 10、$ sat = .5、$ br = .7){$ i = is_null($ i)? mt_rand(0、$ n):$ i; $ rgb = hsv2rgb(配列($ i *(360 / $ n)、$ sat、$ br)); ($ i = 0; $ i <= 2; $ i)$ rgb [$ i] = dechex(ceil($ rgb [$ i])); implode( ''、$ rgb)を返します。 }

関数hsv2rgb($ c){list($ h、$ s、$ v)= $ c; if($ s == 0)が配列($ 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


「最も識別可能」なものを実現するには、RGBではなく、Lab(またはその他の知覚的に線形の色空間)のような知覚的な色空間を使用する必要があります。 また、このスペースを量子化してスペースのサイズを減らすこともできます。

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