Algorytm losowego generowania estetycznej palety kolorów [zamknięty]

301

Szukam prostego algorytmu do generowania dużej liczby przypadkowych, estetycznych kolorów. Więc nie ma szalonych neonowych kolorów, kolorów przypominających kał itp.

Znalazłem rozwiązania tego problemu, ale opierają się one na alternatywnych paletach kolorów niż RGB. Wolę po prostu używać prostego RGB niż mapowania tam iz powrotem. Te inne rozwiązania mogą co najwyżej wygenerować tylko 32 lub więcej przyjemnych losowych kolorów.

Wszelkie pomysły byłyby świetne.

Brian Gianforcearo
źródło
2
Zrobiłbym stronę internetową, która generuje losowy kolor przy każdej wizycie. Oddaj głos „ten kolor skał” / „ten kolor jest do bani”. Następnie posortuj według stosunku głosów.
Nosredna
Możesz sprawdzić HSL i HSV.
Jim Keener
48
„kolory przypominające fekalia” Uwielbiam to
lol
To nie jest algorytm.
Matt The Ninja
Dodam komentarz, ponieważ pytanie jest zamknięte. Nie próbowałem tego, ale byłoby interesujące wypróbować fraktal lub procedurę, używając np. Algorytmu lub wariantów przemieszczenia punktu środkowego ( lighthouse3d.com/opengl/terrain/index.php?mpd2 ) lub Perlin Noise, ale zamiast wysokości mieszać komponenty rgb kolorów.
alfoks

Odpowiedzi:

426

Możesz uśrednić wartości RGB losowych kolorów z wartościami stałego koloru:

(przykład w Javie)

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


Mieszanie losowych kolorów z białym (255, 255, 255) tworzy neutralne pastele poprzez zwiększenie jasności przy jednoczesnym zachowaniu odcienia oryginalnego koloru. Te losowo generowane pastele zwykle dobrze do siebie pasują, szczególnie w dużych ilościach.

Oto kilka pastelowych kolorów wygenerowanych przy użyciu powyższej metody:

Pierwszy


Możesz również mieszać losowy kolor ze stałym pastelem, co daje zabarwiony zestaw neutralnych kolorów. Na przykład użycie jasnoniebieskiego tworzy takie kolory:

druga


Idąc dalej, możesz dodać heurystykę do generatora, która uwzględnia uzupełniające się kolory lub poziomy cieniowania, ale wszystko zależy od wrażenia, jakie chcesz osiągnąć za pomocą losowych kolorów.

Niektóre dodatkowe zasoby:

David Crow
źródło
3
Jedynym zastrzeżeniem wydaje się być utrata odróżnialności. Biorąc średnio czerwony zielony i niebieski z jednym kolorem, takim jak biały, naturalnie wszystkie kolory zbliżają się do bieli i zmniejszają różnice między nimi. Na przykład, jeśli spojrzysz na pierwszy zrzut ekranu: kiedy te zielenie są obok siebie, na pewno mogę je rozróżnić, ale co, jeśli nie sąsiadują one z jakąś produkowaną grafiką? To może być problematyczne.
Zelphir Kaltstahl
Generując
87

Chciałbym użyć koła kolorów i przy losowej pozycji można dodać złoty kąt (137,5 stopni)

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

aby za każdym razem uzyskać różne kolory, które się nie nakładają.

Dostosowując jasność koła kolorów, można również uzyskać różne kombinacje jasnych / ciemnych kolorów.

Znalazłem ten post na blogu, który naprawdę dobrze wyjaśnia problem i rozwiązanie za pomocą złotego podziału.

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

AKTUALIZACJA: Właśnie znalazłem inne podejście:

Nazywa się to metodą RYB (czerwona, żółta, niebieska) i jest opisana w tym artykule:

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

jako „Kompozycja kolorów inspirowana farbą”.

Algorytm generuje kolory i każdy nowy kolor jest wybierany, aby zmaksymalizować odległość euklidesową od poprzednio wybranych.

Tutaj znajdziesz dobrą implementację w javascript:

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

AKTUALIZACJA 2:

Sciences Po Medialb właśnie wypuściło narzędzie o nazwie „I Want Hue”, które generuje palety kolorów dla badaczy danych. Używanie różnych przestrzeni kolorów i generowanie palet za pomocą k-średnich grupowania lub wektorów siły (wykresy odpychania) Wyniki tych metod są bardzo dobre, pokazują teorię i implementację na swojej stronie internetowej.

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

Fgblanch
źródło
iWantHue jest odpowiedzią. Idź tam. Zdziw się.
Irongaze.com
23

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

Widziałem pomysł tutaj: http://blog.functionalfun.net/2008/07/random-pastel-colour-generator.html

motobói
źródło
Nie do końca poprawne: musisz również uzupełnić zero cyframi jednocyfrowymi ... W każdym razie, oto działające skrzypce dla osób przeglądających: jsfiddle.net/RedDevil/LLYBQ ----- Zadrapanie ... Nie zrobiłem tego zauważ bit +127 ... Ale to nie wygeneruje ciemnych odcieni.
kumarharsh
2
Pierwotnym pomysłem było wygenerowanie dowolnie przyjemnych kolorów. Ciemne odcienie nie wydają mi się przyjemne;)
motobói
11

Konwersja na inną paletę jest znacznie lepszym sposobem na to. Robią to z tego powodu: inne palety są „percepcyjne” - to znaczy zbliżają do siebie podobne pozorne kolory, a dopasowanie jednej zmiennej zmienia kolor w przewidywalny sposób. Nie dotyczy to RGB, w którym nie ma oczywistej zależności między kolorami, które „pasują do siebie”.

