Algoritmo para generar aleatoriamente una paleta de colores estéticamente agradable [cerrado]

301

Estoy buscando un algoritmo simple para generar una gran cantidad de colores aleatorios y estéticamente agradables. Así que no hay colores de neón locos, colores que recuerden a las heces, etc.

He encontrado soluciones a este problema, pero dependen de paletas de colores alternativas a RGB. Prefiero usar RGB directo que mapear de un lado a otro. Estas otras soluciones también pueden generar, como máximo, solo 32 colores aleatorios más o menos agradables.

Cualquier idea sería genial.

Brian Gianforcaro
fuente
2
Haría un sitio web que genera un color aleatorio en cada visita. Tener un voto de "este color mola" / "este color apesta". Luego ordena por la proporción de votos.
Nosredna
Puede consultar HSL y HSV.
Jim Keener
48
"colores que recuerdan a las heces" Me encanta
lol
Eso no es un algoritmo.
Matt The Ninja el
Agregaré un comentario ya que la pregunta está cerrada. No lo he probado, pero sería interesante intentarlo de manera fractal o de procedimiento, es decir, utilizando el algoritmo de desplazamiento de punto medio o variantes ( lighthouse3d.com/opengl/terrain/index.php?mpd2 ) o ruido de Perlin, pero en lugar de alturas mezclar los componentes rgb de los colores.
alfoks

Respuestas:

426

Puede promediar los valores RGB de colores aleatorios con los de un color constante:

(ejemplo en 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;
}


La mezcla de colores aleatorios con blanco (255, 255, 255) crea pasteles neutros al aumentar la luminosidad mientras se mantiene el tono del color original. Estos pasteles generados al azar generalmente van bien juntos, especialmente en grandes cantidades.

Aquí hay algunos colores pastel generados usando el método anterior:

primero


También puede mezclar el color aleatorio con un pastel constante, lo que da como resultado un conjunto teñido de colores neutros. Por ejemplo, usar un azul claro crea colores como estos:

Segundo


Yendo más lejos, podría agregar heurísticas a su generador que tengan en cuenta los colores complementarios o los niveles de sombreado, pero todo depende de la impresión que desee lograr con sus colores aleatorios.

Algunos recursos adicionales:

David Crow
fuente
3
La única advertencia parece ser la pérdida de distinguibilidad. Al tomar un promedio de rojo, verde y azul con un color como el blanco, naturalmente todos los colores se acercan al blanco y reducen las diferencias entre ellos. Por ejemplo, si miras la primera captura de pantalla: cuando esos verdes están uno al lado del otro, seguramente puedo distinguirlos, pero ¿y si no son adyacentes en algún gráfico producido? Podría ser problemático
Zelphir Kaltstahl
Al generar un componente de color aleatorio, intente restringir el límite superior con algo menos, como 200.
Nickolodeon
87

Usaría una rueda de colores y, dada una posición aleatoria, podría agregar el ángulo dorado (137,5 grados)

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

para obtener diferentes colores cada vez que no se superpongan.

Al ajustar el brillo de la rueda de colores, también puede obtener diferentes combinaciones de colores brillantes / oscuros.

He encontrado esta publicación de blog que explica muy bien el problema y la solución utilizando la proporción áurea.

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

ACTUALIZACIÓN: Acabo de encontrar este otro enfoque:

Se llama método RYB (rojo, amarillo, azul) y se describe en este documento:

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

como "Composición de color inspirada en pintura".

El algoritmo genera los colores y cada nuevo color se elige para maximizar su distancia euclidiana a los previamente seleccionados.

Aquí puede encontrar una buena implementación en javascript:

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

ACTUALIZACIÓN 2:

El Sciences Po Medialb acaba de lanzar una herramienta llamada "Quiero Hue" que genera paletas de colores para los científicos de datos. Usando diferentes espacios de color y generando las paletas usando clusters de k-means o vectores de fuerza (gráficos de repulsión) Los resultados de esos métodos son muy buenos, muestran la teoría y una implementación en su página web.

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

Fgblanch
fuente
iWantHue es la respuesta. Ve allí. Estar asombrado.
Irongaze.com
23

En 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 la idea aquí: http://blog.functionalfun.net/2008/07/random-pastel-colour-generator.html

motobói
fuente
No es completamente correcto: también necesita rellenar con ceros para números de un solo dígito ... De todos modos, aquí hay un violín que funciona para los espectadores: jsfiddle.net/RedDevil/LLYBQ ----- Tacha eso ... No lo hice observe el bit de +127 ... Pero esto no generará sombras oscuras.
kumarharsh
2
La idea original era generar colores arbitrariamente agradables. Las sombras oscuras no me parecen agradables;)
motobói
11

