Алгоритм случайного генерирования эстетически приятной цветовой палитры [закрыто]


301

Я ищу простой алгоритм для генерации большого количества случайных, эстетически приятных цветов. Так что без сумасшедших неоновых цветов, цветов, напоминающих фекалии и т. Д.

Я нашел решение этой проблемы, но они полагаются на альтернативные цветовые палитры, чем RGB. Я бы предпочел просто использовать прямой RGB, а не отображать туда-сюда. Эти другие решения также могут генерировать не более 32 приятных случайных цветов.

Любые идеи будут великолепны.


2
Я бы сделал сайт, который генерирует случайный цвет при каждом посещении. Имейте голос "этот цвет камней" / "этот цвет отстой". Затем сортируйте по соотношению голосов.
Носредна

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

48
"цвета, напоминающие о фекалиях", я люблю это
LOL

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

Я добавлю комментарий, так как вопрос закрыт. Я не пробовал, но интересно было бы попробовать фрактальный или процедурный способ, с помощью т.е. MidPoint Displacement алгоритма или варианты ( lighthouse3d.com/opengl/terrain/index.php?mpd2 ) или Перлин шума, но вместо высоты смешать компоненты 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-programmatically/

ОБНОВЛЕНИЕ: я только что нашел этот другой подход:

Он называется RYB (красный, желтый, синий) и описан в этой статье:

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

как "Paint Inspired Color Compositing".

Алгоритм генерирует цвета, и каждый новый цвет выбирается так, чтобы максимизировать его евклидово расстояние до ранее выбранных.

Здесь вы можете найти хорошую реализацию в javascript:

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

ОБНОВЛЕНИЕ 2:

Наука Po Medialb только что выпустила инструмент под названием «Я хочу Hue», который генерирует цветовые палитры для ученых данных. Использование различных цветовых пространств и создание палитр с помощью кластеризации 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 ... Но тогда это не будет генерировать темные оттенки.
kumarharsh

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

11

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


6

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

TriadMixing + CIE94


5

Ответ, который не следует упускать из виду, поскольку он прост и дает преимущества, - это выборка реальных фотографий и картин. Сэмплируйте столько произвольных пикселей, сколько вы хотите, чтобы случайные цвета отображались на миниатюрах современных художественных фотографий: Сезанн, Ван Гог, Моне, фотографии ... Преимущество заключается в том, что вы можете получать цвета по темам, и они являются органическими цветами. просто поместите 20 - 30 фото в папку и случайный образец каждый раз.

Преобразование в значения HSV является широко распространенным алгоритмом кода для психологически обоснованной палитры. HSV легче рандомизировать.


1
mkweb.bcgsc.ca/color_summarizer/?analyze Вот онлайн-инструмент, который может анализировать реальные фотографии и возвращать вам. График значений RGB говорит о том, что можно получить представление о реальных фотографиях на их графиках .... чрезвычайно полезный веб-сайт, который необходим, если вы пытаетесь разработать авангардные алгоритмы для случайных цветов
com.prehensible


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, они потрясающие ... они дают вам естественное управление цветом, как у художника, а не как у монитора с ЭЛТ, что, по-видимому, не так!

Это способ сделать 1 значение с плавающей запятой. то есть серый, в 1000 ds комбинаций цвета и яркости и насыщенности и т. д .:

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, вы можете использовать эту функцию, это быстрый зигзаг версия 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

Вот что я написал для сайта, который я сделал. Это автоматически сгенерирует случайный плоский цвет фона для любого div с классом .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.