Algorithme pour générer aléatoirement une palette de couleurs esthétiquement agréable [fermé]

301

Je recherche un algorithme simple pour générer un grand nombre de couleurs aléatoires et esthétiques. Donc pas de couleurs fluo folles, des couleurs qui rappellent les matières fécales, etc.

J'ai trouvé des solutions à ce problème mais elles s'appuient sur des palettes de couleurs alternatives à RVB. Je préfère simplement utiliser le RVB droit que le mappage d'avant en arrière. Ces autres solutions peuvent également générer au maximum 32 couleurs aléatoires agréables.

Toutes les idées seraient géniales.

Brian Gianforcaro
la source
2
Je créerais un site Web qui génère une couleur aléatoire à chaque visite. Ayez un vote «cette couleur bascule» / «cette couleur craint». Triez ensuite par rapport au nombre de votes.
Nosredna
Vous pouvez consulter HSL et HSV.
Jim Keener
48
"couleurs rappelant les matières fécales" Je l'adore
lol
Ce n'est pas un algorithme.
Matt The Ninja
J'ajouterai un commentaire car la question est fermée. Je ne l'ai pas essayé, mais il serait intéressant d'essayer une méthode fractale ou procédurale, en utilisant par exemple l'algorithme ou les variantes de déplacement médian ( lighthouse3d.com/opengl/terrain/index.php?mpd2 ) ou Perlin Noise, mais au lieu des hauteurs mélanger les composants RVB des couleurs.
alfoks

Réponses:

426

Vous pouvez faire la moyenne des valeurs RVB de couleurs aléatoires avec celles d'une couleur constante:

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


Le mélange de couleurs aléatoires avec du blanc (255, 255, 255) crée des pastels neutres en augmentant la luminosité tout en conservant la teinte de la couleur d'origine. Ces pastels générés aléatoirement vont généralement bien ensemble, surtout en grand nombre.

Voici quelques couleurs pastel générées à l'aide de la méthode ci-dessus:

Première


Vous pouvez également mélanger la couleur aléatoire avec un pastel constant, ce qui donne un ensemble teinté de couleurs neutres. Par exemple, l'utilisation d'un bleu clair crée des couleurs comme celles-ci:

Seconde


En allant plus loin, vous pouvez ajouter des heuristiques à votre générateur qui prennent en compte des couleurs complémentaires ou des niveaux d'ombrage, mais tout dépend de l'impression que vous souhaitez obtenir avec vos couleurs aléatoires.

Quelques ressources supplémentaires:

David Crow
la source
3
La seule mise en garde semble être la perte de distinction. En prenant la moyenne du vert rouge et du bleu avec une seule couleur comme le blanc, naturellement toutes les couleurs se rapprochent du blanc et réduisent les différences entre elles. Par exemple, si vous regardez la première capture d'écran: Lorsque ces verts sont côte à côte, je peux certainement les distinguer, mais que se passe-t-il s'ils ne sont pas adjacents dans un graphique produit? Cela pourrait être problématique.
Zelphir Kaltstahl
Lorsque vous générez un composant de couleur aléatoire, essayez de restreindre la limite supérieure avec quelque chose de moins, comme 200.
Nickolodeon
87

J'utiliserais une roue chromatique et étant donné une position aléatoire, vous pourriez ajouter l'angle d'or (137,5 degrés)

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

afin d'obtenir à chaque fois des couleurs différentes qui ne se chevauchent pas.

En ajustant la luminosité de la roue chromatique, vous pouvez également obtenir différentes combinaisons de couleurs claires / sombres.

J'ai trouvé ce billet de blog qui explique très bien le problème et la solution en utilisant le nombre d'or.

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

MISE À JOUR: Je viens de trouver cette autre approche:

C'est ce qu'on appelle la méthode RYB (rouge, jaune, bleu) et elle est décrite dans cet article:

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

comme "Compositing couleur inspiré de la peinture".

L'algorithme génère les couleurs et chaque nouvelle couleur est choisie pour maximiser sa distance euclidienne par rapport à celles précédemment sélectionnées.

Ici vous pouvez trouver une bonne implémentation en javascript:

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

MISE À JOUR 2:

Le Sciences Po Medialb vient de sortir un outil appelé "I want Hue" qui génère des palettes de couleurs pour les data scientists. Utiliser différents espaces colorimétriques et générer les palettes en utilisant le clustering k-means ou des vecteurs de force (graphiques de répulsion) Les résultats de ces méthodes sont très bons, ils montrent la théorie et une implémentation dans leur page web.

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

Fgblanch
la source
iWantHue est la réponse. Va là-bas. Être surpris.
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;
}

J'ai vu l'idée ici: http://blog.functionalfun.net/2008/07/random-pastel-colour-generator.html

motobói
la source
Pas tout à fait correct: vous devez également mettre à zéro pour les nombres à un chiffre ... Quoi qu'il en soit, voici un violon qui fonctionne pour les spectateurs: jsfiddle.net/RedDevil/LLYBQ ----- Scratch that ... I did not remarquez le bit +127 ... Mais cela ne générera pas de nuances sombres.
kumarharsh
2
L'idée originale était de générer des couleurs arbitrairement agréables. Les teintes sombres ne me semblent pas agréables;)
motobói
11

La conversion vers une autre palette est un moyen bien supérieur de procéder. Il y a une raison pour laquelle ils le font: d'autres palettes sont «perceptuelles» - c'est-à-dire qu'elles rapprochent les couleurs similaires, et l'ajustement d'une variable change la couleur de manière prévisible. Rien de tout cela n'est vrai pour RGB, où il n'y a pas de relation évidente entre les couleurs qui "vont bien ensemble".

