Escribí los dos métodos a continuación para seleccionar automáticamente N colores distintos. Funciona definiendo una función lineal por partes en el cubo RGB. El beneficio de esto es que también puede obtener una escala progresiva si eso es lo que desea, pero cuando N crece, los colores pueden comenzar a parecerse. También puedo imaginar subdividir uniformemente el cubo RGB en una red y luego dibujar puntos. ¿Alguien sabe algún otro método? Estoy descartando definir una lista y luego simplemente recorrerla. También debería decir que generalmente no me importa si chocan o no se ven bien, solo tienen que ser visualmente distintos.
public static List<Color> pick(int num) {
List<Color> colors = new ArrayList<Color>();
if (num < 2)
return colors;
float dx = 1.0f / (float) (num - 1);
for (int i = 0; i < num; i++) {
colors.add(get(i * dx));
}
return colors;
}
public static Color get(float x) {
float r = 0.0f;
float g = 0.0f;
float b = 1.0f;
if (x >= 0.0f && x < 0.2f) {
x = x / 0.2f;
r = 0.0f;
g = x;
b = 1.0f;
} else if (x >= 0.2f && x < 0.4f) {
x = (x - 0.2f) / 0.2f;
r = 0.0f;
g = 1.0f;
b = 1.0f - x;
} else if (x >= 0.4f && x < 0.6f) {
x = (x - 0.4f) / 0.2f;
r = x;
g = 1.0f;
b = 0.0f;
} else if (x >= 0.6f && x < 0.8f) {
x = (x - 0.6f) / 0.2f;
r = 1.0f;
g = 1.0f - x;
b = 0.0f;
} else if (x >= 0.8f && x <= 1.0f) {
x = (x - 0.8f) / 0.2f;
r = 1.0f;
g = 0.0f;
b = x;
}
return new Color(r, g, b);
}
java
colors
color-scheme
color-picker
trabajo
fuente
fuente
Respuestas:
Puedes usar el modelo de color HSL para crear sus colores.
Si todo lo que desea son tonos diferentes (probablemente) y ligeras variaciones en la luminosidad o la saturación, puede distribuir los tonos de la siguiente manera:
fuente
Esta pregunta aparece en bastantes discusiones SO:
Se proponen diferentes soluciones, pero ninguna es óptima. Afortunadamente, la ciencia viene al rescate
N arbitraria
Los últimos 2 serán gratuitos a través de la mayoría de las bibliotecas universitarias / proxies.
N es finito y relativamente pequeño
En este caso, uno podría buscar una solución de lista. Un artículo muy interesante sobre el tema está disponible gratuitamente:
Hay varias listas de colores a considerar:
También me encontré con esta paleta por un estudiante del MIT. Por último, los siguientes enlaces pueden ser útiles para convertir entre diferentes sistemas de color / coordenadas (algunos colores en los artículos no están especificados en RGB, por ejemplo):
Para la lista de Kelly y Boynton, ya hice la conversión a RGB (con la excepción de blanco y negro, que debería ser obvio). Algún código C #:
Y aquí están los valores RGB en representaciones hexadecimales y de 8 bits por canal:
Para todos los desarrolladores de Java, aquí están los colores JavaFX:
Los siguientes son los colores de Kelly sin clasificar según el orden anterior.
Los siguientes son los colores de Kelly ordenados según los tonos (tenga en cuenta que algunos amarillos no son muy contrastantes)
fuente
Como la respuesta de Uri Cohen, pero en cambio es un generador. Comenzará usando colores muy separados. Determinista.
Muestra, izquierda colores primero:
fuente
Aquí hay una idea. Imagine un cilindro HSV
Defina los límites superior e inferior que desea para Brillo y Saturación. Esto define un anillo cuadrado de sección transversal dentro del espacio.
Ahora, dispersa N puntos al azar dentro de este espacio.
Luego aplique un algoritmo de repulsión iterativa sobre ellos, ya sea para un número fijo de iteraciones, o hasta que los puntos se estabilicen.
Ahora debe tener N puntos que representen N colores que sean lo más diferentes posible dentro del espacio de color que le interese.
Hugo
fuente
Por el bien de las generaciones futuras, agrego aquí la respuesta aceptada en Python.
fuente
Todo el mundo parece haberse perdido la existencia del muy útil espacio de color YUV que fue diseñado para representar las diferencias de color percibidas en el sistema visual humano. Las distancias en YUV representan diferencias en la percepción humana. Necesitaba esta funcionalidad para MagicCube4D que implementa cubos de Rubik en 4 dimensiones y un número ilimitado de otros rompecabezas retorcidos 4D que tienen un número arbitrario de caras.
Mi solución comienza seleccionando puntos aleatorios en YUV y luego separando iterativamente los dos puntos más cercanos, y solo convirtiendo a RGB cuando devuelve el resultado. El método es O (n ^ 3) pero eso no importa para los números pequeños o los que se pueden almacenar en caché. Ciertamente puede hacerse más eficiente, pero los resultados parecen ser excelentes.
La función permite la especificación opcional de umbrales de brillo para no producir colores en los que ningún componente sea más brillante o más oscuro que las cantidades dadas. Es decir, es posible que no desee valores cercanos al blanco o negro. Esto es útil cuando los colores resultantes se utilizarán como colores base que luego se sombrearán a través de la iluminación, la estratificación, la transparencia, etc. y aún deben aparecer diferentes de sus colores base.
fuente
El modelo de color HSL puede ser adecuado para "ordenar" colores, pero si está buscando colores visualmente distintos, definitivamente necesita el modelo de color Lab .
Una vez que sepa eso, encontrar el subconjunto óptimo de N colores de una amplia gama de colores sigue siendo un problema difícil (NP), algo similar al problema del vendedor viajero y todas las soluciones que utilizan algoritmos k-mean o algo realmente no ayuda.
Dicho esto, si N no es demasiado grande y si comienza con un conjunto limitado de colores, encontrará fácilmente un muy buen subconjunto de colores distintivos de acuerdo con una distancia Lab con una función aleatoria simple.
He codificado dicha herramienta para mi propio uso (puede encontrarla aquí: https://mokole.com/palette.html ), esto es lo que obtuve para N = 7:
Todo es JavaScript, así que siéntase libre de echar un vistazo a la fuente de la página y adaptarla a sus propias necesidades.
fuente
L
de 0 a 128 ya
yb
de -128 a 128. ¶ Empecé conL
= 0,a
= -128,b
= -128, que es un azul brillante. Luego aumentéa
tres veces. Big El gran cambio (+128)a
= 50 da como resultado un azul solo ligeramente más oscuro. ❷ (+85)a
= 85 resultados todavía en azul. ❸ Sin embargo, el cambio relativamente pequeño (+43)a
= 128 cambia completamente el color a fucsia.Aquí hay una solución para manejar su problema "distinto", que es totalmente exagerado:
Crea una esfera unitaria y suelta puntos sobre ella con cargas repelentes. Ejecute un sistema de partículas hasta que ya no se muevan (o el delta sea "lo suficientemente pequeño"). En este punto, cada uno de los puntos está lo más lejos posible el uno del otro. Convierte (x, y, z) a rgb.
Lo menciono porque para ciertas clases de problemas, este tipo de solución puede funcionar mejor que la fuerza bruta.
Originalmente vi este enfoque aquí para testear una esfera.
Una vez más, las soluciones más obvias de atravesar el espacio HSL o el espacio RGB probablemente funcionarán bien.
fuente
Intentaría fijar la saturación y la iluminación al máximo y enfocarme solo en el tono. Según lo veo, H puede ir de 0 a 255 y luego se envuelve. Ahora, si quisieras dos colores contrastantes, tomarías los lados opuestos de este anillo, es decir, 0 y 128. Si quisieras 4 colores, tomarías algunos separados por 1/4 de la longitud del círculo 256, es decir, 0, 64,128,192. Y, por supuesto, como otros sugirieron cuando necesita N colores, puede separarlos por 256 / N.
Lo que agregaría a esta idea es usar una representación inversa de un número binario para formar esta secuencia. Mira este:
... de esta manera, si necesita N colores diferentes, puede tomar los primeros N números, revertirlos y obtener tantos puntos distantes como sea posible (para que N sea la potencia de dos) y al mismo tiempo preservar que cada prefijo del La secuencia difiere mucho.
Este era un objetivo importante en mi caso de uso, ya que tenía una tabla donde los colores se ordenaban por área cubierta por este color. Quería que las áreas más grandes de la tabla tuvieran un gran contraste, y estaba de acuerdo con que algunas áreas pequeñas tuvieran colores similares a los del top 10, ya que era obvio para el lector cuál es cuál observando el área.
fuente
getfracs
. Sin embargo, su enfoque es rápido y "simple" en lenguajes de bajo nivel: poco marcha atrás en C .Si N es lo suficientemente grande, obtendrás algunos colores de aspecto similar. Solo hay muchos de ellos en el mundo.
¿Por qué no simplemente distribuirlos uniformemente a través del espectro?
Si desea mezclar la secuencia para que colores similares no estén uno al lado del otro, tal vez podría barajar la lista resultante.
¿Estoy pensando en esto?
fuente
Esto es trivial en MATLAB (hay un comando hsv):
fuente
He escrito un paquete para R llamado qualpalr que está diseñado específicamente para este propósito. Te recomiendo que mires la viñeta para averiguar cómo funciona, pero intentaré resumir los puntos principales.
Qualpalr toma una especificación de colores en el espacio de color HSL (que se describió anteriormente en este hilo), lo proyecta en el espacio de color DIN99d (que es perceptualmente uniforme) y encuentra el
n
que maximiza la distancia mínima entre ellos.fuente
Creo que este algoritmo recursivo simple complementa la respuesta aceptada, para generar valores de tono distintos. Lo hice para hsv, pero también se puede usar para otros espacios de color.
Genera matices en ciclos, lo más separados posible entre sí en cada ciclo.
No pude encontrar este tipo de algoritmo aquí. Espero que ayude, es mi primera publicación aquí.
fuente
Esta función OpenCV utiliza el modelo de color HSV para generar
n
colores distribuidos uniformemente alrededor de 0 <= H <= 360º con un máximo de S = 1.0 y V = 1.0. La función genera los colores BGR enbgr_mat
:fuente