计算混合颜色的RGB代码,假设红色,蓝色和黄色作为原色

时间:2012-01-26 21:48:13

标签: colors

浅色和油漆之间存在不匹配:虽然物理学家会说三原色是红色,绿色和蓝色,但画家会将红色,蓝色和黄色作为原色。 事实上,当用水彩画画时,你不能混合红色,绿色和蓝色的黄色,而不是混合橙色,你只会变成棕色。

以下是我尝试做的事情:从两种给定的RGB颜色开始,我想计算组合颜色的RGB代码,并且我喜欢像水彩一样混合的颜色在纸上。据我所知,计算通常如下:

  • #FF0000 +#0000FF =#880088((FF + 00)/ 2 = 88,(00 + 00)/ 2 = 00,(00 + FF)/ 2 = 88),所以红色和蓝色给出紫色(因为它应该)
  • #FF0000 +#FFFF00 =#FF8800((FF + FF)/ 2 = FF,(00 + FF)/ 2 = 88,(00 + 00)/ 2 = 00),所以红色和黄色给出橙色(因为它应该)

然而,当混合蓝色和黄色时,结果是灰色的:

  • #0000FF +#FFFF00 =#888888((00 + FF)/ 2 = 88,(00 + FF)/ 2 = 88,(FF + 00)/ 2 = 88)=灰色

在纸上你期望变绿(#008800)并且在混合颜色时永远不会变灰。

所以我的问题是,我怎样才能将绿色与黄色交换为原色,然后如何计算出符合油漆定律而非浅色定律的混合色?

4 个答案:

答案 0 :(得分:5)

没有简单的物理模型可以做到这一点,画家的颜色与光有非常精细的相互作用。幸运的是,我们有计算机,不仅限于物理世界的建模 - 我们可以让它们做任何我们想要的任意事情!

第一步是创建一个具有我们需要的色调分布的色轮,红色,黄色和蓝色以120度的增量。网上有很多例子。我在这里创建了一个只有完全饱和的颜色,以便它可以用来生成完整的RGB色域。车轮上的颜色完全是任意的;我将橙色(60°)设置为(255,160,0),因为红色和黄色之间的中点太红,我将纯蓝色(0,0,255)移动到250°而不是240°,因此240°蓝色看起来会更好。

RYB hue color wheel

记住我童年的实验,当你将等量的红色,黄色和蓝色混合在一起时,你会得到一个模糊的棕灰色。我选择了一种合适的颜色,你可以在色轮的中心看到它;在代码中我亲切地称它为“泥”。

要获得除红色,黄色和蓝色之外的所有可能颜色,还需要混合白色和黑色。例如,你通过混合红色和白色获得粉红色,然后通过将橙色(黄色+红色)与黑色混合来获得棕色。

转换适用于比率,而不是绝对数字。与真正的油漆一样,混合1份红色和1份黄色,100份红色和100份黄色没有区别。

代码以Python格式呈现,但转换为其他语言并不难。最棘手的部分是添加红色,黄色和蓝色以创建色调角度。我使用向量加法并转换回atan2的角度。几乎所有其他事情都是通过线性插值(lerp)完成的。

# elementary_colors.py
from math import degrees, radians, atan2, sin, cos

red = (255, 0, 0)
orange = (255, 160, 0)
yellow = (255, 255, 0)
green = (0, 255, 0)
cyan = (0, 255, 255)
blue = (0, 0, 255)
magenta = (255, 0, 255)
white = (255, 255, 255)
black = (0, 0, 0)
mud = (94, 81, 74)

colorwheel = [(0, red), (60, orange), (120, yellow), (180, green),
              (215, cyan), (250, blue), (330, magenta), (360, red)]

red_x, red_y = cos(radians(0)), sin(radians(0))
yellow_x, yellow_y = cos(radians(120)), sin(radians(120))
blue_x, blue_y = cos(radians(240)), sin(radians(240))

def lerp(left, right, left_part, total):
    if total == 0:
        return left
    ratio = float(left_part) / total
    return [l * ratio + r * (1.0 - ratio) for l,r in zip(left, right)]

def hue_to_rgb(deg):
    deg = deg % 360
    previous_angle, previous_color = colorwheel[0]
    for angle, color in colorwheel:
        if deg <= angle:
            return lerp(previous_color, color, angle - deg, angle - previous_angle)
        previous_angle = angle
        previous_color = color

def int_rgb(rgb):
    return tuple(int(c * 255.99 / 255) for c in rgb)

def rybwk_to_rgb(r, y, b, w, k):
    if r == 0 and y == 0 and b == 0:
        rgb = white
    else:
        hue = degrees(atan2(r * red_y + y * yellow_y + b * blue_y,
                            r * red_x + y * yellow_x + b * blue_x))
        rgb = hue_to_rgb(hue)
        rgb = lerp(mud, rgb, min(r, y, b), max(r, y, b))
    gray = lerp(white, black, w, w+k)
    rgb = lerp(rgb, gray, r+y+b, r+y+b+w+k)
    return int_rgb(rgb)

答案 1 :(得分:1)

如果你把红色,蓝色和黄色的颜料混合在一起,你会得到一个黑褐色,而不是黑色。那是因为“红色,蓝色和黄色”并不是真正的原色。青色,洋红色和黄色,这就是打印机在CMYK(K为黑色)工作的原因。

所以你真正要问的是如何将RGB颜色转换为CMYK,在这种情况下any of these links可以帮助你。

答案 2 :(得分:1)

我建议退出初选的概念,无论是RGB还是RYB或CMY等。

据我了解,您的目标是以模拟油漆混合方式(即减色混合)的方式混合颜色(在RGB颜色空间中描述)。从RGB转换为CMY或CMYK将不会有效,因为您仍然需要处理减法混合计算,这在CMY空间中并不容易。

相反,我建议您考虑将RGB颜色转换为光谱反射率曲线。转换非常简单,一旦完成,就可以对反射曲线进行真正的减法混合,然后将结果转换回RGB。

还有另一个类似的问题:https://stackoverflow.com/questions/10254022/,更详细地讨论了这个过程。

答案 3 :(得分:0)

青色,洋红色和黄色应该是红色,黄色和蓝色是中世纪的惯例。

显然这不是一个简单的转换,我在数学中间睡着了,但这是一种方式。

RYB RGB Conversion