Algoritmo para gerar aleatoriamente uma paleta de colors esteticamente agradável

Eu estou procurando um algoritmo simples para gerar um grande número de colors aleatórias, esteticamente agradáveis. Portanto, não há colors de néon louco, colors reminiscentes de fezes, etc.

Eu encontrei soluções para este problema, mas eles dependem de paletas de colors alternativas do que RGB. Eu prefiro usar apenas o RGB direto do que o mapeamento de um lado para o outro. Essas outras soluções também podem, no máximo, gerar apenas 32 colors aleatórias agradáveis.

Qualquer ideia seria ótima.

Você pode calcular a média dos valores RGB de colors aleatórias com as colors constantes:

(exemplo em 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; } 

A mistura de colors aleatórias com branco (255, 255, 255) cria tons pastéis neutros, aumentando a luminosidade e mantendo o matiz da cor original. Estes pastéis gerados aleatoriamente geralmente vão bem juntos, especialmente em grandes números.

Aqui estão algumas colors pastel geradas usando o método acima:

Primeiro

Você também pode misturar a cor aleatória com um pastel constante, o que resulta em um conjunto colorido de colors neutras. Por exemplo, usar um azul claro cria colors como estas:

Segundo

Indo além, você pode adicionar heurísticas ao seu gerador que levam em conta colors complementares ou níveis de sombreamento, mas tudo depende da impressão que você deseja obter com suas colors aleatórias.

Alguns resources adicionais:

Eu usaria uma roda de colors e dada uma posição aleatória, você poderia adicionar o ângulo de ouro (137,5 graus)

http://en.wikipedia.org/wiki/Golden_angle

para obter colors diferentes a cada vez que não se sobreponham.

Ajustando o brilho da roda de colors, você também pode obter diferentes combinações de colors claras / escuras.

Eu encontrei este post que explica muito bem o problema e a solução usando a proporção áurea.

http://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/

ATUALIZAÇÃO: Acabei de encontrar essa outra abordagem:

É chamado de método RYB (vermelho, amarelo, azul) e é descrito neste trabalho:

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

como “Paint Inspired Color Compositing”.

O algoritmo gera as colors e cada nova cor é escolhida para maximizar sua distância euclidiana às previamente selecionadas.

Aqui você pode encontrar uma boa implementação em javascript:

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

ATUALIZAÇÃO 2:

A Sciences Po Medialb acaba de lançar uma ferramenta chamada “I want Hue” que gera paletas de colors para os cientistas de dados. Usando espaços de colors diferentes e gerando as paletas usando agrupamentos k-means ou vetores de força (charts de repulsão) Os resultados desses methods são muito bons, eles mostram a teoria e uma implementação em sua página da web.

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

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

Vi a ideia aqui: http://blog.functionalfun.net/2008/07/random-pastel-colour-generator.html

Converter em outra paleta é uma maneira muito superior de fazer isso. Há uma razão pela qual eles fazem isso: outras paletas são “perceptivas” – isto é, elas colocam colors parecidas similares juntas, e o ajuste de uma variável muda a cor de uma maneira previsível. Nada disso é verdade para o RGB, onde não há uma relação óbvia entre colors que “combinam bem”.

Uma resposta que não deve ser negligenciada, porque é simples e apresenta vantagens, é a amostragem de fotos e pinturas da vida real. amostra como muitos pixels randoms como você quer colors aleatórias em miniaturas de fotos de arte moderna, cezanne, van gogh, monnet, fotos … a vantagem é que você pode obter colors por tema e que eles são colors orgânicas. Basta colocar 20-30 fotos em uma pasta e aleatória amostra uma foto aleatória de cada vez.

Conversão para valores de HSV é um algoritmo de código generalizado para paleta psicologicamente baseada. hsv é mais fácil de randomizar.

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

fonte: https://stackoverflow.com/a/12266311/2875783

Eu tive sucesso usando TriadMixing e CIE94 para evitar colors semelhantes. A imagem a seguir usa as colors de input vermelho, amarelo e branco. Veja aqui

TriadMixing + CIE94

Aqui está um gerador de colors rápido e sujo em C # (usando ‘abordagem RYB’ descrita neste artigo ). É uma reescrita do JavaScript .

Usar:

 List ColorPalette = ColorGenerator.Generate(30).ToList(); 

As duas primeiras colors tendem a ser brancas e um tom de preto. Eu frequentemente os pulo assim (usando o Linq):

 List ColorsPalette = ColorGenerator .Generate(30) .Skip(2) // skip white and black .ToList(); 

Implementação:

 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 { private readonly int pointsCount; private double[] picked; private int pickedCount; private readonly List points = new List(); 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 GetEnumerator() { Generate(); for (int i = 0; i < pointsCount; i++) { yield return Pick(); } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public static IEnumerable 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])); } } } 

Método de David Crow em um liner 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; } 

Para pastel, passe em números inteiros mais altos de luz / escuridão - ou seja, fnGetRandomColour (120, 250)

Créditos: todos os créditos para http://paulirish.com/2009/random-hex-color-code-snippets/ stackoverflow.com/questions/12043187/how-to-check-if-hex-color-is-too-black

Adaptação JavaScript da resposta original de David Crow, IE e código específico do Nodejs incluídos.

 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) + ')'; } 

Execute a function usando:

 generateRandomComplementaryColor(240, 240, 240); 

você poderia tê-los dentro de certo brilho. isso controlaria a quantidade de colors “neon” um pouco. por exemplo, se o “brilho”

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

estava dentro de um certo limite alto, teria uma cor clara e lavada. Por outro lado, se fosse dentro de um certo limite baixo, seria mais escuro. Isso eliminaria todas as colors malucas e destacadas, e se você escolhesse um limite muito alto ou muito baixo, elas seriam bastante próximas de branco ou preto.

Vai ser difícil conseguir o que você quer algoritmicamente – as pessoas estudam a teoria das colors há muito tempo e nem sequer conhecem todas as regras.

No entanto, existem algumas regras que você pode usar para selecionar combinações de colors ruins (ou seja, há regras para colors conflitantes e escolha de colors complementares).

Eu recomendo que você visite a seção de arte da sua biblioteca e confira os livros sobre teoria das colors para obter uma melhor compreensão do que é uma boa cor antes de tentar criar uma – parece que você nem sabe por que certas combinações funcionam e outras t.

-Adão

Eu recomendo fortemente o uso de uma function shader CG HSVtoRGB, eles são incríveis … ele dá a você um controle de colors natural como um pintor em vez de controle como um monitor crt, que você não é presumivelmente!

Esta é uma maneira de fazer um valor flutuante. ou seja, cinza, em 1000 ds de combinações de cor e brilho e saturação etc:

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

O resultado é a RANDOMIZAÇÃO DE CORES IMPRESSIONANTE! não é natural, mas usa gradientes de cor naturais e tem um aspecto orgânico e parâmetros irridescentes.

Para perlin, você pode usar esta function, é uma versão rápida de perlin em zig zag.

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

Aqui está algo que escrevi para um site que fiz. Ele gerará automaticamente uma cor de fundo plana aleatória para qualquer div com a class .flat-color-gen . Jquery só é necessário para adicionar css à página; não é necessário para a parte principal disso, que é o método 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); 

Use colors distintas .

Escrito em javascript.

Ele gera uma paleta de colors visualmente distintas.

colors distintas é altamente configurável:

  • Escolha quantas colors estão na paleta
  • Restringir o matiz a um intervalo específico
  • Restringir o chroma (saturação) a um intervalo específico
  • Restringir a leveza a um intervalo específico
  • Configurar a qualidade geral da paleta