Algoritmo per generare casualmente una tavolozza di colori esteticamente gradevole [chiuso]


301

Sto cercando un semplice algoritmo per generare un gran numero di colori casuali, esteticamente gradevoli. Quindi niente pazzi colori al neon, colori che ricordano le feci, ecc.

Ho trovato soluzioni a questo problema, ma si basano su tavolozze di colori alternative rispetto a RGB. Preferirei semplicemente usare RGB diretto piuttosto che mappare avanti e indietro. Queste altre soluzioni possono anche generare al massimo solo 32 colori casuali piacevoli.

Qualunque idea sarebbe apprezzata.


2
Realizzerei un sito Web che genera un colore casuale ad ogni visita. Avere un voto "this color rocks" / "this color sucks". Quindi ordina in base al rapporto dei voti.
Nosredna,

Puoi dare un'occhiata a HSL e HSV.
Jim Keener

48
"colori che ricordano le feci" Lo adoro
lol

Questo non è un algoritmo.
Matt The Ninja,

Aggiungerò un commento poiché la domanda è chiusa. Non l'ho provato, ma sarebbe interessante provare un modo frattale o procedurale, usando l'algoritmo o le varianti di spostamento del punto medio ( lighthouse3d.com/opengl/terrain/index.php?mpd2 ) o Perlin Noise, ma invece delle altezze per mescolare i componenti rgb dei colori.
Alfoks

Risposte:


426

È possibile calcolare la media dei valori RGB di colori casuali con quelli di un colore costante:

(esempio in 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;
}


Mischiando i colori casuali con il bianco (255, 255, 255) si creano pastelli neutri aumentando la luminosità mantenendo la tonalità del colore originale. Questi pastelli generati casualmente di solito vanno bene insieme, specialmente in grandi numeri.

Ecco alcuni colori pastello generati usando il metodo sopra:

Primo


Puoi anche mescolare il colore casuale con un pastello costante, che si traduce in un insieme colorato di colori neutri. Ad esempio, l'uso di un azzurro crea colori come questi:

Secondo


Andando oltre, potresti aggiungere euristiche al tuo generatore che tengano conto dei colori complementari o dei livelli di ombreggiatura, ma tutto dipende dall'impressione che vuoi ottenere con i tuoi colori casuali.

Alcune risorse aggiuntive:


3
L'unica avvertenza sembra essere la perdita di distinguibilità. Prendendo la media di rosso verde e blu con un colore come il bianco, naturalmente tutti i colori si avvicinano al bianco e riducono le differenze tra loro. Ad esempio, se guardi il primo screenshot: quando quei verdi sono uno accanto all'altro, sicuramente li posso distinguere, ma cosa succede se non sono adiacenti in qualche elemento grafico prodotto? Potrebbe essere problematico.
Zelphir Kaltstahl

Quando si genera un componente colore casuale, provare a limitare il limite superiore con qualcosa di meno, come 200.
Nickolodeon

87

Vorrei usare una ruota dei colori e data una posizione casuale potresti aggiungere l'angolo d'oro (137,5 gradi)

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

per ottenere colori diversi ogni volta che non si sovrappongono.

Regolando la luminosità della ruota dei colori è possibile ottenere anche diverse combinazioni di colori chiaro / scuro.

Ho trovato questo post sul blog che spiega molto bene il problema e la soluzione usando la sezione aurea.

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

AGGIORNARE: ho appena trovato questo altro approccio:

Si chiama metodo RYB (rosso, giallo, blu) ed è descritto in questo documento:

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

come "Paint Inspired Color Compositing".

L'algoritmo genera i colori e ogni nuovo colore viene scelto per massimizzare la sua distanza euclidea da quelli precedentemente selezionati.

Qui puoi trovare una buona implementazione in javascript:

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

AGGIORNAMENTO 2:

Sciences Po Medialb ha appena rilasciato uno strumento chiamato "Voglio la tonalità" che genera palette di colori per i data scientist. Usando diversi spazi colore e generando le tavolozze usando il clustering k-mean o i vettori di forza (grafici di repulsione) I risultati di questi metodi sono molto buoni, mostrano la teoria e un'implementazione nella loro pagina web.

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


iWantHue è la risposta. Vai lì. Essere stupito.
Irongaze.com

23

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

Ho visto l'idea qui: http://blog.functionalfun.net/2008/07/random-pastel-colour-generator.html


Non completamente corretto: è necessario zero-padding anche per i numeri a una cifra ... Comunque, ecco un violino funzionante per gli osservatori: jsfiddle.net/RedDevil/LLYBQ ----- Gratta che ... Non ho nota il bit +127 ... Ma questo non genererà sfumature scure.
Kumarharsh,

2
L'idea originale era quella di generare colori arbitrariamente piacevoli. Le tonalità scure non mi sembrano piacevoli;)
motobói

11

La conversione in un'altra tavolozza è un modo di gran lunga superiore per farlo. C'è una ragione per cui lo fanno: le altre tavolozze sono "percettive", ovvero mettono vicini colori apparenti simili e regolando una variabile si cambia il colore in modo prevedibile. Niente di tutto ciò è vero per RGB, dove non esiste una relazione evidente tra i colori che "vanno bene insieme".


