【问题标题】:Algorithm to randomly generate an aesthetically-pleasing color palette [closed]随机生成美观调色板的算法[关闭]
【发布时间】:2010-09-07 18:25:32
【问题描述】:

我正在寻找一种简单的算法来生成大量随机的、美观的颜色。所以没有疯狂的霓虹色,让人联想到粪便的颜色等。

我找到了解决这个问题的方法,但他们依赖于替代调色板而不是 RGB。 我宁愿只使用直接 RGB 而不是来回映射。这些其他解决方案也最多只能生成 32 种左右令人愉悦的随机颜色。

任何想法都会很棒。

【问题讨论】:

  • 您可以查看 HSL 和 HSV。
  • 这不是算法。
  • 我将添加评论,因为问题已关闭。我没有尝试过,但是尝试分形或程序方式会很有趣,使用即中点置换算法或变体 (lighthouse3d.com/opengl/terrain/index.php?mpd2) 或柏林噪声,而不是高度来混合颜色的 rgb 分量。
  • 看看我构建的调色板生成器及其源代码:hypejunction.github.io/color-wizard 您基本上可以采用一系列色调,确定产生您喜欢的颜色的亮度步骤,并使用抛物线确定饱和度公式。

标签: algorithm colors


【解决方案1】:

您可以让它们处于一定的亮度范围内。这将稍微控制“霓虹”颜色的数量。例如,如果“亮度”

brightness = sqrt(R^2+G^2+B^2)

在某个上限范围内,它会有一种褪色的浅色。相反,如果它在某个下限内,它会更暗。这将消除任何疯狂、突出的颜色,如果您选择一个非常高或非常低的界限,它们都将非常接近白色或黑色。

