320

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

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

任何想法都会很棒。

4

16 回答 16

442

您可以将随机颜色的 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)混合,通过增加亮度同时保持原始颜色的色调来创建中性粉彩。这些随机生成的粉彩通常可以很好地搭配在一起,尤其是大量使用时。

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

第一的


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

第二


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

一些额外的资源:

于 2008-09-04T06:00:39.977 回答
89

我会使用色轮并给定一个随机位置,您可以添加黄金角(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

于 2011-02-15T19:01:04.720 回答
23

在 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

于 2012-09-04T15:05:23.603 回答
11

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

于 2009-06-07T20:45:33.690 回答
7

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

TriadMixing + CIE94

于 2016-12-09T20:15:29.700 回答
5

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

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

于 2013-08-16T08:59:14.913 回答
4

在 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

于 2014-03-12T20:25:12.460 回答
3

这是 C# 中快速而肮脏的颜色生成器(使用本文中描述的“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]));
        }
    }
}
于 2014-01-26T09:09:40.570 回答
3

R 两行中的 David Crow 方法:

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))
}
于 2015-02-13T13:40:11.853 回答
3

使用不同的颜色

用javascript写的。

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

distinct-colors 是高度可配置的:

  • 选择调色板中有多少种颜色
  • 将色调限制在特定范围内
  • 将色度(饱和度)限制在特定范围内
  • 将亮度限制在特定范围内
  • 配置调色板的一般质量
于 2015-08-20T17:24:55.723 回答
2
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

于 2013-02-11T10:28:12.397 回答
1

JavaScript 改编自 David Crow 的原始答案,包括 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);
于 2015-07-25T17:44:38.580 回答
0

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

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

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

于 2008-09-04T02:16:50.263 回答
0

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

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

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

-亚当

于 2008-09-04T03:36:43.800 回答
0

我强烈建议使用 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;
}
于 2014-03-30T12:23:57.883 回答
0

这是我为我制作的网站写的东西。它将为任何具有 class 的 div 自动生成随机的平面背景颜色.flat-color-gen。Jquery 仅用于向页面添加 css 的目的;这不是方法的主要部分所必需的generateFlatColorWithOrder()

JsFiddle 链接

(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);
于 2015-07-23T17:30:11.117 回答