Алгоритм випадкового генерування естетично приємної палітри кольорів [закрито]


301

Я шукаю простий алгоритм для створення великої кількості випадкових, естетично приємних кольорів. Тож ніяких божевільних неонових кольорів, кольорів, що нагадують кал тощо.

Я знайшов рішення цієї проблеми, але вони покладаються на альтернативні кольорові палітри, ніж RGB. Я б скоріше просто скористався прямим RGB, ніж картографувати туди і назад. Ці інші рішення також можуть створювати лише 32 приємні випадкові кольори.

Будь-які ідеї були б чудовими.


2
Я б створив веб-сайт, який генерує випадковий колір при кожному відвідуванні. Проведіть голосування "цей колір скелі" / "цей колір смокче". Потім сортуйте за співвідношенням голосів.
Nosredna

Ви можете перевірити HSL та HSV.
Джим Кінер

48
"кольори, що нагадують кал" Я люблю це
lol

Це не алгоритм.
Метт Ніндзя

Я додам коментар, оскільки питання закрите. Я не пробував цього, але було б цікаво спробувати фрактальний або процедурний спосіб, використовуючи алгоритм або варіанти Midpoint Displacement (варіанти lighthouse3d.com/opengl/terrain/index.php?mpd2 ) або Perlin Noise, але замість висоти змішати rgb компоненти кольорів.
alfoks

Відповіді:


426

Можна порівняти значення RGB випадкових кольорів із значеннями постійного кольору:

(приклад на 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;
}


Змішування випадкових кольорів з білим (255, 255, 255) створює нейтральні пастелі, збільшуючи легкість, зберігаючи відтінок початкового кольору. Ці пастелі, що генеруються випадковим чином, зазвичай добре поєднуються, особливо у великій кількості.

Ось кілька пастельних кольорів, створених за допомогою описаного вище способу:

Спочатку


Ви також можете змішати випадковий колір з постійною пастеллю, що призводить до тонованого набору нейтральних кольорів. Наприклад, за допомогою світло-синього кольору створюються такі кольори:

Друге


Подальше, ви можете додати евристику до свого генератора, яка б враховувала додаткові кольори або рівні затінення, але все залежить від враження, яке ви хочете досягти від своїх випадкових кольорів.

Деякі додаткові ресурси:


3
Єдиним застереженням, здається, є втрата відмінності. Приймаючи в середньому червоний зелений і синій з одним кольором, таким як білий, природно, всі кольори наближаються до білого і зменшують відмінності між ними. Наприклад, якщо ви подивитесь на перший скріншот: Коли ці зелені знаходяться поруч, я, безумовно, можу їх розрізнити, але що робити, якщо вони не сусідять у створеній графіці? Це може бути проблематично.
Зельфір Кальтшталь

Створюючи випадковий кольоровий компонент, спробуйте обмежити верхню межу чимось меншим, як-от 200.
Nickolodeon

87

Я б використовував кольорове колесо і з урахуванням випадкового положення ви можете додати золотий кут (137,5 градусів)

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

щоб кожен раз отримувати різні кольори, які не перетинаються.

Регулюючи яскравість кольорового колеса, ви також можете отримати різні поєднання яскравих / темних кольорів.

Я знайшов цю публікацію в блозі, яка дуже добре пояснює проблему та рішення з використанням золотого співвідношення.

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

ОНОВЛЕННЯ: Я щойно знайшов такий інший підхід:

Він називається методом RYB (червоний, жовтий, синій), і він описаний у цій роботі:

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

як "Композиція кольорів, натхненних фарбою".

Алгоритм генерує кольори, і кожен новий колір вибирається, щоб максимально збільшити його евклідову відстань до раніше вибраних.

Тут ви можете знайти гарну реалізацію в javascript:

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

ОНОВЛЕННЯ 2:

Науки Po Medialb щойно випустили інструмент під назвою "Я хочу відтінку", який генерує кольорову палітру для науковців даних. Використання різних кольорових просторів та генерування палітри за допомогою k-засобів кластеризації чи векторів сили (графіки відштовхування) Результати цих методів дуже хороші, вони показують теорію та реалізацію на своїй веб-сторінці.

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


iWantHue - це відповідь. Іди туди. Дивуйтеся.
Irongaze.com

23

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

Ідею побачили тут: http://blog.functionalfun.net/2008/07/random-pastel-colour-generator.html


Не зовсім коректно: для одноцифрових чисел також потрібно нульове заміщення ... У будь-якому випадку, тут є робоча загадка для глядачів: jsfiddle.net/RedDevil/LLYBQ ----- Подрастуйте, що ... Я не помічайте +127 біт ... Але тоді це не створить темних відтінків.
кумархарш

2
Початкова ідея полягала у створенні довільно приємних кольорів. Темні відтінки мені не здаються приємними;)
motobói

11