Nick Johnson
źródło
5

Odpowiedzią, której nie należy zapominać, ponieważ jest prosta i ma zalety, jest próbkowanie prawdziwych zdjęć i obrazów. próbkuj tyle losowych pikseli, ile chcesz losowych kolorów na miniaturach zdjęć współczesnej sztuki, Cezanne, Van Gogha, Monneta, zdjęć ... Zaletą jest to, że możesz uzyskać kolory według motywu i że są to kolory organiczne. po prostu umieść 20-30 zdjęć w folderze i za każdym razem losowo próbuj losowe zdjęcie.

Konwersja na wartości HSV jest szeroko rozpowszechnionym algorytmem kodu dla palety opartej na psychologii. hsv jest łatwiejszy do randomizacji.

zrozumiały
źródło
1
mkweb.bcgsc.ca/color_summarizer/?analyze Oto narzędzie online, które może analizować rzeczywiste zdjęcia i powraca do Ciebie Grapher z wartości RGB mówi, że może poczuć, co prawdziwe zdjęcia mają na swoich wykresach ... niezwykle przydatna strona internetowa, która jest niezbędna, jeśli próbujesz zaprojektować awangardowe algorytmy dla losowych
kolorów-
4

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

źródło: https://stackoverflow.com/a/12266311/2875783

Petr Bugyík
źródło
3

Oto szybki i brudny generator kolorów w C # (przy użyciu „podejścia RYB” opisanego w tym artykule ). To przepisanie z JavaScript .

Posługiwać się:

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

Pierwsze dwa kolory wydają się być białe i odcień czerni. Często pomijam je w ten sposób (używając Linq):

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

Realizacja:

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
źródło
Usunąłem
Dylan Watson
3

Metoda Davida Crowa w dwuliniowej wersji 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))
}
Dave_L
źródło
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;
} 

W przypadku pastelu podaj wyższe liczby całkowite ciemne / jasne - tj. FnGetRandomColour (120, 250)

Kredyty: wszystkie kredyty do http://paulirish.com/2009/random-hex-color-code-snippets/ stackoverflow.com/questions/12043187/how-to-check-if-hex-color-is-too-black

ChilledFlame
źródło
1

Adaptacja JavaScriptu oryginalnej odpowiedzi Davida Crowa, w tym kod IE i 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) + ')';
}

Uruchom funkcję, używając:

generateRandomComplementaryColor(240, 240, 240);
Sceptyk
źródło
1

Używaj wyraźnych kolorów .

Napisane w javascript.

Generuje paletę wizualną wyraźnych kolorów.

wyraźne kolory są wysoce konfigurowalne:

  • Wybierz, ile kolorów jest w palecie
  • Ogranicz odcień do określonego zakresu
  • Ogranicz nasycenie (nasycenie) do określonego zakresu
  • Ogranicz lekkość do określonego zakresu
  • Skonfiguruj ogólną jakość palety
InternalFX
źródło
0

możesz mieć ich jasność. które nieco kontrolowałyby ilość „neonowych” kolorów. na przykład, jeśli „jasność”

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

mieścił się w pewnej wysokiej granicy, miałby sprany, jasny kolor. I odwrotnie, gdyby znajdował się w pewnym dolnym zakresie, byłby ciemniejszy. Wyeliminowałoby to wszelkie zwariowane, wyróżniające się kolory, a jeśli wybierzesz granicę naprawdę wysoko lub bardzo nisko, wszystkie byłyby dość zbliżone do bieli lub czerni.

cześć
źródło
0

Algorytm będzie trudny do uzyskania, czego chcesz - ludzie od dawna studiują teorię kolorów, a nawet nie znają wszystkich zasad.

Istnieją jednak pewne reguły, których można użyć do wyeliminowania złych kombinacji kolorów (tj. Istnieją zasady dotyczące kolidowania kolorów i wybierania kolorów uzupełniających).

Polecam odwiedzić sekcję artystyczną biblioteki i zapoznać się z książkami na temat teorii kolorów, aby lepiej zrozumieć, co jest dobrym kolorem, zanim spróbujesz go stworzyć - wydaje się, że możesz nawet nie wiedzieć, dlaczego niektóre kombinacje działają, a inne nie t.

-Adam

Adam Davis
źródło
0

Zdecydowanie polecam użycie funkcji cieniowania CG HSVtoRGB, są niesamowite ... daje naturalną kontrolę kolorów jak malarz zamiast kontroli jak monitor CRT, co prawdopodobnie nie jest!

Jest to sposób na uzyskanie 1 wartości zmiennoprzecinkowej. tj. szary, na 1000 ds kombinacji kolorów, jasności i nasycenia itp .:

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

wynikiem jest NIESAMOWITE RANDOMIZACJA KOLORÓW! nie jest naturalny, ale wykorzystuje naturalne gradienty kolorów i wygląda organicznie i kontroluje parametry opalizujące / pastelowe.

W przypadku perlina możesz użyć tej funkcji, jest to szybka wersja zig zag perlina.

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;
}
zrozumiały
źródło
0

Oto coś, co napisałem dla witryny, którą wykonałem. Automatycznie wygeneruje losowy płaski kolor tła dla dowolnej div z klasą .flat-color-gen. Jquery jest wymagane tylko w celu dodania css do strony; nie jest to wymagane w głównej części tego, jaką jest generateFlatColorWithOrder()metoda.

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);
Efraim
źródło