问题描述
||
当混合蓝色和黄色油漆时,结果是某种绿色。
我有两种rgb颜色:
蓝色=(0,0,255)
黄色=(255,255,0)
找到两种颜色混合使用时产生的rgb颜色的算法是什么?该算法产生的颜色不必十分精确。对于上面的示例,它只需要看起来像某种绿色即可。
提前致谢。
编辑:根据LaC的回答,用Go编写的此功能对我有用。
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}
}
编辑#2虽然如此,但设法将青色和黄色混合,蓝色和黄色之间的混合变为黑色,这似乎不正确。我仍在寻找有效的算法。
编辑#3这是Go中使用HLS颜色空间的完整工作示例:http://go.pastie.org/1976031。谢谢马克·兰瑟姆。
编辑#4似乎更好的混色方法是使用Kubelka-Munk方程
解决方法
油漆通过吸收起作用。首先从白光(255,255,255)乘以吸收系数。
蓝色油漆吸收了所有击中它的红色和绿色光。
黄色油漆吸收了所有击中它的蓝光。
在一个理想的世界中,这意味着将黄色和蓝色的油漆混合会产生黑色的油漆,或至多是浑浊的灰色。实际上,“蓝色”涂料偏向绿色,因此您会得到绿色的泥泞。我从未见过将黄色和蓝色混合产生令人满意的绿色的示例。 Wikipedia讨论了此过程的一些复杂性:http://en.wikipedia.org/wiki/Primary_color#Subtractive_primaries
我认为您真正要问的是如何沿着色轮对颜色进行插值。这应该与颜色是吸收性的(如涂料中的)还是发射性的(如RGB显示器中的)无关。
编辑:通过在HSL色彩空间中工作,您可以获得所需的结果。这是一些实现该算法的Python代码;平均色调是棘手的,并且基于我先前对平均角度的回答。
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,0),(0,255))
(0,111)
>>> average_colors((255,0)
请注意,由于上述原因,该答案并不模拟涂料混合。而是提供直观的颜色混合,这是任何现实世界中都不存在的。
,实际上,通过将黄色和青色(相减)混合可以得到绿色。黄色是红色+绿色(255、255、0),青色是绿色+蓝色(0、255、255)。现在使用相反的颜色:蓝色(0,0,255)和红色(255,0,0)。将它们相加混合即可得到紫色(255、0、255)。相反,变成绿色(0、255、0)。
换句话说,您可以将减色混合作为两种颜色相反的加性混合的相反。
,色空间RBG基于发光,染料和颜料的色空间基于光吸收。
例如植物的外观不是绿色的,因为它们发出绿光,而是因为它们吸收了所有其他颜色的光,仅反射绿色。
基于此,您应该能够完成从RGB到吸收性色彩空间的转换,进行“混合”,然后再次返回,就可以非常接近了。
,您想使用减色CMY颜色(青色,品红色,黄色)(如LaC所做的那样,而未使用该术语)
来回转换很简单:(C,M,Y)=(-R,-G,-B)。
因此CMY(0,0)是白色,而CMY(FF,FF,FF)是黑色。
添加两种CMY颜色时,有不同的方法来计算新值。您可以为每个颜色值取平均值,最大值或介于两者之间的值。
例如。对于滤光器,您始终使用最大值。对于您要正确使用的油漆,它接近平均值。
正如LaC所指出的,混合黄色和蓝色不会得到绿色,而是将黄色和青色混合得到绿色。当以最大值混合时(例如,滤光器),黄色和蓝色实际上给出黑色。这就是为什么您可能要使用更接近平均值的油漆混合的原因。
您不想使用CMYK,除非您要打印一些东西。黑色的“ K”颜色主要用于打印机中以节省墨水,但不需要代表颜色。
,使用Convert :: Color产生这种输出:
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] HSV=[ 0,100,100]
blue is 0x0000FF sRGB=[ 0,255] HSV=[240,100]
red+blue is 0x800080 sRGB=[128,128] HSV=[300,50]
black is 0xFFFFFF sRGB=[255,255] HSV=[ 0,100]
white is 0x000000 sRGB=[ 0,0]
grey is 0x808080 sRGB=[128,128,128] HSV=[ 0,50]
dark red is 0xFF8080 sRGB=[255,50,100]
light red is 0x800000 sRGB=[128,50]
pink is 0x800080 sRGB=[128,50]
deep purple is 0xBF80FF sRGB=[191,255] HSV=[270,100]
运行此类代码时:
#!/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,$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,$v;
print \"\\n\";
}
sub main {
my $vermilion = rgb 227,52;
my $mauve = rgb 224,255;
show mauve => $mauve;
show vermilion => $vermilion;
my $mix = alpha_blend $mauve $vermilion;
show mix => $mix;
print \"\\n\";
my $red = rgb 255,0;
my $blue = rgb 0,255;
show red => $red;
show blue => $blue;
$mix = alpha_blend $red $blue;
show \"red+blue\" => $mix;
print \"\\n\";
my $black = rgb 255,255;
my $white = rgb 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,255;
my $violet = rgb 127,255;
my $pink = alpha_blend $magenta $white;
my $deep_purple = alpha_blend $violet $black;
show pink => $pink;
show \"deep purple\" => $deep_purple;;
}