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

StackOverflow https://stackoverflow.com/questions/43044

  •  09-06-2019
  •  | 
  •  

Pergunta

Estou procurando um algoritmo simples para gerar um grande número de cores aleatórias e esteticamente agradáveis.Portanto, nada de cores néon malucas, cores que lembram fezes, etc.

Encontrei soluções para esse problema, mas elas dependem de paletas de cores alternativas às 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.

Qualquer ideia seria ótima.

Foi útil?

Solução

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 branco (255, 255, 255) cria tons pastéis neutros, aumentando a luminosidade e mantendo a tonalidade da cor original.Esses pastéis gerados aleatoriamente geralmente combinam bem, especialmente em grandes números.

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

First


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:

Second


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

Alguns recursos adicionais:

Outras dicas

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 a cada vez que não se sobreponham.

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

Encontrei esta postagem no 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-programmaticamente/

ATUALIZAR: Acabei de encontrar esta outra abordagem:

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

http://trêsreis.tk/mirror/ryb_TR.pdf

como "Composição de cores inspirada em pintura".

O algoritmo gera as cores e cada nova cor é escolhida de forma a 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 agrupamento k-means ou 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 web.

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

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

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

Converter para outra paleta é uma maneira muito superior de fazer isso.Há uma razão pela qual eles fazem isso:outras paletas são 'perceptivas' - isto é, elas colocam cores aparentemente semelhantes próximas umas das outras e o ajuste de uma variável altera a cor de maneira previsível.Nada disso é verdade para RGB, onde não existe uma relação óbvia entre cores que “combinam bem”.

Uma resposta que não deve ser esquecida, por ser simples e apresentar vantagens, é a amostragem de fotos e pinturas da vida real.experimente quantos pixels aleatórios desejar, cores aleatórias em 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 tirar uma amostra aleatória de cada vez.

A conversão para valores HSV é um algoritmo de código amplamente difundido para paletas de base psicológica.hsv é mais fácil de randomizar.

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

Eu tive sucesso usando TríadeMixagem e CIE94 para evitar cores semelhantes.A imagem a seguir usa as cores de entrada vermelho, amarelo e branco.Ver aqui.

TriadMixing + CIE94

Aqui está um gerador de cores rápido e sujo em C# (usando a 'abordagem RYB' descrita neste artigo).É uma reescrita de 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 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]));
        }
    }
}

Método de David Crow em duas linhas 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))
}
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 escuros/claros de luma mais altos - ou seja, fnGetRandomColour(120, 250)

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

Adaptação JavaScript da resposta original de David Crow, código específico do IE e Nodejs incluído.

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

você pode fazer com que eles tenham 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)

estivesse dentro de um certo limite alto, teria uma cor clara e desbotada.Por outro lado, se estivesse dentro de um determinado limite inferior, seria mais escuro.Isso eliminaria quaisquer cores malucas e destacadas e se você escolhesse um limite muito alto ou muito baixo, todas elas ficariam bem próximas do branco ou do preto.

Será difícil conseguir o que você deseja através de algoritmos - as pessoas estudam a teoria das cores há muito tempo e nem 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 cores conflitantes e escolha de cores complementares).

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

-Adão

Eu recomendo fortemente usar uma função de shader CG HSVtoRGB, eles são fantásticos...ele oferece controle natural de cores como um pintor, em vez de controle como um monitor CRT, o que você provavelmente não é!

Esta é uma maneira de criar 1 valor flutuante.ou sejaCinza, em 1000 ds de combinações de cor, 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 é uma RANDOMIZAÇÃO DE CORES INCRÍVEL!não é natural, mas usa gradientes de cores naturais e parece orgânico e com parâmetros iridescentes / pastéis controláveis.

Para perlin, você pode usar esta função, é uma versão rápida em zigue-zague 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;
}

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

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

Usar cores distintas.

Escrito em javascript.

Ele gera uma paleta de visualmente cores distintas.

cores distintas é altamente configurável:

  • Escolha quantas cores existem na paleta
  • Restringir o matiz a um intervalo específico
  • Restringir o croma (saturação) a um intervalo específico
  • Restrinja a luminosidade a uma faixa específica
  • Configure a qualidade geral da paleta
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top