Algoritmo de generación de paleta de colores



¿Busca una hermosa paleta de colores para el sitio? ¿Luz de fondo RGB recientemente instalada en casa, o quiere pintar la habitación con nuevos colores? ¿O compró un teclado con retroiluminación de color y quiere usarlo al máximo? Cualquiera que sea la situación en la que se encuentre, seguramente ajustará constantemente los esquemas de color.

Como programador, escribí rápidamente algunas líneas de código para generar paletas de colores al azar. Inmediatamente sintiendo que tal enfoque podría no dar los mejores resultados, en un par de minutos implementé el botón "recargar" de la paleta. Me pareció que para obtener un gran esquema, solo necesitas un poco de suerte y paciencia.

Estaba equivocado La generación aleatoria de paletas de colores es una mierda. De vez en cuando, un hermoso color coexiste con un tono feo y sucio de marrón o amarillo. Las colecciones de colores son siempre demasiado oscuras o demasiado claras y de bajo contraste, o los conjuntos consisten en colores muy similares. Era necesario encontrar una solución diferente.

Espacios de color


Comencemos con la teoría. Hoy, los espacios de color se usan ampliamente para clasificar los colores:

sRGB


RGB significa Red Green Blue . Así es como funcionan las pantallas: emiten luz en tres canales de color, que se mezclan en diferentes proporciones para producir todo tipo de colores. El valor en cada canal varía de 0 a 255. R:0, G:0, B:0 (o # 000000 en expresión hexadecimal) es negro, y R:255, G:255, B:255 (o #ffffff ) - blanco.

Laboratorio cie


El espacio de color de CIE Lab es más amplio que sRGB e incluye todos los colores percibidos por los humanos. Fue creado con la expectativa de la universalidad de la percepción. En otras palabras, la distancia entre los colores corresponde a la diferencia subjetiva: si los valores de los dos colores están cerca uno del otro, entonces se parecen. Por otro lado, dos colores muy separados entre sí también se perciben como completamente diferentes. En CIE Lab, se asigna más espacio para colores saturados que para oscuros y claros. Por cierto, para el ojo humano, el verde muy oscuro es casi indistinguible del negro. Además, este espacio de color es tridimensional: L significa ligereza (de 0.0 a 1.0), b (de aproximadamente -1.0 a 1.0) son canales de color.

HCL


Si RGB describe cómo la pantalla muestra los colores y el Laboratorio CIE cómo los percibimos, entonces HCL es el espacio de color que describe más de cerca cómo pensamos sobre los colores. También es tridimensional, H significa tonalidad (0 a 360 grados), representa croma y L representa luminancia (ambos parámetros se miden de 0.0 a 1.0).

Recomiendo usar CIE Lab para cálculos y HCL para representar paletas para el usuario. Si lo desea, puede convertir los valores de estos espacios a RGB.

Descomposición del espacio de color


Como necesitaba obtener un conjunto de colores únicos e individuales, primero descartamos aquellos que se parecen mucho. El espacio de color será tridimensional, y el algoritmo de agrupación k-means es perfecto para separar tales conjuntos de datos de baja dimensión. Él está tratando de descomponer los datos (en nuestro caso, el espacio de color) en k áreas separadas. Y luego la paleta se ensambla desde los puntos centrales de los grupos en estas áreas. El gif muestra una visualización bidimensional del algoritmo en el espacio tridimensional del Laboratorio CIE.

Escribir un código


Usando el método k-means implementado en Go, el problema se resuelve en solo unas pocas líneas de código. Primero, prepare los valores de color en el espacio CIE Lab:

 var d clusters.Observations for l := 0.2; l <= 0.8; l += 0.05 { for a := -1.0; a < 1.0; a += 0.1 { for b := -1.0; b < 1.0; b += 0.1 { d = append(d, clusters.Coordinates{l, a, b}) } } } 

Ya tomé un par de parámetros e impuse ciertas restricciones en los colores generados. En este ejemplo, desecharemos los colores demasiado oscuros (brillo <0.2) y demasiado brillantes (brillo> 0.8).

Expanda el espacio de color recién creado:

 km := kmeans.New() clusters, _ := km.Partition(d, 8) 

La función Partition devolverá segmentos de ocho grupos. Cada grupo tiene un punto Center , que es un color separado en un espacio dado. Sus coordenadas se pueden convertir fácilmente a un valor RGB hexadecimal:

 col := colorful.Lab(c.Center[0], c.Center[1], c.Center[2]) col.Clamped().Hex() 

Recuerde que un laboratorio CIE es más ancho que RGB, lo que significa que algunos valores de laboratorio no se pueden convertir a RGB. Estos valores se pueden convertir usando Clamped a los colores más cercanos en el espacio RGB.

Código completo


 package main import ( "github.com/muesli/kmeans" "github.com/muesli/clusters" colorful "github.com/lucasb-eyer/go-colorful" ) func main() { // Create data points in the CIE L*a*b* color space // l for lightness, a & b for color channels var d clusters.Observations for l := 0.2; l <= 0.8; l += 0.05 { for a := -1.0; a <= 1.0; a += 0.1 { for b := -1.0; b <= 1.0; b += 0.1 { d = append(d, clusters.Coordinates{l, a, b}) } } } // Partition the color space into 8 clusters km := kmeans.New() clusters, _ := km.Partition(d, 8) for _, c := range clusters { col := colorful.Lab(c.Center[0], c.Center[1], c.Center[2]) fmt.Println("Color as Hex:", col.Clamped().Hex()) } } 

Un conjunto de ocho (no tan) colores aleatorios generados por este código:



Define tu propio espacio de color


Agregue más control sobre la generación de color. Podemos gestionar fácilmente los datos utilizados para otros cálculos, seleccionando así el espacio de color para satisfacer nuestras necesidades. Genere una paleta de colores pastel:

 func pastel(c colorful.Color) bool { _, s, v := col.Hsv() return 0.2 <= s && s <= 0.4 && 0.7 <= v && v <= 1.0 } for l := 0.0; l <= 1.0; l += 0.05 { for a := -1.0; a <= 1.0; a += 0.1 { for b := -1.0; b <= 1.0; b += 0.1 { col := colorful.Lab(l, a, b) if col.IsValid() && pastel(col) { d = append(d, clusters.Coordinates{l, a, b}) } } } } 

Otro espacio de color es HSV , las letras en el nombre significan tono, saturación y brillo. En este espacio, los colores pastel suelen tener un alto brillo y baja saturación.

Esto es lo que sucedió:



También puede filtrar los colores por su saturación (croma) y brillo para obtener un conjunto de tonos "cálidos":

 func warm(col colorful.Color) bool { _, c, l := col.Hcl() return 0.1 <= c && c <= 0.4 && 0.2 <= l && l <= 0.5 } 

Resultado:



Paquete de gama


Estoy trabajando en una biblioteca llamada gama , que recopilará todas las piezas descritas aquí en un paquete conveniente en Go, que le permite generar y administrar paletas de colores y temas. Ya puedes probarlo, pero todavía está en funcionamiento.

Source: https://habr.com/ru/post/es414455/


All Articles