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

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

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

любые идеи были бы здорово.

16 ответов


вы можете усреднить значения 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) создает нейтральные пастели, увеличивая легкость при сохранении оттенка исходного цвета. Эти случайно сгенерированные пастели обычно хорошо сочетаются, особенно в большом количестве.

вот некоторые пастельные цвета, созданные с использованием выше метод:

First


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

Second


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

дополнительные материалы:


Я бы использовал цветовое колесо и, учитывая случайное положение, вы могли бы добавить золотой угол (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

как "краска вдохновила цвет композитинга".

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

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

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

обновление 2:

Sciences Po Medialb только что выпустили инструмент под названием" Я хочу оттенок", который генерирует цветовые палитры для ученых данных. Использование различных цветовых пространств и генерация палитр с помощью кластеризации k-средних или силовые векторы (графики отталкивания) результаты этих методов очень хороши, они показывают теорию и реализацию на своей веб-странице.

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


в 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


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


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

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


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

источник:https://stackoverflow.com/a/12266311/2875783


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

TriadMixing + CIE94


вот быстрый и грязный генератор цвета в 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]));
        }
    }
}

метод Дэвида Кроу в двухстрочном 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))
}

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


JavaScript-адаптация оригинального ответа Дэвида Кроу, т. е. и конкретный код 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);

вы могли бы иметь их в пределах определенной яркости. это немного контролировало бы количество "неоновых" цветов. например, если "яркость"

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

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


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

, есть некоторые правила, которые вы можете использовать для отбраковки плохих цветовых комбинаций (т. е. есть правила для столкновения цветов и выбора дополнительных цветов).

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

Адам


я настоятельно рекомендую использовать функцию шейдера CG HSVtoRGB, они потрясающие... это дает вам естественный контроль цвета, как художник вместо контроля, как ЭЛТ-монитор, который вы arent предположительно!

Это способ сделать 1 значение float. т. е. серый, в 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);

результат удивительный рандомизации цвета! это не естественно, но он использует естественные цветовые градиенты, и это выглядит органично и controlleably irridescent / пастельные параметры.

для 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;
}

вот что я написал для сайта, который я сделал. Он будет автоматически генерировать случайный плоский цвет фона для любого div с классом .flat-color-gen. Jquery требуется только для добавления css на страницу; это не требуется для основной части этого, которая является generateFlatColorWithOrder() метод.

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

использовать различных цветов.

написано на javascript.

Он генерирует палитру визуально различных цветов.

distinct-цвета легко настраивается:

  • выберите, сколько цветов в палитре
  • ограничить оттенок до определенного диапазона
  • ограничить цветность (насыщенность) определенным диапазоном
  • ограничения на легкость для определенного диапазон
  • настройка общего качества палитры