在绘制颜色的颜色空间中找到两种颜色之间的颜色的算法。

huangapple go评论139阅读模式
英文:

Algorithm for finding the color between two others - in the colorspace of painted colors

问题

当混合蓝色和黄色的颜料时,结果是一种绿色。

我有两个RGB颜色:

蓝色 = (0, 0, 255)

黄色 = (255, 255, 0)

找到混合这两种颜色的RGB颜色的算法是什么,就像使用颜料时它们会呈现的样子一样?算法得到的颜色不需要非常精确。对于上面的例子,它只需要看起来像一种绿色即可。

提前感谢。

**编辑:**这个用Go语言编写的函数对我有用,基于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}
}

编辑#2尽管这可以混合青色和黄色,但蓝色和黄色之间的混合变成了黑色,这似乎不正确。我仍然在寻找一个可行的算法。

编辑#3Mark Ransom的答案在使用HLS颜色空间时效果很好。谢谢,Mark Random。

编辑#4似乎更好的颜色混合方法是使用Kubelka-Munk方程。

英文:

When mixing blue and yellow paint, the result is some sort of green.

I have two rgb colors:

blue = (0, 0, 255)

and yellow = (255, 255, 0)

What is the algorithm for finding the rgb color that is the result of mixing the two colors, as they would appear when using paint? The resulting colors from the algorithm does not have to be terribly exact. For the example above it would only have to look like some sort of green.

Thanks in advance.

Edit: This function, written in Go, worked for me, based on the answer from 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 this manages to mix cyan and yellow, the mix between blue and yellow becomes black, which doesn't seem right. I'm still looking for a working algorithm.

Edit #3 The answer from Mark Ransom worked pretty well, using the HLS colorspace. Thanks, Mark Random.

Edit #4 It seems like the way forward for even better color mixing would be to use the Kubelka-Munk equation

答案1

得分: 13

油漆通过吸收来起作用。你从白光(255,255,255)开始,然后将其乘以吸收因子。

蓝色油漆吸收所有碰到它的红光和绿光。

黄色油漆吸收所有碰到它的蓝光。

在理想情况下,这意味着混合黄色和蓝色油漆会得到黑色油漆,或者最好是一种浑浊的灰色。实际上,“蓝色”油漆对绿色有偏好,所以你得到一种浑浊的绿色。我从未见过混合黄色和蓝色能产生令人满意的绿色的例子。维基百科详细介绍了这个过程的一些复杂性:http://en.wikipedia.org/wiki/Primary_color#Subtractive_primaries

我认为你真正想问的是如何在色轮上插值颜色。这应该与颜料吸收的颜色无关,就像RGB显示器中发光的颜色一样。

**编辑:**通过在HSL颜色空间中工作,你可以得到你想要的结果。下面是用Python实现该算法的一些代码;平均色调是棘手的,基于我之前的一个答案来平均角度(https://stackoverflow.com/questions/5343629/averaging-angles)。

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)

请注意,这个答案模拟油漆混合,原因如上所述。相反,它提供了一种直观的颜色混合,没有根据任何物理世界的实际情况。

英文:

Paint works by absorption. You start with white light (255,255,255) and multiply it by the absorption factors.

Blue paint absorbs all red and green light that hits it.

Yellow paint absorbs all blue light that hits it.

In a perfect world, that means that combining yellow and blue paint would result in black paint, or at best a muddy gray. In practice the "blue" paint has a bias towards green, so you get a muddy green. I've never seen an example of mixing yellow and blue that produces a satisfactory green. Wikipedia goes into some of the complexities of this process: http://en.wikipedia.org/wiki/Primary_color#Subtractive_primaries

I think what you are really asking is how to interpolate colors along a color wheel. This should be independent of whether the colors are absorptive as in paint, or emissive as in RGB displays.

Edit: By working in the HSL color space you can get the kind of results you're looking for. Here's some code in Python that implements the algorithm; averaging hues is tricky, and is based on a previous answer of mine for averaging angles.

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)

