Algoritmo para gerar aleatoriamente uma paleta de cores esteticamente agradável [fechada]


301

Estou procurando um algoritmo simples para gerar um grande número de cores aleatórias e esteticamente agradáveis. Portanto, não há cores loucas de neon, cores que lembram fezes, etc.

Encontrei soluções para esse problema, mas elas dependem de paletas de cores alternativas do que RGB. Eu prefiro usar RGB direto do que mapear para frente e para trás. Essas outras soluções também podem gerar no máximo apenas 32 cores aleatórias agradáveis.

Alguma idéia seria ótima.


2
Eu faria um site que gera uma cor aleatória a cada visita. Tenha um voto "esta cor é demais" / "essa cor é uma merda". Em seguida, classifique pela proporção de votos.
Nosredna

Você pode conferir HSL e HSV.
Jim Keener

48
"cores que lembram fezes" Eu adoro isso
lol

Isso não é um algoritmo.
Matt A Ninja

Vou adicionar um comentário, pois a pergunta está encerrada. Eu não tentei, mas seria interessante tentar uma maneira fractal ou procedural, usando, por exemplo, o algoritmo ou variantes do deslocamento do ponto médio ( lighthouse3d.com/opengl/terrain/index.php?mpd2 ) ou o ruído Perlin, mas em vez das alturas para misturar os componentes rgb das cores.
alfoks

Respostas:


426

Você pode calcular a média dos valores RGB de cores aleatórias com os de uma cor constante:

(exemplo em 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;
}


A mistura de cores aleatórias com o branco (255, 255, 255) cria tons neutros, aumentando a luminosidade, mantendo o tom da cor original. Esses pastéis gerados aleatoriamente geralmente andam bem juntos, especialmente em grandes números.

Aqui estão algumas cores pastel geradas usando o método acima:

Primeiro


Você também pode misturar a cor aleatória com um pastel constante, o que resulta em um conjunto colorido de cores neutras. Por exemplo, usar um azul claro cria cores como estas:

Segundo


Indo além, você pode adicionar heurísticas ao seu gerador que levem em consideração cores ou níveis de sombreamento complementares, mas tudo depende da impressão que você deseja obter com suas cores aleatórias.

Alguns recursos adicionais:


3
A única ressalva parece ser a perda de capacidade de distinguir. Ao calcular a média de vermelho, verde e azul com uma cor como o branco, naturalmente todas as cores se aproximam do branco e reduzem as diferenças entre elas. Por exemplo, se você olhar para a primeira captura de tela: Quando esses verdes estão próximos, certamente posso distingui-los, mas e se eles não estiverem adjacentes em algum gráfico produzido? Pode ser problemático.
Zelphir Kaltstahl 19/03/16

Ao gerar componente de cor aleatória, tente restringia o limite superior com algo menos, como 200.
Nickolodeon

87

Eu usaria uma roda de cores e, dada uma posição aleatória, você poderia adicionar o ângulo dourado (137,5 graus)

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

para obter cores diferentes sempre que não se sobrepõem.

Ajustando o brilho da roda de cores, você também pode obter diferentes combinações de cores claras / escuras.

Encontrei este post do blog que explica muito bem o problema e a solução usando a proporção áurea.

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

UPDATE: Acabei de encontrar essa outra abordagem:

É chamado de método RYB (vermelho, amarelo, azul) e é descrito neste artigo:

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

como "Composição de cores inspiradas em tinta".

O algoritmo gera as cores e cada nova cor é escolhida para maximizar sua distância euclidiana às previamente selecionadas.

Aqui você pode encontrar uma boa implementação em javascript:

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

ATUALIZAÇÃO 2:

A Sciences Po Medialb acaba de lançar uma ferramenta chamada "I want Hue", que gera paletas de cores para cientistas de dados. Usando diferentes espaços de cores e gerando as paletas usando o cluster de k ou meios de vetores de força (gráficos de repulsão) Os resultados desses métodos são muito bons, eles mostram a teoria e uma implementação em sua página da web.

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


iWantHue é a resposta. Vá ali. Surpreenda-se.
Irongaze.com

23

Em 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;
}

Viu a ideia aqui: http://blog.functionalfun.net/2008/07/random-pastel-colour-generator.html


Não está completamente correto: você precisa zerar também para números de um dígito ... De qualquer forma, aqui está um violino para quem procura: jsfiddle.net/RedDevil/LLYBQ ----- Risque isso ... eu não observe o bit +127 ... Mas isso não gerará tons escuros.
precisa saber é o seguinte

2
A idéia original era gerar cores arbitrariamente agradáveis. Os tons escuros não parecem agradável para mim;)
motobói

11

A conversão para outra paleta é uma maneira muito superior de fazer isso. Há uma razão para eles fazerem isso: outras paletas são 'perceptivas' - ou seja, juntam cores semelhantes e o ajuste de uma variável altera a cor de maneira previsível. Nada disso se aplica ao RGB, onde não há relação óbvia entre as cores que "combinam bem".


