用于创build色轮的function

这是我屡次伪解的东西,从来没有find一个解决scheme。 这是困在我身上。 问题是想出一种方法来生成N种颜色,尽可能区分N是参数。

我首先想到的是“如何在一个距离最远的空间生成N个向量”。 你可以看到,RGB(或者你使用的任何其他尺度在色彩空间中构成了一个基础)就是vector。 看看随机点挑选 。 希望这对你是个好开始! 一旦你有一组向量被最大化的一部分,你可以将它们保存在一个哈希表或其他东西,以后,只要执行随机旋转,以获得所有你想要的颜色彼此最大距离!

编辑:更多的思考这个问题,最好将线性庄园的颜色映射成按照字典顺序(0,0,0) – >(255,255,255),然后均匀分布。 我真的不知道这样做会有多好,但是应该说,

n = 10我们知道我们有16777216种颜色(256 ^ 3)。 我们可以使用bucklesalgorithm515来查找按字典索引的颜色。 \ frac {\ binom {256 ^ 3} {3}} {n} * i 。 你可能不得不编辑algorithm,以避免溢出,并可能添加一些小的速度改进。

最好在“知觉均匀”的颜色空间中find距离最远的颜色,例如CIELAB(使用L *,a *,b *坐标之间的欧几里得距离作为距离度量),然后转换为您select的颜色空间。 感知的一致性是通过调整色彩空间来逼近人类视觉系统中的非线性来实现的。

一些相关资源:

ColorBrewer – 一组颜色devise为在地图上最大程度地区分使用。

Escapeing RGBland:为统计graphicsselect颜色 – 一个技术报告,描述了一套在hcl色彩空间中生成好的(即最大可区分的)颜色集合的algorithm。

以下是一些代码,用于在指定亮度的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; } 

这是不是也是你设置颜色的一个因素?

就像如果你使用Dillie-O的想法,你需要尽可能地混合颜色。 0 64 128 256是从一个到下一个。 但0 256 64 128在一个车轮将更“分开”

这有道理吗?

我读过的地方人眼不能区分不到4个值相隔。 所以这是要记住的东西。 以下algorithm不能弥补这一点。

我不确定这正是你想要的,但这是随机生成非重复颜色值的一种方法:

(注意,前面提供的不一致的伪代码)

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

但是这种方法会显着减慢你的algorithm。

另一种方法是放弃随机性,并系统地遍历每个4个值,并在上面的例子中为数组添加颜色。

我知道这是一个旧的post,但我find了一个PHP解决scheme的主题,最后来到一个简单的解决scheme:

 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表示可能的颜色数量,$表示饱和度,$ br表示亮度。

为了实现“最明显的”,我们需要使用像Lab这样的感知色彩空间(或任何其他感知线性色彩空间)而不是RGB。 而且,我们可以量化这个空间来减小空间的大小。

用所有可能的量化条目生成完整的三维空间,并运行K k=N的K均值algorithm。 由此产生的中心/“手段”应该大致相互分开。

Interesting Posts