Nick Johnson
la source
6

J'ai réussi à utiliser TriadMixing et CIE94 pour éviter des couleurs similaires. L'image suivante utilise les couleurs d'entrée rouge, jaune et blanc. Voyez ici .

TriadMixing + CIE94

Moriarty
la source
5

Une réponse à ne pas négliger, car elle est simple et présente des avantages, est l'échantillonnage de photos et de peintures réelles. échantillonnez autant de pixels aléatoires que vous voulez de couleurs aléatoires sur les miniatures de photos d'art moderne, cézanne, van gogh, monnet, photos ... l'avantage est que vous pouvez obtenir des couleurs par thème et que ce sont des couleurs organiques. mettez simplement 20 à 30 photos dans un dossier et échantillonnez au hasard une photo aléatoire à chaque fois.

La conversion en valeurs HSV est un algorithme de code répandu pour une palette à base psychologique. hsv est plus facile à randomiser.

compréhensible
la source
1
mkweb.bcgsc.ca/color_summarizer/?analyze Voici un outil en ligne qui peut analyser des photos réelles et vous renvoie Le graphique des valeurs RVB dit peut avoir une idée de ce que les photos réelles ont dans leurs graphiques .... site extrêmement utile, indispensable si vous essayez de concevoir des algorithmes d'avant-garde pour des couleurs aléatoires-
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;
}

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

Petr Bugyík
la source
3

Voici un générateur de couleurs rapide et sale en C # (en utilisant «l'approche RYB» décrite dans cet article ). C'est une réécriture de JavaScript .

Utilisation:

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

Les deux premières couleurs ont tendance à être blanches et une nuance de noir. Je les saute souvent comme ça (en utilisant Linq):

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

La mise en oeuvre:

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
la source
J'ai supprimé la réponse Java mais si nécessaire, la version Java peut être vue dans ce Gist: gist.github.com/lotsabackscatter/3f6a658fd7209e010dad
Dylan Watson
3

La méthode de David Crow dans un R à deux lignes:

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

Pour le pastel, passez des nombres entiers luma / luma supérieurs - c.-à-d. FnGetRandomColour (120, 250)

Crédits: tous les crédits à http://paulirish.com/2009/random-hex-color-code-snippets/ stackoverflow.com/questions/12043187/how-to-check-if-hex-color-is-too-black

ChilledFlame
la source
1

Adaptation JavaScript de la réponse originale de David Crow, IE et code spécifique Nodejs inclus.

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

Exécutez la fonction en utilisant:

generateRandomComplementaryColor(240, 240, 240);
Sceptique
la source
1

Utilisez des couleurs distinctes .

Écrit en javascript.

Il génère une palette de couleurs visuellement distinctes.

distinct-colors est hautement configurable:

  • Choisissez le nombre de couleurs dans la palette
  • Restreindre la teinte à une plage spécifique
  • Restreindre la chrominance (saturation) à une plage spécifique
  • Restreindre la légèreté à une plage spécifique
  • Configurer la qualité générale de la palette
InternalFX
la source
0

vous pourriez les avoir dans une certaine luminosité. cela contrôlerait un peu la quantité de couleurs "néon". par exemple, si la "luminosité"

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

était dans une certaine limite élevée, il aurait une couleur claire délavée. Inversement, si elle se situait dans une certaine limite basse, elle serait plus sombre. Cela éliminerait toutes les couleurs folles et remarquables et si vous choisissez une limite vraiment haute ou très basse, elles seraient toutes assez proches du blanc ou du noir.

bonjour
la source
0

Il va être difficile d'obtenir ce que vous voulez algorithmiquement - les gens étudient la théorie des couleurs depuis longtemps et ils ne connaissent même pas toutes les règles.

Cependant, il existe certaines règles que vous pouvez utiliser pour éliminer les mauvaises combinaisons de couleurs (c'est-à-dire qu'il existe des règles pour s'affronter les couleurs et choisir des couleurs complémentaires).

Je vous recommande de visiter la section d'art de votre bibliothèque et de consulter des livres sur la théorie des couleurs pour mieux comprendre ce qu'est une bonne couleur avant d'essayer d'en créer une - il semble que vous ne sachiez même pas pourquoi certaines combinaisons fonctionnent et d'autres ne fonctionnent pas. t.

-Adam

Adam Davis
la source
0

Je recommande fortement d'utiliser une fonction de shader CG HSVtoRGB, ils sont géniaux ... cela vous donne un contrôle des couleurs naturel comme un peintre au lieu d'un contrôle comme un moniteur CRT, ce que vous n'êtes probablement pas!

C'est une façon de faire 1 valeur flottante. c'est-à-dire gris, en 1000 ds de combinaisons de couleurs et de luminosité et de saturation, 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);

le résultat est UNE RANDOMISATION DE COULEUR IMPRESSIONNANTE! ce n'est pas naturel, mais il utilise des dégradés de couleurs naturelles et il a l'air de paramètres organiques et contrôlables irisés / pastels.

Pour perlin, vous pouvez utiliser cette fonction, c'est une version rapide en zig zag 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;
}
compréhensible
la source
0

Voici quelque chose que j'ai écrit pour un site que j'ai fait. Il générera automatiquement une couleur de fond plate aléatoire pour toute div avec la classe .flat-color-gen. Jquery n'est requis que pour ajouter du CSS à la page; ce n'est pas nécessaire pour la partie principale de cela, qui est la generateFlatColorWithOrder()méthode.

Lien 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);
Ephraim
la source