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

StackOverflow https://stackoverflow.com/questions/43044

  •  09-06-2019
  •  | 
  •  

Вопрос

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

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

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

Это было полезно?

Решение

Вы можете усреднить значения 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

В яваскрипте:

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 — широко распространенный алгоритм кода для психологически обоснованной палитры.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

Я добился успеха, используя ТриадаСмешивание и 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-адаптация оригинального ответа Дэвида Кроу, включая специальный код для 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);

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

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

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

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

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

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

-Адам

Я настоятельно рекомендую использовать функцию шейдера 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;
}

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

Использовать разные цвета.

Написано на яваскрипте.

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

различные цвета имеют широкие возможности настройки:

  • Выберите количество цветов в палитре
  • Ограничить оттенок определенным диапазоном
  • Ограничить цветность (насыщенность) определенным диапазоном.
  • Ограничить яркость определенным диапазоном
  • Настройка общего качества палитры
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top