La conversión a otra paleta es una forma muy superior de hacer esto. Hay una razón por la que hacen eso: otras paletas son 'perceptuales', es decir, ponen colores similares similares muy cerca, y al ajustar una variable cambia el color de una manera predecible. Nada de eso es cierto para RGB, donde no hay una relación obvia entre colores que "combinan bien".

Nick Johnson
fuente
6

He tenido éxito con TriadMixing y CIE94 para evitar colores similares. La siguiente imagen utiliza los colores de entrada rojo, amarillo y blanco. Ver aquí .

TriadMixing + CIE94

Moriarty
fuente
5

Una respuesta que no debe pasarse por alto, porque es simple y presenta ventajas, es el muestreo de fotos y pinturas de la vida real. muestre tantos píxeles aleatorios como desee colores aleatorios en miniaturas de imágenes de arte moderno, cezanne, van gogh, monnet, fotos ... la ventaja es que puede obtener colores por tema y que son colores orgánicos. solo ponga 20-30 fotos en una carpeta y muestre aleatoriamente una foto aleatoria cada vez.

La conversión a valores HSV es un algoritmo de código generalizado para la paleta psicológicamente basada. hsv es más fácil de aleatorizar.

comprensible
fuente
1
mkweb.bcgsc.ca/color_summarizer/?analyze Aquí hay una herramienta en línea que puede analizar fotos de la vida real y regresa a usted. muy útil sitio web, que es esencial si usted está tratando de diseñar algoritmos de vanguardia para colores- al azar
com.prehensible
4

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

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

Petr Bugyík
fuente
3

Aquí hay un generador de color rápido y sucio en C # (usando el 'enfoque RYB' descrito en este artículo ). Es una reescritura de JavaScript .

Utilizar:

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

Los primeros dos colores tienden a ser blancos y un tono negro. A menudo los omito así (usando Linq):

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

Implementación:

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]));
        }
    }
}
m1ch4ls
fuente
He eliminado la respuesta de Java, pero si es necesario, la versión de Java se puede ver en este Gist: gist.github.com/lotsabackscatter/3f6a658fd7209e010dad
Dylan Watson
3

El método de David Crow en un R de dos líneas:

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))
}
Dave_L
fuente
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, pase los enteros oscuros / claros de luma más altos, es decir, fnGetRandomColour (120, 250)

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

ChilledFlame
fuente
1

Adaptación de JavaScript de la respuesta original de David Crow, incluido el código específico de IE y 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) + ')';
}

Ejecute la función usando:

generateRandomComplementaryColor(240, 240, 240);
Escéptico
fuente
1

Usa colores distintos .

Escrito en javascript.

Genera una paleta de colores visualmente distintos.

distintos colores es altamente configurable:

  • Elige cuántos colores hay en la paleta
  • Restringe el tono a un rango específico
  • Restringe el croma (saturación) a un rango específico
  • Restringe la ligereza a un rango específico
  • Configurar la calidad general de la paleta
InternalFX
fuente
0

podrías hacer que estén dentro de un cierto brillo. eso controlaría un poco la cantidad de colores "neón". por ejemplo, si el "brillo"

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

estaba dentro de cierto límite alto, tendría un color claro y desteñido. Por el contrario, si estuviera dentro de un cierto límite bajo, sería más oscuro. Esto eliminaría cualquier color loco y destacado, y si elige un límite realmente alto o muy bajo, todos estarán bastante cerca del blanco o el negro.

holaandre
fuente
0

Va a ser difícil obtener lo que quiere algorítmicamente: las personas han estado estudiando la teoría del color durante mucho tiempo y ni siquiera conocen todas las reglas.

Sin embargo, hay algunas reglas que puede usar para eliminar combinaciones de colores defectuosos (es decir, hay reglas para el choque de colores y la elección de colores complementarios).

Te recomiendo que visites la sección de arte de tu biblioteca y que consultes libros sobre teoría del color para comprender mejor qué es un buen color antes de intentar crearlo; parece que ni siquiera sabes por qué ciertas combinaciones funcionan y otras no. t.

-Adán

Adam Davis
fuente
0

Recomiendo encarecidamente usar una función de sombreador CG HSVtoRGB, son increíbles ... le brinda control de color natural como un pintor en lugar de control como un monitor crt, ¡lo cual probablemente no sea!

Esta es una manera de hacer 1 valor flotante. es decir, gris, en 1000 ds de combinaciones de color, brillo y saturación, 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);

¡El resultado es una ALARMA DE COLOR IMPRESIONANTE! no es natural, pero utiliza gradientes de color naturales y se ve orgánico y controlablemente parámetros iridiscentes / pastel.

Para Perlin, puede usar esta función, es una versión rápida en zigzag de 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;
}
comprensible
fuente
0

Aquí hay algo que escribí para un sitio que hice. Generará automáticamente un color de fondo plano aleatorio para cualquier div con la clase .flat-color-gen. Jquery solo se requiere para agregar css a la página; No es necesario para la parte principal de esto, que es el 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);
Efraín
fuente