首页 / 知识

随机生成美学上令人愉悦的调色板的算法

2023-04-14 03:52:00

Algorithm to randomly generate an aesthetically-pleasing color palette

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

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

任何想法都会很棒。


您可以将随机颜色的RGB值与常量颜色的RGB值进行平均:

(Java中的例子)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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)混合可通过增加亮度同时保持原始色调的色调来创建中性色调。这些随机生成的粉彩通常很好地结合在一起,特别是大量。

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

First



您还可以将随机颜色与常量柔和色调混合,从而产生一组有色的中性色。例如,使用浅蓝色会创建如下颜色:

Second



更进一步,您可以在生成器中添加启发式算法,考虑补色或阴影级别,但这一切都取决于您想要使用随机颜色实现的印象。

一些额外的资源:

  • http://en.wikipedia.org/wiki/Color_theory
  • http://en.wikipedia.org/wiki/Complementary_color

我会使用色轮并给出一个随机位置你可以添加金色角度(137,5度)

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

为了在每次不重叠时获得不同的颜色。

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

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

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

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

它被称为RYB(红色,黄色,蓝色)方法,它在本文中描述:

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

作为"Paint Inspired Color Compositing"。

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

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

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

更新2:

Sciences Po Medialb刚刚发布了一款名为"我想要Hue"的工具,可以为数据科学家生成调色板。使用不同的颜色空间并使用k-means聚类或力矢量生成调色板(排斥图)这些方法的结果非常好,它们在其网页中显示了理论和实现。

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


在javascript中:

1
2
3
4
5
6
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


转换到另一个调色板是一种非常优越的方法。他们这样做是有原因的:其他调色板是"感性的" - 也就是说,它们将类似的看似颜色放在一起,调整一个变量会以可预测的方式改变颜色。对于RGB来说,这一切都不是真的,在这些颜色之间没有明显的关系。


一个不容忽视的答案,因为它简单而且具有优势,是对现实生活照片和绘画的抽样。在现代艺术照片,cezanne,梵高,monnet,照片的缩略图上随机选择颜色随机颜色......优点是你可以按主题获取颜色,并且它们是有机颜色。只需在文件夹中放置20 - 30个图片,并随机随机抽样随机图片。

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


在PHP中:

1
2
3
4
5
6
7
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


我使用TriadMixing和CIE94成功避免了类似的颜色。下图使用红色,黄色和白色的输入颜色。看这里。

TriadMixing + CIE94


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

采用:

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

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

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

执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
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]));
        }
    }
}

大卫·克劳在R双线班车中的方法:

1
2
3
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))
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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) + ')';
}

运行该功能:

1
generateRandomComplementaryColor(240, 240, 240);


我强烈建议使用CG HSVtoRGB着色器功能,它们非常棒......它可以让你像画家一样自然控制色彩,而不是像crt显示器那样控制,你不可能!

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

1
2
3
4
5
6
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);

结果是令人敬畏的颜色随机化!它不自然,但它使用自然的颜色渐变,它看起来有机和可控制的irridescent /粉彩参数。

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

1
2
3
4
5
6
7
8
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;
}

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

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

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


这是我为我制作的网站写的东西。它将为类.flat-color-gen的任何div自动生成随机平面背景颜色。只有在向页面添加css时才需要Jquery;它的主要部分不需要它,这是generateFlatColorWithOrder()方法。

JsFiddle链接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
(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);

使用不同颜色。

用javascript编写。

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

distinct-colors具有高度可配置性:

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

在算法上很难得到你想要的东西 - 人们长期以来一直在研究色彩理论,他们甚至不知道所有的规则。

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

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

-亚当


算法调色板解决方案映射

最新内容

相关内容

热门文章

推荐文章

标签云

猜你喜欢