Note that this answer does not emulate paint mixing, for the reasons stated above. Rather it gives an intuitive mixing of colors that is not grounded in any physical world reality.

答案2

得分: 9

实际上,通过混合(减法混合)黄色和青色可以得到绿色。黄色是红色+绿色(255, 255, 0),青色是绿色+蓝色(0, 255, 255)。现在制作它们的相反颜色:蓝色(0, 0, 255)和红色(255, 0, 0)。将它们加法混合,你会得到紫色(255, 0, 255)。制作它的相反颜色,你会得到绿色(0, 255, 0)。

换句话说,你可以通过将两种颜色的相反颜色进行加法混合来得到减法混合。

英文:

Actually, you get green from mixing (subtractively) yellow and cyan. Yellow is red + green (255, 255, 0), cyan is green + blue (0, 255, 255). Now make their opposite colors: blue (0, 0, 255) and red (255, 0, 0). Mix them additively and you get purple (255, 0, 255). Make its opposite and you get green (0, 255, 0).

In other words, you can get a subtractive mix as the opposite of the additive mix of the opposites of your two colors.

答案3

得分: 4

颜色空间RGB是基于光的发射,染料和颜料的颜色空间是基于光的吸收

例如,植物之所以看起来是绿色,并不是因为它们发射绿光,而是因为它们吸收了所有其他颜色的光,只反射绿色。

基于这一点,你应该能够通过将RGB转换为吸收性颜色空间,进行“混合”,然后再转换回来,得到相当接近的结果。

英文:

The colour space RBG is based on light emission, the colour space of dyes and pigments is based on light absorption.

e.g. Plant's don't look green because they emit green light, but because they absorb all the other colours of light, reflecting only green.

Based on this, you should be able to get pretty close by doing a conversion from RGB to an absorptive colour space, doing the "mix" and then back again.

答案4

得分: 2

你想使用减法的CMY颜色(青色,洋红色,黄色)(就像LaC所做的那样,不使用该术语)

前后转换很简单:(C,M,Y)=(-R,-G,-B)。
所以CMY(0,0,0)是白色,CMY(FF,FF,FF)是黑色。

当你添加两个CMY颜色时,有不同的方法来计算新值。你可以对每个颜色值取平均值、最大值或介于两者之间的值。
例如,对于光过滤器,你总是使用最大值。对于油漆,你可能想使用更接近平均值的值。

正如LaC指出的那样,你不能通过混合黄色和蓝色来得到绿色,而是通过混合黄色和青色来得到绿色。当通过最大值混合(例如光过滤器)时,黄色和蓝色实际上会得到黑色。这就是为什么在混合油漆时,你可能想使用更接近平均值的值。

除非你想打印某些东西,否则你不想使用CMYK。黑色的“K”颜色主要用于打印机节省墨水,但不需要表示颜色。

英文:

You wanna use subtractive CMY-colors (Cyan, Magenta, Yellow) (as LaC is doing, whithout using the term)

The conversion back and forth is simple: (C,M,Y) = (-R,-G,-B).
So CMY(0,0,0) is white and CMY(FF,FF,FF) is black.

When you add two CMY colors, there are different ways to calculate the new values. You can take the average, max or something in between for each color value.
Eg. for light-filters you always use the max value. For paint you properly want to use, something closer to the average value.

As LaC points out, you don't get green from mixing yellow and blue, but from mixing yellow and cyan. Yellow and blue actually gives black, when mixing by max value (eg. light filters). This is why, you might want to use something closer to the average value for paint mixing.

You don't wanna use CMYK, unless you want to print something. The black "K" color is primarily used in printers to save ink, but it's not needed to represent colors.

答案5

得分: 1

使用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,  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]
英文:

Use Convert::Color to produce this sort of output:

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] 

When running this sort of code:

#!/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;;
}

huangapple
  • 本文由 发表于 2011年5月26日 04:38:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/6130621.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定