심미적으로 만족스러운 색상 팔레트를 무작위로 생성하는 알고리즘

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

  •  09-06-2019
  •  | 
  •  

문제

저는 미학적으로 만족스러운 색상을 무작위로 많이 생성하는 간단한 알고리즘을 찾고 있습니다.따라서 미친 네온 컬러, 배설물을 연상시키는 컬러 등은 사용하지 마세요.

이 문제에 대한 해결책을 찾았지만 RGB보다 대체 색상 팔레트에 의존합니다.앞뒤로 매핑하는 것보다 직선 RGB를 사용하는 것이 좋습니다.이러한 다른 솔루션도 최대 32개 정도의 만족스러운 임의 색상만 생성할 수 있습니다.

어떤 아이디어라도 좋을 것입니다.

도움이 되었습니까?

해결책

임의 색상의 RGB 값과 일정한 색상의 RGB 값을 평균화할 수 있습니다.

(자바의 예)

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(red, yellow, blue) 방법이라고 하며 이 문서에 설명되어 있습니다.

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

"페인트에서 영감을 얻은 색상 합성"으로.

알고리즘은 색상을 생성하고 각각의 새로운 색상은 이전에 선택한 색상과의 유클리드 거리를 최대화하기 위해 선택됩니다.

여기에서 자바스크립트의 좋은 구현을 찾을 수 있습니다.

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

업데이트 2:

Sciences Po Medialb는 데이터 과학자를 위한 색상 팔레트를 생성하는 "I want Hue"라는 도구를 방금 출시했습니다.다양한 색상 공간을 사용하고 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.functionfun.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 접근 방식' 사용). 기사).에서 다시 쓴 것입니다. 자바스크립트.

사용:

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 두 줄로 구성된 David Crow의 방법:

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

David Crow의 원래 답변에 대한 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 셰이더 기능을 사용하는 것을 강력히 권장합니다. 정말 훌륭합니다...아마도 CRT 모니터처럼 제어하는 ​​대신 화가처럼 자연스러운 색상 제어를 제공합니다.

1개의 float 값을 만드는 방법입니다.즉.회색은 색상, 밝기, 채도 등의 조합으로 1000ds로 표시됩니다.

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