algorithm colors go rgb color-space

algorithm - Algoritmo para encontrar el color entre otros dos: en el espacio de color de los colores pintados



colors rgb (5)

Desea utilizar colores CMY sustractivos (cian, magenta, amarillo) (como lo hace LaC, sin usar el término)

La conversión de ida y vuelta es simple: (C, M, Y) = (-R, -G, -B).
Entonces CMY (0,0,0) es blanco y CMY (FF, FF, FF) es negro.

Cuando agrega dos colores CMY, existen diferentes formas de calcular los nuevos valores. Puede tomar el promedio, máximo o algo intermedio para cada valor de color.
P.ej. para filtros de luz, siempre usa el valor máximo. Para la pintura que desea utilizar, algo más cercano al valor promedio.

Como señala LaC, no se pone verde al mezclar amarillo y azul, sino que se mezcla con amarillo y cian. Amarillo y azul realmente da negro, cuando se mezcla por valor máximo (por ejemplo, filtros de luz). Por esta razón, es posible que desee utilizar algo más cercano al valor promedio para la mezcla de pintura.

No quieres usar CMYK, a menos que quieras imprimir algo. El color negro "K" se usa principalmente en impresoras para ahorrar tinta, pero no es necesario para representar colores.

Al mezclar pintura azul y amarilla, el resultado es una especie de verde.

Tengo dos colores rgb:

azul = (0, 0, 255)

y amarillo = (255, 255, 0)

¿Cuál es el algoritmo para encontrar el color rgb que es el resultado de mezclar los dos colores, como aparecerían al usar pintura? Los colores resultantes del algoritmo no tienen que ser terriblemente exactos. Para el ejemplo anterior, solo debería verse como una especie de verde.

Gracias por adelantado.

Editar: Esta función, escrita en Ir, funcionó para mí, según la respuesta de LaC.

func paintMix(c1, c2 image.RGBAColor) image.RGBAColor { r := 255 - ((255 - c1.R) + (255 - c2.R)) g := 255 - ((255 - c1.G) + (255 - c2.G)) b := 255 - ((255 - c1.B) + (255 - c2.B)) return image.RGBAColor{r, g, b, 255} }

Edit # 2 Allthought esto logra mezclar cian y amarillo, la mezcla entre azul y amarillo se vuelve negra, lo que no parece correcto. Todavía estoy buscando un algoritmo de trabajo.

Editar # 3 Aquí hay un ejemplo completo de trabajo en Go, usando el espacio de color HLS: http://go.pastie.org/1976031 . Gracias Mark Ransom.

Editar # 4 Parece que el camino a seguir para una mejor mezcla de colores sería usar la ecuación de Kubelka-Munk


El espacio de color RBG se basa en la emisión de luz, el espacio de color de los colorantes y pigmentos se basa en la absorción de la luz.

por ejemplo, las plantas no se ven verdes porque emiten luz verde, sino porque absorben todos los otros colores de la luz, reflejando solo el verde.

De acuerdo con esto, deberías poder acercarte haciendo una conversión de RGB a un espacio de color absorbente, hacer la "mezcla" y luego volver otra vez.


En realidad, obtienes verde al mezclar (de manera sutil) amarillo y cian. El amarillo es rojo + verde (255, 255, 0), cian es verde + azul (0, 255, 255). Ahora haz los colores opuestos: azul (0, 0, 255) y rojo (255, 0, 0). Mézclalos de forma aditiva y obtienes morado (255, 0, 255). Haz lo opuesto y obtienes verde (0, 255, 0).

En otras palabras, puede obtener una mezcla sustractiva como opuesta a la mezcla aditiva de los opuestos de sus dos colores.


La pintura funciona por absorción. Empiezas con luz blanca (255,255,255) y lo multiplicas por los factores de absorción.

La pintura azul absorbe toda la luz roja y verde que la golpea.

La pintura amarilla absorbe toda la luz azul que la golpea.

En un mundo perfecto, eso significa que la combinación de pintura amarilla y azul daría como resultado pintura negra o, en el mejor de los casos, un gris barroso. En la práctica, la pintura "azul" tiene un sesgo hacia el verde, por lo que se obtiene un verde fangoso. Nunca he visto un ejemplo de mezclar amarillo y azul que produzca un verde satisfactorio. Wikipedia aborda algunas de las complejidades de este proceso: http://en.wikipedia.org/wiki/Primary_color#Subtractive_primaries