【讨论】:

    【解决方案2】:

    很难通过算法得到你想要的东西——人们研究色彩理论已经很长时间了,他们甚至不知道所有的规则。

    但是,您可以使用一些规则来剔除不良的颜色组合(即,有一些规则用于冲突颜色和选择互补色)。

    我建议您在尝试制作颜色之前访问您图书馆的艺术部分并查看有关颜色理论的书籍,以更好地了解什么是好的颜色 - 看起来您甚至可能不知道为什么某些组合有效并且其他人没有。

    -亚当

    【讨论】:

      【解决方案3】:

      您可以将随机颜色的 RGB 值与恒定颜色的 RGB 值平均:

      (Java 中的示例)

      public Color generateRandomColor(Color mix) {
          Random random = new Random();
          int red = random.nextInt(256);
          int green = random.nextInt(256);
          int blue = random.nextInt(256);
      
          // mix the color
          if (mix != null) {
              red = (red + mix.getRed()) / 2;
              green = (green + mix.getGreen()) / 2;
              blue = (blue + mix.getBlue()) / 2;
          }
      
          Color color = new Color(red, green, blue);
          return color;
      }
      


      将随机颜色与白色(255、255、255)混合,通过增加亮度同时保持原始颜色的色调来创建中性粉彩。这些随机生成的粉彩通常可以很好地搭配在一起,尤其是在大量时。

      以下是使用上述方法生成的一些柔和颜色:


      您还可以将随机颜色与恒定的粉彩混合,从而产生一组有色的中性色。例如,使用浅蓝色会产生如下颜色:


      更进一步,您可以在生成器中添加启发式算法,将补色或阴影级别考虑在内,但这完全取决于您希望使用随机颜色获得的印象。

      一些额外的资源:

      【讨论】:

      • 唯一的警告似乎是失去了可区分性。通过将红色绿色和蓝色与一种颜色(例如白色)取平均值,所有颜色自然会更接近白色并减少它们之间的差异。例如,如果您查看第一个屏幕截图:当这些果岭彼此相邻时,我当然可以区分它们,但是如果它们在某些生成的图形中不相邻怎么办?可能有问题。
      • 在生成随机颜色分量时,尝试用更少的值来限制上限,比如 200。
      【解决方案4】:

      转换为另一个调色板是一种更好的方法。他们这样做是有原因的:其他调色板是“可感知的”——也就是说,它们将相似的外观颜色放在一起,调整一个变量以可预测的方式改变颜色。对于 RGB 来说,这一切都不是真的,因为“很好地融合在一起”的颜色之间没有明显的关系。

      【讨论】:

        【解决方案5】:

        我会使用色轮并给定一个随机位置,您可以添加黄金角(137.5 度)

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

        为了每次得到不重叠的不同颜色。

        调整色轮的亮度,您还可以获得不同的亮/暗颜色组合。

        我发现这篇博文很好地解释了问题和使用黄金比例的解决方案。

        http://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/

        更新:我刚刚发现了另一种方法:

        称为RYB(red,yellow,blue)方法,本文对此进行了描述:

        http://threekings.tk/mirror/ryb_TR.pdf

        作为“受绘画启发的色彩合成”。

        算法生成颜色并选择每种新颜色以使其与先前选择的颜色的欧几里得距离最大化。

        在这里你可以找到一个好的javascript实现:

        http://afriggeri.github.com/RYB/

        更新 2:

        Sciences Po Medialb 刚刚发布了一个名为“I want Hue”的工具,它可以为数据科学家生成调色板。使用不同的颜色空间并通过使用 k-means 聚类或力向量(排斥图)生成调色板这些方法的结果非常好,它们在他们的网页中展示了理论和实现。

        http://tools.medialab.sciences-po.fr/iwanthue/index.php

        【讨论】:

          【解决方案6】:

          在javascript中:

          function pastelColors(){
              var r = (Math.round(Math.random()* 127) + 127).toString(16);
              var g = (Math.round(Math.random()* 127) + 127).toString(16);
              var b = (Math.round(Math.random()* 127) + 127).toString(16);
              return '#' + r + g + b;
          }
          

          在这里看到了这个想法:http://blog.functionalfun.net/2008/07/random-pastel-colour-generator.html

          【讨论】:

          • 不完全正确:您也需要对个位数数字进行零填充...无论如何,这是一个适合旁观者的工作小提琴:jsfiddle.net/RedDevil/LLYBQ ----- 从头开始​​...我没有注意到 +127 位......但这不会产生暗色调。
          • 最初的想法是生成任意令人愉悦的颜色。深色调对我来说似乎并不愉快;)
          【解决方案7】:
          function fnGetRandomColour(iDarkLuma, iLightLuma) 
          {       
            for (var i=0;i<20;i++)
            {
              var sColour = ('ffffff' + Math.floor(Math.random() * 0xFFFFFF).toString(16)).substr(-6);
          
              var rgb = parseInt(sColour, 16);   // convert rrggbb to decimal
              var r = (rgb >> 16) & 0xff;  // extract red
              var g = (rgb >>  8) & 0xff;  // extract green
              var b = (rgb >>  0) & 0xff;  // extract blue
          
              var iLuma = 0.2126 * r + 0.7152 * g + 0.0722 * b; // per ITU-R BT.709
          
          
              if (iLuma > iDarkLuma && iLuma < iLightLuma) return sColour;
            }
            return sColour;
          } 
          

          对于柔和,传入更高亮度的暗/亮整数 - 即 fnGetRandomColour(120, 250)

          学分:所有学分 http://paulirish.com/2009/random-hex-color-code-snippets/ stackoverflow.com/questions/12043187/how-to-check-if-hex-color-is-too-black

          【讨论】:

            【解决方案8】:

            一个不应该被忽视的答案,因为它简单且具有优势,是现实生活中的照片和绘画的采样。在现代艺术图片、塞尚、梵高、莫奈、照片的缩略图上,随心所欲地采样任意数量的随机像素......优点是您可以按主题获取颜色,并且它们是有机颜色。只需将 20 - 30 张图片放在一个文件夹中,然后每次随机抽取一张随机图片。

            转换为 HSV 值是基于心理调色板的广泛代码算法。 hsv 更容易随机化。

            【讨论】:

            • mkweb.bcgsc.ca/color_summarizer/?analyze 这是一个在线工具,可以分析真实照片并返回给您 RGB 值的绘图员说可以了解真实照片在图表中的内容... . 非常有用的网站,如果您正在尝试为随机颜色设计前卫算法,这是必不可少的-
            【解决方案9】:

            这是 C# 中快速而肮脏的颜色生成器(使用 article 中描述的“RYB 方法”)。这是JavaScript的重写。

            用途:

            List<Color> ColorPalette = ColorGenerator.Generate(30).ToList();
            

            前两种颜色往往是白色和黑色。我经常这样跳过它们(使用 Linq):

            List<Color> ColorsPalette = ColorGenerator
                        .Generate(30)
                        .Skip(2) // skip white and black
                        .ToList(); 
            

            实施:

            public static class ColorGenerator
            {
            
                // RYB color space
                private static class RYB
                {
                    private static readonly double[] White = { 1, 1, 1 };
                    private static readonly double[] Red = { 1, 0, 0 };
                    private static readonly double[] Yellow = { 1, 1, 0 };
                    private static readonly double[] Blue = { 0.163, 0.373, 0.6 };
                    private static readonly double[] Violet = { 0.5, 0, 0.5 };
                    private static readonly double[] Green = { 0, 0.66, 0.2 };
                    private static readonly double[] Orange = { 1, 0.5, 0 };
                    private static readonly double[] Black = { 0.2, 0.094, 0.0 };
            
                    public static double[] ToRgb(double r, double y, double b)
                    {
                        var rgb = new double[3];
                        for (int i = 0; i < 3; i++)
                        {
                            rgb[i] = White[i]  * (1.0 - r) * (1.0 - b) * (1.0 - y) +
                                     Red[i]    * r         * (1.0 - b) * (1.0 - y) +
                                     Blue[i]   * (1.0 - r) * b         * (1.0 - y) +
                                     Violet[i] * r         * b         * (1.0 - y) +
                                     Yellow[i] * (1.0 - r) * (1.0 - b) *        y +
                                     Orange[i] * r         * (1.0 - b) *        y +
                                     Green[i]  * (1.0 - r) * b         *        y +
                                     Black[i]  * r         * b         *        y;
                        }
            
                        return rgb;
                    }
                }
            
                private class Points : IEnumerable<double[]>
                {
                    private readonly int pointsCount;
                    private double[] picked;
                    private int pickedCount;
            
                    private readonly List<double[]> points = new List<double[]>();
            
                    public Points(int count)
                    {
                        pointsCount = count;
                    }
            
                    private void Generate()
                    {
                        points.Clear();
                        var numBase = (int)Math.Ceiling(Math.Pow(pointsCount, 1.0 / 3.0));
                        var ceil = (int)Math.Pow(numBase, 3.0);
                        for (int i = 0; i < ceil; i++)
                        {
                            points.Add(new[]
                            {
                                Math.Floor(i/(double)(numBase*numBase))/ (numBase - 1.0),
                                Math.Floor((i/(double)numBase) % numBase)/ (numBase - 1.0),
                                Math.Floor((double)(i % numBase))/ (numBase - 1.0),
                            });
                        }
                    }
            
                    private double Distance(double[] p1)
                    {
                        double distance = 0;
                        for (int i = 0; i < 3; i++)
                        {
                            distance += Math.Pow(p1[i] - picked[i], 2.0);
                        }
            
                        return distance;
                    }
            
                    private double[] Pick()
                    {
                        if (picked == null)
                        {
                            picked = points[0];
                            points.RemoveAt(0);
                            pickedCount = 1;
                            return picked;
                        }
            
                        var d1 = Distance(points[0]);
                        int i1 = 0, i2 = 0;
                        foreach (var point in points)
                        {
                            var d2 = Distance(point);
                            if (d1 < d2)
                            {
                                i1 = i2;
                                d1 = d2;
                            }
            
                            i2 += 1;
                        }
            
                        var pick = points[i1];
                        points.RemoveAt(i1);
            
                        for (int i = 0; i < 3; i++)
                        {
                            picked[i] = (pickedCount * picked[i] + pick[i]) / (pickedCount + 1.0);
                        }
            
                        pickedCount += 1;
                        return pick;
                    }
            
                    public IEnumerator<double[]> GetEnumerator()
                    {
                        Generate();
                        for (int i = 0; i < pointsCount; i++)
                        {
                            yield return Pick();
                        }
                    }
            
                    IEnumerator IEnumerable.GetEnumerator()
                    {
                        return GetEnumerator();
                    }
                }
            
                public static IEnumerable<Color> Generate(int numOfColors)
                {
                    var points = new Points(numOfColors);
            
                    foreach (var point in points)
                    {
                        var rgb = RYB.ToRgb(point[0], point[1], point[2]);
                        yield return Color.FromArgb(
                            (int)Math.Floor(255 * rgb[0]),
                            (int)Math.Floor(255 * rgb[1]),
                            (int)Math.Floor(255 * rgb[2]));
                    }
                }
            }
            

            【讨论】:

            【解决方案10】:

            在 php 中:

            function pastelColors() {
                $r = dechex(round(((float) rand() / (float) getrandmax()) * 127) + 127);
                $g = dechex(round(((float) rand() / (float) getrandmax()) * 127) + 127);
                $b = dechex(round(((float) rand() / (float) getrandmax()) * 127) + 127);
            
                return "#" . $r . $g . $b;
            }
            

            来源:https://stackoverflow.com/a/12266311/2875783

            【讨论】:

              【解决方案11】:

              我强烈建议您使用 CG HSVtoRGB 着色器功能,它们非常棒……它为您提供像画家一样的自然色彩控制,而不是像 crt 显示器那样的控制,您可能不会!

              这是一种制作 1 个浮点值的方法。即灰色,成 1000 ds 的颜色、亮度和饱和度等组合:

              int rand = a global color randomizer that you can control by script/ by a crossfader etc.
              float h = perlin(grey,23.3*rand)
              float s = perlin(grey,54,4*rand)
              float v = perlin(grey,12.6*rand)
              
              Return float4 HSVtoRGB(h,s,v);
              

              结果是真棒颜色随机化!它不是自然的,但它使用自然的颜色渐变,并且看起来有机且可控的虹彩/柔和参数。

              对于 perlin,你可以使用这个函数,它是 perlin 的快速 zig zag 版本。

              function  zig ( xx : float ): float{    //lfo nz -1,1
                  xx= xx+32;
                  var x0 = Mathf.Floor(xx);
                  var x1 = x0+1;
                  var v0 = (Mathf.Sin (x0*.014686)*31718.927)%1;
                  var v1 = (Mathf.Sin  (x1*.014686)*31718.927)%1;
                  return Mathf.Lerp( v0 , v1 , (xx)%1 )*2-1;
              }
              

              【讨论】:

                【解决方案12】:

                David Crow 在 R 两行中的方法:

                GetRandomColours <- function(num.of.colours, color.to.mix=c(1,1,1)) {
                  return(rgb((matrix(runif(num.of.colours*3), nrow=num.of.colours)*color.to.mix)/2))
                }
                

                【讨论】:

                  【解决方案13】:

                  这是我为我创建的网站写的。它将为任何具有.flat-color-gen 类的 div 自动生成一个随机的平面背景颜色。 Jquery 仅用于将 css 添加到页面的目的; generateFlatColorWithOrder() 方法的主要部分不需要它。

                  JsFiddle Link

                  (function($) {
                      function generateFlatColorWithOrder(num, rr, rg, rb) {
                          var colorBase = 256;
                          var red = 0;
                          var green = 0;
                          var blue = 0;
                          num = Math.round(num);
                          num = num + 1;
                          if (num != null) {
                  
                              red = (num*rr) % 256;
                              green = (num*rg) % 256;
                              blue = (num*rb) % 256;
                          }
                          var redString = Math.round((red + colorBase) / 2).toString();
                          var greenString = Math.round((green + colorBase) / 2).toString();
                          var blueString = Math.round((blue + colorBase) / 2).toString();
                          return "rgb("+redString+", "+greenString+", "+blueString+")";
                          //return '#' + redString + greenString + blueString;
                      }
                  
                      function generateRandomFlatColor() {
                          return generateFlatColorWithOrder(Math.round(Math.random()*127));
                      }
                  
                      var rr = Math.round(Math.random()*1000);
                      var rg = Math.round(Math.random()*1000);
                      var rb = Math.round(Math.random()*1000);
                      console.log("random red: "+ rr);
                      console.log("random green: "+ rg);
                      console.log("random blue: "+ rb);
                      console.log("----------------------------------------------------");
                      $('.flat-color-gen').each(function(i, obj) {
                          console.log(generateFlatColorWithOrder(i));
                          $(this).css("background-color",generateFlatColorWithOrder(i, rr, rg, rb).toString());
                      });
                  })(window.jQuery);
                  

                  【讨论】:

                    【解决方案14】:

                    对 David Crow 原始答案的 JavaScript 改编,包括 IE 和 Nodejs 特定代码。

                    generateRandomComplementaryColor = function(r, g, b){
                        //--- JavaScript code
                        var red = Math.floor((Math.random() * 256));
                        var green = Math.floor((Math.random() * 256));
                        var blue = Math.floor((Math.random() * 256));
                        //---
                    
                        //--- Extra check for Internet Explorers, its Math.random is not random enough.
                        if(!/MSIE 9/i.test(navigator.userAgent) && !/MSIE 10/i.test(navigator.userAgent) && !/rv:11.0/i.test(navigator.userAgent)){
                            red = Math.floor((('0.' + window.crypto.getRandomValues(new Uint32Array(1))[0]) * 256));
                            green = Math.floor((('0.' + window.crypto.getRandomValues(new Uint32Array(1))[0]) * 256));
                            blue = Math.floor((('0.' + window.crypto.getRandomValues(new Uint32Array(1))[0]) * 256));
                        };
                        //---
                    
                        //--- nodejs code
                        /*
                        crypto = Npm.require('crypto');
                        red = Math.floor((parseInt(crypto.randomBytes(8).toString('hex'), 16)) * 1.0e-19 * 256);
                        green = Math.floor((parseInt(crypto.randomBytes(8).toString('hex'), 16)) * 1.0e-19 * 256);
                        blue = Math.floor((parseInt(crypto.randomBytes(8).toString('hex'), 16)) * 1.0e-19 * 256);
                        */
                        //---
                    
                        red = (red + r)/2;
                        green = (green + g)/2;
                        blue = (blue + b)/2;
                    
                        return 'rgb(' + Math.floor(red) + ', ' + Math.floor(green) + ', ' + Math.floor(blue) + ')';
                    }
                    

                    使用以下命令运行函数:

                    generateRandomComplementaryColor(240, 240, 240);
                    

                    【讨论】:

                      【解决方案15】:

                      使用distinct-colors

                      用javascript编写。

                      它会生成一个视觉上不同颜色的调色板。

                      distinct-colors 是高度可配置的:

                      • 选择调色板中有多少种颜色
                      • 将色调限制在特定范围内
                      • 将色度(饱和度)限制在特定范围内
                      • 将亮度限制在特定范围内
                      • 配置调色板的一般质量

                      【讨论】:

                        【解决方案16】:

                        我已经成功使用TriadMixingCIE94 来避免类似的颜色。下图使用红色、黄色和白色的输入颜色。见here

                        【讨论】:

                          猜你喜欢
                          • 2015-05-05
                          • 2022-10-17
                          • 2011-07-07
                          • 2012-06-13
                          • 1970-01-01
                          • 2012-01-28
                          • 1970-01-01
                          • 1970-01-01
                          相关资源
                          最近更新 更多