6

Ho avuto successo usando TriadMixing e CIE94 per evitare colori simili. L'immagine seguente utilizza i colori di input rosso, giallo e bianco. Vedi qui .

TriadMixing + CIE94


5

Una risposta da non trascurare, perché è semplice e presenta vantaggi, è il campionamento di foto e dipinti della vita reale. campiona tutti i pixel casuali che vuoi sui colori casuali sulle anteprime di immagini di arte moderna, cezanne, van gogh, monnet, foto ... il vantaggio è che puoi ottenere colori per tema e che sono colori organici. basta inserire 20-30 foto in una cartella e campionare casualmente una foto casuale ogni volta.

La conversione in valori HSV è un algoritmo di codice diffuso per una tavolozza psicologicamente basata. hsv è più facile da randomizzare.


1
mkweb.bcgsc.ca/color_summarizer/?analyze Ecco uno strumento online in grado di analizzare le foto della vita reale e tornare a te Grapher dei valori RGB dice che può avere un'idea di ciò che le foto della vita reale hanno nei loro grafici .... sito web estremamente utile, che è essenziale se stai cercando di progettare algoritmi d'avanguardia per colori
casuali-

4

In 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

Ecco un generatore di colori veloce e sporco in C # (usando "l'approccio RYB" descritto in questo articolo ). È una riscrittura da JavaScript .

Uso:

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

I primi due colori tendono ad essere bianco e una sfumatura di nero. Li salto spesso in questo modo (usando Linq):

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

Implementazione:

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

Ho rimosso la risposta Java, ma se necessario, la versione Java può essere vista in questo Gist: gist.github.com/lotsabackscatter/3f6a658fd7209e010dad
Dylan Watson,

3

Il metodo di David Crow in una R-liner doppia:

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

Per il pastello, passa a interi di luce / buio più alti della luma - cioè fnGetRandomColour (120, 250)

Crediti: tutti i crediti a http://paulirish.com/2009/random-hex-color-code-snippets/ stackoverflow.com/questions/12043187/how-to-check-if-hex-color-is-too-black


1

Adattamento JavaScript della risposta originale di David Crow, codice IE e Nodejs specifici inclusi.

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) + ')';
}

Esegui la funzione utilizzando:

generateRandomComplementaryColor(240, 240, 240);

1

Usa colori diversi .

Scritto in JavaScript.

Genera una tavolozza visivamente distinti.

i colori distinti è altamente configurabile:

  • Scegli quanti colori ci sono nella tavolozza
  • Limitare la tonalità a un intervallo specifico
  • Limitare il chroma (saturazione) a un intervallo specifico
  • Limitare la leggerezza a un intervallo specifico
  • Configura la qualità generale della tavolozza

0

potresti averli entro una certa luminosità. controllerebbe un po 'la quantità di colori "neon". per esempio, se la "luminosità"

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

era entro un certo limite alto, avrebbe un colore sbiadito e chiaro. Al contrario, se fosse entro un certo limite inferiore, sarebbe più scuro. Ciò eliminerebbe tutti i colori pazzi e straordinari e se scegliessi un limite molto alto o molto basso, sarebbero tutti abbastanza vicini al bianco o al nero.


0

Sarà difficile ottenere ciò che desideri in modo algoritmico: le persone studiano la teoria del colore da molto tempo e non conoscono nemmeno tutte le regole.

Tuttavia, ci sono alcuni regole che puoi usare per eliminare le combinazioni di colori sbagliate (ad esempio, ci sono regole per scontrarsi con i colori e scegliere colori complementari).

Ti consiglierei di visitare la sezione artistica della tua biblioteca e di leggere libri sulla teoria del colore per ottenere una migliore comprensione di ciò che è un buon colore prima di provare a crearne uno - sembra che potresti non sapere perché alcune combinazioni funzionano e altre no " t.

-Adamo


0

Consiglio vivamente di usare una funzione shader CG HSVtoRGB, sono fantastici ... ti dà il controllo del colore naturale come un pittore invece del controllo come un monitor crt, che presumibilmente non sei!

Questo è un modo per fare 1 valore float. cioè grigio, in 1000 ds di combinazioni di colore, luminosità e saturazione ecc:

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

il risultato è UNA RANDOMIZZAZIONE COLORE ECCEZIONALE! non è naturale ma utilizza sfumature di colore naturali e sembra parametri organici e controllabili in modo irridescente / pastello.

Per perlin, puoi usare questa funzione, è una versione veloce a zig zag di 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

Ecco qualcosa che ho scritto per un sito che ho realizzato. Genererà automaticamente un colore di sfondo piatto casuale per qualsiasi div con la classe .flat-color-gen. Jquery è richiesto solo allo scopo di aggiungere css alla pagina; non è richiesto per la parte principale di questo, che è il generateFlatColorWithOrder()metodo.

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);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.