Creo que lo que realmente estás preguntando es cómo interpolar colores a lo largo de una rueda de colores. Esto debería ser independiente de si los colores son absorbentes como en la pintura o emisivos como en las pantallas RGB.

Editar: trabajando en el espacio de color HSL puede obtener el tipo de resultados que está buscando. Aquí hay un código en Python que implementa el algoritmo; promediar tonos es complicado y se basa en una respuesta mía anterior para promediar ángulos .

from colorsys import rgb_to_hls,hls_to_rgb from math import sin,cos,atan2,pi def average_colors(rgb1, rgb2): h1, l1, s1 = rgb_to_hls(rgb1[0]/255., rgb1[1]/255., rgb1[2]/255.) h2, l2, s2 = rgb_to_hls(rgb2[0]/255., rgb2[1]/255., rgb2[2]/255.) s = 0.5 * (s1 + s2) l = 0.5 * (l1 + l2) x = cos(2*pi*h1) + cos(2*pi*h2) y = sin(2*pi*h1) + sin(2*pi*h2) if x != 0.0 or y != 0.0: h = atan2(y, x) / (2*pi) else: h = 0.0 s = 0.0 r, g, b = hls_to_rgb(h, l, s) return (int(r*255.), int(g*255.), int(b*255.)) >>> average_colors((255,255,0),(0,0,255)) (0, 255, 111) >>> average_colors((255,255,0),(0,255,255)) (0, 255, 0)

Tenga en cuenta que esta respuesta no imita la mezcla de pintura, por las razones indicadas anteriormente. Más bien da una mezcla intuitiva de colores que no se basa en ninguna realidad física del mundo.


Utilice Convert :: Color para producir este tipo de resultados:

mauve is 0xE0B0FF sRGB=[224,176,255] HSV=[276, 31,100] vermilion is 0xE34234 sRGB=[227, 66, 52] HSV=[ 5, 77, 89] mix is 0xE2799A sRGB=[226,121,154] HSV=[341, 46, 89] red is 0xFF0000 sRGB=[255, 0, 0] HSV=[ 0,100,100] blue is 0x0000FF sRGB=[ 0, 0,255] HSV=[240,100,100] red+blue is 0x800080 sRGB=[128, 0,128] HSV=[300,100, 50] black is 0xFFFFFF sRGB=[255,255,255] HSV=[ 0, 0,100] white is 0x000000 sRGB=[ 0, 0, 0] HSV=[ 0, 0, 0] grey is 0x808080 sRGB=[128,128,128] HSV=[ 0, 0, 50] dark red is 0xFF8080 sRGB=[255,128,128] HSV=[ 0, 50,100] light red is 0x800000 sRGB=[128, 0, 0] HSV=[ 0,100, 50] pink is 0x800080 sRGB=[128, 0,128] HSV=[300,100, 50] deep purple is 0xBF80FF sRGB=[191,128,255] HSV=[270, 50,100]

Al ejecutar este tipo de código:

#!/usr/bin/env perl use strict; use warnings; use Convert::Color; main(); exit; sub rgb($$$) { my($r, $g, $b) = @_; return new Convert::Color:: "rgb8:$r,$g,$b"; } sub show($$) { my ($name, $color) = @_; printf "%-12s is 0x%6s", $name, uc $color->hex; printf " sRGB=[%3d,%3d,%3d] ", $color->rgb8; my ($h,$s,$v) = $color->as_hsv->hsv; for ($s, $v) { $_ *= 100 } printf " HSV=[%3.0f,%3.0f,%3.0f] ", $h, $s, $v; print "/n"; } sub main { my $vermilion = rgb 227, 66, 52; my $mauve = rgb 224, 176, 255; show mauve => $mauve; show vermilion => $vermilion; my $mix = alpha_blend $mauve $vermilion; show mix => $mix; print "/n"; my $red = rgb 255, 0, 0; my $blue = rgb 0, 0, 255; show red => $red; show blue => $blue; $mix = alpha_blend $red $blue; show "red+blue" => $mix; print "/n"; my $black = rgb 255, 255, 255; my $white = rgb 0, 0, 0; show black => $black; show white => $white; my $grey = alpha_blend $black $white; show grey => $grey; print "/n"; my $dark_red = alpha_blend $red $black; my $light_red = alpha_blend $red $white; show "dark red" => $dark_red; show "light red" => $light_red; print "/n"; my $magenta = rgb 255, 0, 255; my $violet = rgb 127, 0, 255; my $pink = alpha_blend $magenta $white; my $deep_purple = alpha_blend $violet $black; show pink => $pink; show "deep purple" => $deep_purple;; }