Перетворення на іншу палітру - це набагато кращий спосіб зробити це. Це є причиною, що вони роблять так: інші палітри є «перцептивними» - тобто вони складають схожі кольори, здавалося б, близько один до одного, і, регулюючи одну змінну, змінює колір передбачувано. Нічого цього не стосується RGB, де немає очевидних зв’язків між кольорами, які "добре йдуть разом".


6

Я мав успіх у використанні TriadMixing та CIE94, щоб уникнути подібних кольорів. На наступному зображенні використовуються кольори введення червоний, жовтий та білий. Дивіться тут .

TriadMixing + CIE94


5

Відповідь, яку не слід оминути увагою, адже вона проста і дає переваги, - вибірки фотографій та картин із реального життя. виберіть стільки випадкових пікселів, скільки вам потрібно, щоб випадкові кольори були на ескізах зображень сучасного мистецтва, сезанн, ван гог, моне, фотографій ... Перевага полягає в тому, що ви можете отримати кольори за темою, а також те, що вони є органічними кольорами. просто помістіть 20 - 30 фотографій у папку і кожен раз довільно вибирайте випадкову картинку.

Перетворення на значення HSV - це широко розповсюджений алгоритм коду для психологічно обґрунтованої палітри. hsv простіше рандомізувати.


1
mkweb.bcgsc.ca/color_summarizer/?analyze Ось онлайн-інструмент, який може аналізувати фотографії в реальному житті та повертається до вас. надзвичайно корисний веб-сайт, який дуже важливий, якщо ви намагаєтеся створити авангардні алгоритми для випадкових кольорів
com. Razonvable


3

Ось швидкий і брудний генератор кольорів у C # (використовуючи "підхід RYB", описаний у цій статті ). Це перезапис з JavaScript .

Використання:

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

Перші два кольори, як правило, білий і відтінок чорного. Я часто пропускаю їх так (використовуючи Linq):

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

Впровадження:

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

Я видалив відповідь на Java, але, якщо потрібно, версію Java можна побачити в цьому Gist: gist.github.com/lotsabackscatter/3f6a658fd7209e010dad
Ділан Уотсон,

3

Метод Девіда Кроу в двоколірній 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))
}

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

Для пастелі переведіть темні / світлі цілі числа вищого луми - тобто fnGetRandomColour (120, 250)

Кредити: всі кредити на http://paulirish.com/2009/random-hex-color-code-snippets/ stackoverflow.com/questions/12043187/how-to-check-if-hex-color-is-too-black


1

Адаптація JavaScript в оригінальній відповіді Девіда Кроу, специфічний код IE та 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) + ')';
}

Запустіть функцію за допомогою:

generateRandomComplementaryColor(240, 240, 240);

1

Використовуйте різні кольори .

Написано у JavaScript.

Це генерує палітру візуально чітких кольорів.

чіткі кольори можна налаштувати:

  • Виберіть кількість кольорів у палітрі
  • Обмежте відтінок певним діапазоном
  • Обмежте кольоровість (насиченість) певним діапазоном
  • Обмежте світлоту на певний діапазон
  • Налаштуйте загальну якість палітри

0

ви могли б мати їх у певній яскравості. що трохи контролювало б кількість "неонових" кольорів. наприклад, якщо "яскравість"

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

був у певній високій межі, він мав би вимитий, світлий колір. І навпаки, якби це було в межах певної низької межі, було б темніше. Це дозволить усунути будь-які божевільні, видатні кольори, і якби ви вибрали обв'язаний дійсно високий або дійсно низький, всі вони будуть досить близькими до білого або чорного.


0

Отримати те, що потрібно алгоритмічно, буде важко - люди давно вивчають теорію кольорів, і навіть не знають усіх правил.

Однак є деякі правила, які ви можете використовувати для зменшення поганих поєднань кольорів (тобто є правила для поєднання кольорів та вибору додаткових кольорів).

Я рекомендую вам відвідати розділ мистецтв вашої бібліотеки та ознайомитись з книгами з теорії кольорів, щоб краще зрозуміти, що таке хороший колір, перш ніж спробувати його зробити - здається, ви можете навіть не знати, чому деякі комбінації працюють, а інші - ні " т.

-Адам


0

Я настійно рекомендую використовувати функцію шейдера CG HSVtoRGB, вони приголомшливі ... це дає вам природний контроль кольору, як художник, а не контроль, як монітор crt, який ви, напевно, не маєте!

Це спосіб зробити значення 1 float. тобто сірий, на 1000 дб комбінацій кольору, яскравості та насиченості тощо:

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

результат - ДОВІДНА РАНДОМИЗАЦІЯ КОЛЬОРУ! Це не природно, але він використовує природні градієнти кольору, і він виглядає органічно і керуючим ірисцентним / пастельним параметрами.

Для perlin ви можете скористатися цією функцією, це швидка версія zig zag 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

Ось щось я написав для сайту, який я зробив. Він автоматично генерує випадковий плоский колір фону для будь-якого діла з класом .flat-color-gen. Jquery потрібен лише для додавання css на сторінку; не потрібно для основної частини цього, що є generateFlatColorWithOrder()методом.

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);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.