【问题标题】:Algorithm For Generating Unique Colors生成独特颜色的算法
【发布时间】:2010-11-13 04:28:54
【问题描述】:

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

我有一系列 ID 从 1 开始计数的对象。我想用一种不同的、美观的颜色来表示它们中的每一个,这种颜色不会轻易与相邻的颜色混淆。颜色不一定是随机的。我希望每次输入相同的 ID 时都得到相同的颜色。

【问题讨论】:

    标签: algorithm colors language-agnostic


    【解决方案1】:

    我已经检查了所有方法,解决了不止几种方法。最后是 CIEde2000 的蛮力,真的,你最好的选择只是一个静态列表。无论您做什么,您都无法获得超过 30 种具有良好清晰度的颜色。考虑到色盲和混淆线,你真的在​​做一些阻碍的事情。使用查找表并使用一些其他特征修改数据点,而不仅仅是颜色。

    #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
    

    【讨论】:

      【解决方案2】:

      您可以将 id 乘以 golden ratio (phi) 得到一个数字 0

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

      然后就是将该数字转换为颜色的问题,例如

      hue = floor(n * 256)
      
      【解决方案3】:

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

      How to Generate Random Colors Programmatically

      基本上你可以使用 HSV 颜色空间,设置一个固定的 Saturation 和 Value,并修改 Hue。当您知道您需要的颜色数量时,只需将色调的范围[0,1[ 以此分割即可。如果您不知道所需颜色的数量,您仍然可以使用黄金比例从这个空间中选择颜色。

      【讨论】:

      • @philmccull 我将其修改为仅通过更改色调来生成 30 种独特且视觉上不同的颜色。 jsfiddle.net/hCtc3/42
      • 技术不错。
      【解决方案4】:

      平面设计师知道,如果要在信息显示中使用大量相互靠近的颜色,则这些颜色在色彩空间中应该相对接近。饱和度或色调的小幅变化通常比大的跳跃要好 - 当涉及多种颜色时,人眼实际上发现在颜色距离不是很大时更容易吸收信息。

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

      【讨论】:

        【解决方案5】:

        可能元素的数量是否有合理的下限?一种快速简单的解决方案是使用项目的 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;
               }
            }
        }
        

        【讨论】:

        • 查看我的答案,了解如何避免预测 EXPECTED_MAX 并仍然获得均匀分布。
        【解决方案6】:

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

        示例:以下脚本选择 400 种不同的颜色,其中 0

        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()
        

        结果是

        这可以与 martinus 的答案 https://stackoverflow.com/a/5104386/1165155 或此线程中的其他答案结合使用。相比之下,以下示例在 hsl 颜色空间中,0

        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()
        

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

        【讨论】:

          【解决方案7】:

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

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

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

          【讨论】:

            猜你喜欢
            • 2010-10-20
            • 2011-03-09
            • 1970-01-01
            • 1970-01-01
            • 2013-02-23
            • 1970-01-01
            • 2012-01-03
            • 2015-05-16
            相关资源
            最近更新 更多