如何为任何自然数n生成n种不同的颜色?

说n = 100; 如何生成100个视觉上不同的颜色? 这在math上是可能的吗?

100有很多颜色,但是你可以通过在HSB或HSL空间中尽可能稀疏地分配它们来做到这一点; 在RGB中执行可能很困难。

例如,您可能会决定使用10种不同的色调,4种不同的饱和度以及3种不同的亮度设置,最多可以显示120种颜色。 您需要仔细select饱和度和亮度值; 人类的眼睛是复杂而混乱的传感器。 如果将颜色空间视为圆锥体,则在每个亮度/饱和度级别上可能需要不同数量的色调。

这里是HSB维基百科条目的链接。

是啊。 定义不同是一种推迟到一个颜色空间的产物,那么当我们说最大的不同的颜色时,我们所说的颜色是尽可能远离所有其他颜色的颜色。 但是由于色彩空间不变,答案不会改变。 并且实施更适合于人眼的事物,以及人类的眼睛如何像CIE-lab de2000色彩距离那样看到色彩,这使得所有的计算都变得困难,但是使得静态列表变得容易。 这里有128个条目。

private static final String[] indexcolors = new String[]{ "#000000", "#FFFF00", "#1CE6FF", "#FF34FF", "#FF4A46", "#008941", "#006FA6", "#A30059", "#FFDBE5", "#7A4900", "#0000A6", "#63FFAC", "#B79762", "#004D43", "#8FB0FF", "#997D87", "#5A0007", "#809693", "#FEFFE6", "#1B4400", "#4FC601", "#3B5DFF", "#4A3B53", "#FF2F80", "#61615A", "#BA0900", "#6B7900", "#00C2A0", "#FFAA92", "#FF90C9", "#B903AA", "#D16100", "#DDEFFF", "#000035", "#7B4F4B", "#A1C299", "#300018", "#0AA6D8", "#013349", "#00846F", "#372101", "#FFB500", "#C2FFED", "#A079BF", "#CC0744", "#C0B9B2", "#C2FF99", "#001E09", "#00489C", "#6F0062", "#0CBD66", "#EEC3FF", "#456D75", "#B77B68", "#7A87A1", "#788D66", "#885578", "#FAD09F", "#FF8A9A", "#D157A0", "#BEC459", "#456648", "#0086ED", "#886F4C", "#34362D", "#B4A8BD", "#00A6AA", "#452C2C", "#636375", "#A3C8C9", "#FF913F", "#938A81", "#575329", "#00FECF", "#B05B6F", "#8CD0FF", "#3B9700", "#04F757", "#C8A1A1", "#1E6E00", "#7900D7", "#A77500", "#6367A9", "#A05837", "#6B002C", "#772600", "#D790FF", "#9B9700", "#549E79", "#FFF69F", "#201625", "#72418F", "#BC23FF", "#99ADC0", "#3A2465", "#922329", "#5B4534", "#FDE8DC", "#404E55", "#0089A3", "#CB7E98", "#A4E804", "#324E72", "#6A3A4C", "#83AB58", "#001C1E", "#D1F7CE", "#004B28", "#C8D0F6", "#A3A489", "#806C66", "#222800", "#BF5650", "#E83000", "#66796D", "#DA007C", "#FF1A59", "#8ADBB4", "#1E0200", "#5B4E51", "#C895C5", "#320033", "#FF6832", "#66E1D3", "#CFCDAC", "#D0AC94", "#7ED379", "#012C58" }; 

这是第256个图像。

最大距离

(从左到右)(从上到下)。 如果确保每个颜色在颜色空间内尽可能等距,则可以获得更多不同的颜色。 该查找表将每个附加颜色select为与以前的所有颜色最大程度地不同,而不是在开始时指定N,然后映射出颜色空间。 所以是的,蛮力和一个高层次的颜色的平滑algorithm,你自己设置了相同的一组颜色。 在一天左右的过程中。

编辑:

