อัลกอริธึมที่จะสร้างพาเลตต์สีที่น่าพึงพอใจแบบสุ่ม [ปิด]


301

ฉันกำลังมองหาอัลกอริทึมง่าย ๆ ในการสร้างสีแบบสุ่มที่ชื่นชอบความสวยงาม ดังนั้นจึงไม่มีสีนีออนที่บ้าคลั่งสีที่ชวนให้นึกถึงอุจจาระ ฯลฯ

ฉันพบวิธีแก้ไขปัญหานี้แล้ว แต่พวกเขาใช้พาเล็ตสีอื่น ๆ แทน RGB ฉันอยากจะใช้ RGB แบบตรงมากกว่าการทำแผนที่ไปมา โซลูชันอื่น ๆ เหล่านี้ยังสามารถสร้างสีแบบสุ่มที่น่าพอใจได้เพียง 32 สีเท่านั้น

ความคิดใด ๆ จะดีมาก


2
ฉันจะสร้างเว็บไซต์ที่สร้างสีแบบสุ่มเมื่อเข้าชมแต่ละครั้ง มีการโหวต "สีนี้หิน" / "สีนี้แย่" จากนั้นจัดเรียงตามอัตราส่วนของคะแนน
Nosredna

คุณสามารถตรวจสอบ HSL และ HSV
Jim Keener

48
"สีที่ชวนให้นึกถึงอุจจาระ" ฉันรักมัน
ฮ่า ๆ

นั่นไม่ใช่อัลกอริทึม
Matt The Ninja

ฉันจะเพิ่มความคิดเห็นเนื่องจากคำถามถูกปิด ฉันยังไม่ได้ลอง แต่มันน่าสนใจที่จะลองใช้วิธีเศษส่วนหรือขั้นตอนโดยใช้อัลกอริธึมแทนที่หรือจุดกึ่งกลาง ( lighthouse3d.com/opengl/terrain/index.php?mpd2 ) หรือ Perlin Noise แทนความสูง เพื่อผสมองค์ประกอบ rgb ของสี
2560

คำตอบ:


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
ข้อแม้เดียวดูเหมือนว่าจะสูญเสียความแตกต่าง โดยการใช้ค่าเฉลี่ยของสีแดงสีเขียวและสีน้ำเงินด้วยสีเดียวเช่นสีขาวทุกสีจะขยับเข้าใกล้สีขาวมากขึ้นและลดความแตกต่างระหว่างสีเหล่านั้น ตัวอย่างเช่นหากคุณดูภาพหน้าจอแรก: เมื่อกรีนเหล่านั้นอยู่ติดกันฉันจะแยกแยะได้ แต่ถ้าพวกเขาไม่ได้อยู่ติดกันในกราฟิกที่ผลิตออกมา อาจเป็นปัญหาได้
Zelphir Kaltstahl

เมื่อสร้างส่วนประกอบสีแบบสุ่มให้ลอง จำกัด ขอบเขตบนด้วยค่าที่น้อยกว่าเช่น 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

เป็น "การผสมสีที่ได้รับแรงบันดาลใจจากสี"

อัลกอริทึมสร้างสีและสีใหม่แต่ละสีได้รับการเลือกเพื่อเพิ่มระยะห่างของยูเซอลินให้เท่ากับสีที่เลือกไว้ก่อนหน้านี้

ที่นี่คุณสามารถค้นหาการใช้งานที่ดีใน javascript:

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

อัปเดต 2:

Science Po Medialb เพิ่งเปิดตัวเครื่องมือที่ชื่อว่า "ฉันต้องการเว้" ซึ่งสร้างจานสีสำหรับนักวิทยาศาสตร์ด้านข้อมูล การใช้พื้นที่สีที่แตกต่างและสร้างจานสีโดยใช้การจัดกลุ่ม k-mean หรือบังคับเวกเตอร์ (กราฟแสดงการเขม่น) ผลลัพธ์จากวิธีการเหล่านั้นดีมากพวกเขาแสดงทฤษฎีและการใช้งานในหน้าเว็บของพวกเขา

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


iWantHue คือคำตอบ ไปที่นั่น. จะประหลาดใจ
Irongaze.com

23

ในจาวาสคริปต์:

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


ไม่ถูกต้องอย่างสมบูรณ์: คุณต้อง zero-padding สำหรับตัวเลขหลักเดียวเช่นกัน ... ต่อไปนี่คือซอที่ใช้งานได้สำหรับผู้ค้นหา: jsfiddle.net/RedDevil/LLYBQ ----- เกาที่ ... ฉันไม่ได้ สังเกตุที่ +127 บิต ... แต่แล้วนี่จะไม่สร้างเฉดสีเข้ม
kumarharsh

2
ความคิดดั้งเดิมคือการสร้างสีที่ถูกใจโดยพลการ เฉดสีเข้มดูไม่น่าถูกใจสำหรับฉัน;)
motobói

11

การเปลี่ยนไปใช้พาเลตต์อื่นเป็นวิธีที่เหนือกว่าในการทำสิ่งนี้ มีเหตุผลที่พวกเขาทำเช่น: จานสีอื่น ๆ คือ 'การรับรู้' - นั่นคือพวกเขาวางสีที่ดูเหมือนคล้ายกันไว้ด้วยกันและการปรับหนึ่งตัวแปรจะเปลี่ยนสีในลักษณะที่คาดการณ์ได้ ไม่มีสิ่งใดที่เป็นจริงสำหรับ RGB ซึ่งไม่มีความสัมพันธ์ที่ชัดเจนระหว่างสีที่ "เข้ากันได้ดี"


