生成独特颜色的算法

时间:2009-07-22 21:08:20

标签: algorithm colors language-agnostic

我正在寻找能够生成一系列颜色的算法,以便颜色尽可能广泛地分布(因此它们不会轻易混淆)。

我有一系列具有从1开始计数的ID的对象。我想用不同的,美学上令人愉悦的颜色来表示这些对象,这些颜色不容易与其邻居混淆。颜色不一定是随机的。我想每次输入相同的ID时都会得到相同的颜色。

7 个答案:

答案 0 :(得分:23)

我已经检查了所有方法,解决了很多方法。最后用CIEde2000蛮力,真的,你最好的选择只是一个静态列表。无论你做什么,你都不能获得超过30种颜色,并且具有良好的清晰度。色盲的因素和混乱的线条,你真的在​​做一些阻碍。使用查找表并使用除颜色之外的其他一些特征修改数据点。

max difference color palette

#000000
#00FF00
#0000FF
#FF0000
#01FFFE
#FFA6FE
#FFDB66
#006401
#010067
#95003A
#007DB5
#FF00F6
#FFEEE8
#774D00
#90FB92
#0076FF
#D5FF00
#FF937E
#6A826C
#FF029D
#FE8900
#7A4782
#7E2DD2
#85A900
#FF0056
#A42400
#00AE7E
#683D3B
#BDC6FF
#263400
#BDD393
#00B917
#9E008E
#001544
#C28C9F
#FF74A3
#01D0FF
#004754
#E56FFE
#788231
#0E4CA1
#91D0CB
#BE9970
#968AE8
#BB8800
#43002C
#DEFF74
#00FFC6
#FFE502
#620E00
#008F9C
#98FF52
#7544B1
#B500FF
#00FF78
#FF6E41
#005F39
#6B6882
#5FAD4E
#A75740
#A5FFD2
#FFB167
#009BFF
#E85EBE

答案 1 :(得分:17)

您可以将id乘以golden ratio(phi)以得到数字0< = n< 1.您生成的所有数字往往均匀分布。

PHI = (1 + sqrt(5))/2
n = id * PHI - floor(id * PHI) 

然后将该数字转换为颜色,例如

hue = floor(n * 256)

答案 2 :(得分:10)

图形设计师知道,如果在信息显示中要使用很多颜色,那么颜色应该在颜色空间中相对接近。饱和度或色调的微小变化通常比大跳跃更好 - 当涉及许多颜色时,人眼实际上发现当颜色距离不是很大时,更容易吸收信息。

另外,不要忘记你的一些用户会失色。由于色盲的种类繁多,很难知道要避免哪种组合。也许其他人可以解决这个问题?

答案 3 :(得分:10)

我写了一篇关于同一主题的文章:

How to Generate Random Colors Programmatically

基本上,您可以使用HSV颜色空间,设置固定的饱和度和值,以及修改Hue。当您知道所需的颜色数量时,只需将Hue的范围[0,1[分开即可。如果您不知道所需颜色的数量,您仍然可以使用黄金比例从该空间中选择颜色。

答案 4 :(得分:7)

可能元素的数量是否具有合理的下限?一种快速简便的解决方案是使用项目的ID存储一系列颜色值。假设您的颜色数量相对较少,而且您确定不会超过一定数量的商品。

如果你想生成颜色而不是使用列表,那么使它们具有一致和正确外观的一个技巧就是使用HSB生成它们。预先定义亮度和饱和度,然后将色调值基于ID的某个函数(这可能是各种各样的事情,具体取决于您计划拥有多少ID,但将ID乘以某个量(并且当它超过时进行修改) 255!)是一个很好的粗略方法。使用这种方法,颜色将在饱和度和亮度方面全部“对齐”,但它们每个都有不同的颜色。

我在工作上有点无聊,所以我匆匆忙忙地解决了一个问题:

class HsbColor
{
    public int Hue { get; set; }
    public int Saturation { get; set; }
    public int Brightness { get; set; }

    public Color ToRGB
    {
        // left as exercise to the reader...
    }
}

public class Item
{


    public int Id { get; set; }
    private static const byte EXPECTED_MAX = 15;
    private static int HUE_FACTOR = 255 / EXPECTED_MAX;

    public HsbColor Color 
    {
       get {

         var color = new HsbColor() { Saturation = 175, Brightness = 175 };

         color.Hue = (Id * HUE_FACTOR) % 255;

         return color;
       }
    }
}

答案 5 :(得分:0)

我发现 hsluv 颜色空间对于随机选择颜色非常有用,而不是 hsl,因为在我看来,颜色分布更均匀。见https://www.hsluv.org/

示例:以下脚本选择 400 种不同的颜色,其中 0 <= 色调 <= 360 和 80 <= 饱和度 <= 100(在范围内均匀选择),并且亮度是基于 66 左右的正态分布选择的,标准为10的偏差:

import matplotlib.pyplot as plt
import numpy as np
from hsluv import hsluv_to_rgb

nrows, ncols = 20, 20

h = np.random.uniform(low=0, high=360, size=(nrows, ncols))
l = np.random.normal(loc=66, scale=10, size=(nrows, ncols))
s = np.random.uniform(low=80, high=100, size=(nrows, ncols))

image = np.dstack((h,s,l))
image = np.apply_along_axis(hsluv_to_rgb, 2, image)

plt.figure(figsize=(15,15))
plt.matshow(image, fignum=1)
plt.xticks([])
plt.yticks([])
plt.show()

结果是

enter image description here

这可以与 martinus 的答案 https://stackoverflow.com/a/5104386/1165155 或此线程中的其他答案结合使用。相比之下,以下示例在 hsl 颜色空间中,0 <= 色调 <= 1、0.4 <= 亮度 <= 0.6 和 0.9 <= 饱和度 <= 1:

import matplotlib.pyplot as plt
import numpy as np
from colormap.colors import hls2rgb

nrows, ncols = 20, 20

h = np.random.uniform(low=0, high=1, size=(nrows, ncols))
l = np.random.uniform(low=0.4, high=0.6, size=(nrows, ncols))
s = np.random.uniform(low=0.9, high=1, size=(nrows, ncols))

image2 = np.apply_along_axis(lambda color: hls2rgb(*color), 2, image)

plt.figure(figsize=(15,15))
plt.matshow(image2, fignum=1)
plt.xticks([])
plt.yticks([])
plt.show()

enter image description here

请注意,这里的亮度并不相同(蓝色和红色方块似乎比黄色或绿色方块更暗)。以下文章解释了原因:https://programmingdesignsystems.com/color/perceptually-uniform-color-spaces/

答案 6 :(得分:0)

我有一个简单的解决方案,它独特、稳定但可能很丑:

color_code = "#" + md5(unique_key_like_email).substring(0, 3)

MD5 可以方便地生成基于 16 个字符的 0-9+a-f,非常适合用于颜色索引。