6

Eu tive sucesso usando o TriadMixing e o CIE94 para evitar cores semelhantes. A imagem a seguir usa as cores de entrada vermelho, amarelo e branco. Veja aqui .

TriadMixing + CIE94


5

Uma resposta que não deve ser esquecida, porque é simples e apresenta vantagens, é a amostragem de fotos e pinturas da vida real. experimente quantos pixels aleatórios desejar cores aleatórias nas miniaturas de fotos de arte moderna, cézanne, van gogh, monnet, fotos ... a vantagem é que você pode obter cores por tema e que são cores orgânicas. basta colocar de 20 a 30 fotos em uma pasta e amostrar aleatoriamente uma foto aleatória toda vez.

A conversão para valores HSV é um algoritmo de código generalizado para paleta psicologicamente baseada. HSV é mais fácil de randomizar.


1
mkweb.bcgsc.ca/color_summarizer/?analyze Aqui está uma ferramenta on-line que pode analisar fotos da vida real e retornar a você. Os valores dos RGB indicam que você pode ter uma idéia do que as fotos da vida real têm em seus gráficos .... extremamente site útil, que é essencial se você está tentando projetar algoritmos de vanguarda para cores-aleatório
com.prehensible

4

Em 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;
}

fonte: https://stackoverflow.com/a/12266311/2875783


3

Aqui está um gerador de cores rápido e sujo em C # (usando a 'abordagem RYB' descrita neste artigo ). É uma reescrita do JavaScript .

Usar:

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

As duas primeiras cores tendem a ser brancas e um tom de preto. Costumo ignorá-los assim (usando o Linq):

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

Implementação:

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]));
        }
    }
}

Eu removi a resposta Java, mas, se necessário, a versão Java pode ser visto neste Gist: gist.github.com/lotsabackscatter/3f6a658fd7209e010dad
Dylan Watson

3

O método de David Crow em uma linha dupla 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))
}

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;
} 

Para pastel, passe números inteiros luma escuro / claro mais altos - ou seja, fnGetRandomColour (120, 250)

Créditos: todos os créditos em http://paulirish.com/2009/random-hex-color-code-snippets/ stackoverflow.com/questions/12043187/how-to-check-if-hex-color-is-too-black


1

Adaptação JavaScript da resposta original de David Crow, incluindo o código específico do IE e do 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) + ')';
}

Execute a função usando:

generateRandomComplementaryColor(240, 240, 240);

1

Use cores distintas .

Escrito em javascript.

Ele gera uma paleta de visualmente distintas.

cores distintas é altamente configurável:

  • Escolha quantas cores estão na paleta
  • Restrinja a tonalidade a um intervalo específico
  • Restrinja o croma (saturação) a um intervalo específico
  • Restrinja a luminosidade a um intervalo específico
  • Configurar a qualidade geral da paleta

0

você poderia tê-los dentro de um certo brilho. isso controlaria um pouco a quantidade de cores "neon". por exemplo, se o "brilho"

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

estava dentro de um certo limite, teria uma cor clara e desbotada. Por outro lado, se estivesse dentro de um certo limite inferior, seria mais escuro. Isso eliminaria todas as cores loucas e de destaque e se você escolher um limite muito alto ou muito baixo, todos eles ficarão bem próximos de branco ou preto.


0

Vai ser difícil conseguir o que você deseja algoritmicamente - as pessoas estudam a teoria das cores há muito tempo e nem sequer conhecem todas as regras.

No entanto, existem alguns regras que você pode usar para selecionar combinações de cores ruins (ou seja, existem regras para combinar cores e escolher cores complementares).

Eu recomendo que você visite a seção de arte da sua biblioteca e consulte os livros sobre teoria das cores para entender melhor o que é uma boa cor antes de tentar criar uma - parece que você nem sabe por que certas combinações funcionam e outras não. t.

-Adão


0

Eu recomendo fortemente o uso de uma função de sombreador CG HSVtoRGB, eles são incríveis ... oferece controle natural de cores como um pintor, em vez de um monitor CRT, o que você provavelmente não é!

Esta é uma maneira de fazer 1 valor flutuante. Cinza, em 1000 ds de combinações de cores, brilho e saturação, etc:

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

O resultado é RANDOMIZAÇÃO INCRÍVEL DA COR! não é natural, mas usa gradientes de cores naturais e parece parâmetros orgânicos e controláveis ​​irridescentes / pastel.

Para o perlin, você pode usar esta função, é uma versão rápida em zig zag do perlin.

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;
}

0

Aqui está algo que eu escrevi para um site que criei. Ele gera automaticamente uma cor de plano de fundo aleatória para qualquer div da classe .flat-color-gen. O Jquery é necessário apenas para a finalidade de adicionar css à página; não é necessário para a parte principal disso, que é o generateFlatColorWithOrder()método.

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);
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.