6

ฉันประสบความสำเร็จในการใช้TriadMixingและCIE94เพื่อหลีกเลี่ยงสีที่คล้ายกัน ภาพต่อไปนี้ใช้สีอินพุตแดง, เหลืองและขาว ดูที่นี่

TriadMixing + CIE94


5

คำตอบที่ไม่ควรมองข้ามเพราะเป็นเรื่องง่ายและนำเสนอข้อดีคือการสุ่มตัวอย่างภาพถ่ายและภาพวาดในชีวิตจริง ตัวอย่างพิกเซลสุ่มจำนวนมากเท่าที่คุณต้องการสีแบบสุ่มในภาพขนาดย่อของภาพศิลปะสมัยใหม่, cezanne, van gogh, monnet, ภาพถ่าย ... ข้อดีคือคุณสามารถรับสีตามธีมและเป็นสีอินทรีย์ เพียงแค่ใส่ 20 - 30 รูปในโฟลเดอร์และสุ่มตัวอย่างรูปแบบสุ่มทุกครั้ง

การแปลงค่า HSV เป็นอัลกอริทึมโค้ดที่แพร่หลายสำหรับจานสีที่ใช้ในทางจิตวิทยา hsv นั้นง่ายต่อการสุ่ม


1
mkweb.bcgsc.ca/color_summarizer/?analyzeนี่คือเครื่องมือออนไลน์ที่สามารถวิเคราะห์ภาพถ่ายในชีวิตจริงและกลับไปที่คุณ Grapher ของค่า RGB บอกว่าจะได้รับความรู้สึกของสิ่งที่ภาพถ่ายในชีวิตจริงมีในกราฟของพวกเขา .... เว็บไซต์ที่มีประโยชน์อย่างมากซึ่งเป็นสิ่งจำเป็นหากคุณพยายามออกแบบอัลกอริทึมเปรี้ยวจี๊ดสำหรับ
colours


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
Dylan Watson

3

วิธีการของ 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))
}

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

สำหรับพาสเทลให้ส่งผ่านจำนวนเต็ม luma dark / light ที่สูงขึ้นเช่น 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 ของคำตอบดั้งเดิมของ David Crow รวมถึงรหัสเฉพาะ 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

ใช้ที่แตกต่างกันสี

เขียนด้วยจาวาสคริปต์

มันสร้างจานสีที่แตกต่างทางสายตา

สีที่แตกต่างสามารถกำหนดค่าได้สูง:

  • เลือกจำนวนสีในจานสี
  • จำกัด เว้ไปยังช่วงที่ระบุ
  • จำกัด ความเข้มของสี (ความอิ่มตัว) ให้อยู่ในช่วงที่ระบุ
  • จำกัด ความสว่างให้อยู่ในช่วงที่ระบุ
  • กำหนดค่าคุณภาพทั่วไปของพาเล็ต

0

คุณสามารถให้พวกเขาอยู่ในความสว่างที่แน่นอน ที่จะควบคุมปริมาณของ "นีออน" สีเล็กน้อย เช่นหาก "ความสว่าง"

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

อยู่ภายในขอบเขตที่แน่นอนมันจะมีสีอ่อนออกไป ในทางกลับกันถ้ามันอยู่ในขอบเขตที่ต่ำมันจะเข้มขึ้น การทำเช่นนี้จะกำจัดสีที่บ้าและโดดเด่นใด ๆ และถ้าคุณเลือกขอบเขตที่สูงหรือต่ำจริง ๆ พวกมันจะอยู่ใกล้กับสีขาวหรือดำ


0

มันจะยากที่จะได้รับสิ่งที่คุณต้องการเป็นอัลกอริธึมผู้คนศึกษาทฤษฎีสีมาเป็นเวลานานและพวกเขาก็ไม่รู้กฎทั้งหมด

อย่างไรก็ตามมีกฎบางอย่างที่คุณสามารถใช้ในการคัดสรรชุดสีที่ไม่ดี (เช่นมีกฎสำหรับการปะทะสีและเลือกสีเสริม)

ฉันขอแนะนำให้คุณไปที่ส่วนศิลปะของห้องสมุดและลองอ่านหนังสือเกี่ยวกับทฤษฎีสีเพื่อให้เข้าใจได้ดีขึ้นว่าอะไรคือสีที่ดีก่อนที่คุณจะลองทำดู - คุณอาจไม่รู้ด้วยซ้ำว่าทำไมชุดค่าผสมบางอย่างกับชุดอื่น ๆ เสื้อ

อดัม


0

ฉันขอแนะนำอย่างยิ่งให้ใช้ฟังก์ชั่น CG HSVtoRGB shader พวกมันยอดเยี่ยม ... มันให้การควบคุมสีที่เป็นธรรมชาติเหมือนกับจิตรกรแทนการควบคุมเช่นจอ crt ที่คุณไม่น่าจะเป็น!

นี่เป็นวิธีที่จะทำให้ 1 ค่าลอยตัว เช่นสีเทาเป็น 1,000 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 คุณสามารถใช้ฟังก์ชั่นนี้มันเป็นรุ่น 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

นี่คือสิ่งที่ฉันเขียนสำหรับเว็บไซต์ที่ฉันทำ มันจะอัตโนมัติสร้างสุ่มแบนสีพื้นหลังสำหรับ 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);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.