我没有这方面的专业知识,而且我的math技能相当平均。 但是我认为这个问题的解决scheme比这里提供的许多答案更加复杂和有趣,因为我试图近期做类似的事情,并没有find解决scheme。

色差

颜色的感觉当然是主观的,但是人类之间有很大的一致性。 例如,我们都同意红色,绿色和蓝色是非常不同的颜色,甚至色盲的人也认同黑色和白色是非常不同的。

RGB

计算机系统中最常见的颜色表示是向量(r,g,b) ,它表示了一个简单的距离函数

RGB颜色差异

让我们把rgb的范围设为[0,1] ,看看它是如何工作的:

  1. 红色(1,0,0)和红色(1,0,0)的距离为0 ,这应该是显而易见的
  2. 红色(1,0,0)和黄色(1,1,0)的距离为1 ,小于距离
  3. 红色(1,0,0)和蓝色 0,0,1 sqrt(2) ,这是合理的

到现在为止还挺好。 然而,问题是蓝色和红色的距离与黑色(0,0,0)的距离相同,但是在看图像时,这似乎并不成立:

蓝色和红色在黑色

另外,黄色 1,1,0 和洋红色 1,0,1 都与白色 1,1,1 具有相同的距离1 ,这似乎也不合理:

黄色和洋红色在白色

HSL和HSV

我认为可以肯定的是HSL和HSV配色scheme的模拟指标有相同的问题。 这些配色scheme不用于比较颜色。

CIEDE2000

幸运的是,有科学家已经试图find比较颜色的好方法。 他们想出了一些精心制作的方法,最新的是CIEDE2000

CIEDE2000

(文章中描述的完整公式是巨大的

这个指标考虑到了人类的认知,就像我们似乎无法很好地辨别蓝色阴影一样。 所以我会说我们用这个作为我们的色差函数。

选色algorithm

天真的解决scheme

一些答案build议使用以下algorithm

 colors = [] for n in range(n): success=False while not success: new_color = random_color() for color in colors: if distance(color, new_color)>far_enough: colors.append(new_color) success = True break 

这个algorithm有一些问题:

  1. 颜色的间距不是最佳的。 如果我们将颜色想象成一条线上的数字,那么三个数字就会像这样被最佳地分开:

    |一个—– —– bÇ|

    在那里包装另外一个号码,而不用移动a,b和c,显然比重新排列所有的颜色更差。

  2. 该algorithm不保证终止 。 如果没有足够的颜色来形成列表中现有的颜色,该怎么办? 循环将永远持续下去

适当的解决scheme

那么..我没有一个。

您想要转换为HSL,然后遍历色相(H)的值,同时保持其他2个值不变。

对于从HSL转换回RGB的每个值。

在这里和这里看到我的答案。

如果你的N非常大,所以颜色看起来不是很明显,那么你可以在所有相同的色调上重新迭代,改变其他的组件来改变饱和度或亮度。 所以基本上你可以有一个最大数量的色调值使用,一旦命中,你可以重新开始不同的饱和度或亮度。

不是你的问题的答案,但是,如果n有一个最大值,你的应用程序允许它,你可以使用预定义的颜色列表,如:

http://en.wikipedia.org/wiki/List_of_colors

一个好处是,您可以在色盲患者的工具提示中显示人性化的颜色名称。

对于初学者,不要使用RGB空间; 这个问题很难find更糟的色彩空间。 (根据您使用的颜色是用于显示还是用于打印,您可能有大量的接近黑色或接近白色的难以区分的颜色。)

如果您使用实验室空间,则可以使用感知颜色模型(CIE 1996?和CIE 2000)来测量颜色的视觉紧密度(分别用于打印和显示)。

你不会说如果你要计算颜色一次并存储结果,或者如果它们需要重新计算(在这种情况下,如果它必须是确定性的)。 很明显,关于如何最好地生成这个集合的讨论将取决于这个。

虽然我会build议平均分割色彩空间的轴(比如说8),并用这些作为初始点比任何随机过程更有效率。 当然,你只需要比较任何点到它的邻居(只有当它们已经在集合中),这将为您节省大量的比较。