41

说 n = 100; 如何生成 100 种视觉上不同的颜色?这在数学上可能吗?

4

6 回答 6

46

是的。定义独特是遵循颜色空间的产物,然后当我们说最大程度不同的颜色时,我们的意思是说尽可能远离所有其他颜色的颜色。但由于色彩空间没有改变,答案也不会改变。并且实施更适合人眼的东西以及人眼如何看待颜色(如 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 作为图像。

最大距离

(从左到右)(从上到下)。如果您确保每种颜色在颜色空间内尽可能等距,您可能可以获得更多不同的颜色。该查找表将每种附加颜色与所有先前颜色最大程度地区别开来,而不是在开始时指定 N 然后映射出颜色空间。所以是的,蛮力和高级颜色距离算法,您将自己制作相同的颜色集。在一天左右的时间里。


如果您确实设置列表并使它们等距,则可以在不同颜色之间获得不同的数字,例如, 5 种颜色以 5 种颜色击败默认列表,该列表在 min_delta_max 53.2 和 min_delta_max 61.5

或者列表中的颜色10色表,#156FC3 #165859 #24C4FF #30A581 #957D5C #213E02 #DE9AF5 #68D840 #6E0062 #C25B77 超出了预计算列表中的前十个元素。

如果你想试试这个: https ://gist.github.com/tatarize/a483db49993e6e0e994ad82ba3e2a22e

可以编辑为 take num_of_colors,您可以长时间运行它并获得一组颜色,这些颜色应该具有较低的整体 min_delta_max (列表中任意两种颜色之间的最大最大最小距离)。您仍然需要一个预编译列表。

于 2013-11-30T08:18:12.760 回答
37

编辑:

我在这方面没有任何专业知识,我的数学技能相当平均。但我认为这个问题的解决方案比这里的许多答案建议的更复杂和有趣,因为我最近尝试做类似的事情但没有找到解决方案。

色差

对颜色的感知当然是主观的,但人类之间存在显着的一致性。例如,我们都可以同意红色、绿色和蓝色是非常不同的颜色,甚至色盲的人也同意黑色和白色是非常不同的。

RGB

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

RGB色差

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

  1. red (1, 0, 0)和 red (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, 1, 0)和洋红色(1, 0, 1)与白色(1, 1, 1)的距离1也相同,这似乎也没有任何意义:

白底黄和洋红

HSL 和 HSV

我认为可以安全地假设HSL 和 HSV 配色方案的模拟指标存在相同的问题。这些配色方案不是为比较颜色而设计的。

CIEDE2000

幸运的是,科学家们已经在尝试找到一种比较颜色的好方法。他们想出了一些复杂的方法,最新的方法是CIEDE2000

CIEDE2000

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

该指标考虑了人类的感知,例如我们似乎无法很好地辨别蓝色阴影的事实。所以我会说我们使用它作为我们的色差函数。

颜色选择算法

天真的解决方案

一些答案建议了以下算法

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

该算法存在一些问题:

  1. 颜色的间距不是最佳的。如果我们将颜色想象成一条线上的数字,三个数字的最佳间距将是这样的:

    |a-----b-----c|

    在不移动 a、b 和 c 的情况下在其中添加一个额外的数字显然比重新排列所有颜色更糟糕。

  2. 该算法不保证终止。如果列表中的现有颜色没有足够的颜色怎么办?循环将永远继续

适当的解决方案

嗯..我没有。

于 2010-02-24T18:17:34.097 回答
6

100 是很多颜色,但您可以通过在 HSB 或 HSL 空间中尽可能稀疏地分布它们来做到这一点;用 RGB 做这件事可能很困难。

例如,您可能决定使用 10 种不同的色调、4 种不同的饱和度和 3 种不同的亮度设置,这将提供多达 120 种颜色。您需要仔细选择饱和度和亮度值;人眼是复杂而令人困惑的传感器。如果您将色彩空间视为一个锥形,您可能需要在每个亮度/饱和度级别上使用不同数量的色调。

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

于 2010-02-24T18:11:58.287 回答
4

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

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

在这里这里查看我的答案。

如果您的 N 非常大,因此颜色在视觉上并不明显,那么您可以在此时重新迭代所有相同的色调并更改其他组件以改变饱和度或亮度。所以基本上你可以使用最大数量的色调值,一旦达到这个值,你就可以用不同的饱和度或亮度重新开始。

于 2010-02-24T18:11:44.143 回答
2

不是您的问题的答案,但是,如果n具有最大值并且您的应用程序允许它,您可以使用预定义的颜色列表,如下所示:

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

一个优点是您可以在工具提示中为色盲人士显示一个人类可读的颜色名称。

于 2010-02-24T18:31:19.737 回答
1

对于初学者,不要使用 RGB 空间;很难为这个问题找到更糟糕的色彩空间。(取决于您是使用显示颜色还是打印颜色,您可能会有大量无法区分的颜色,接近黑色或接近白色。)

如果您使用 Lab 空间,则有感知颜色模型(CIE 1996?和 CIE 2000)用于测量颜色的视觉接近度(分别用于打印和显示)。

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

虽然我建议将颜色空间的轴平均划分(比如分成 8 个)并将其用作初始点,这比任何随机过程都要有效得多。当然,您只需要将任何点与其邻居进行比较(并且仅当它们已经在集合中时),这将为您节省大量比较。

于 2010-02-24T19:19:31.883 回答