Подтвердить что ты не робот

Алгоритм поиска цвета между двумя другими - в цветовом пространстве окрашенных цветов

При смешивании синей и желтой краски результат - это своего рода зеленый цвет.

У меня есть два цвета rgb:

blue = (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. Все это позволяет смешивать голубые и желтые, сочетание между синим и желтым становится черным, что кажется неправильным. Я все еще ищу алгоритм работы.

Редактировать # 3 Здесь приведен полный рабочий пример в Go, используя цветовое пространство HLS: http://go.pastie.org/1976031. Спасибо Mark Ransom.

Изменить # 4 Кажется, что путь вперед для еще лучшего смешивания цветов заключался бы в использовании уравнения Кубельки-Мунк

4b9b3361

Ответ 1

Краска работает по поглощению. Вы начинаете с белого света (255,255,255) и умножаете его на коэффициенты поглощения.

Синяя краска поглощает весь красный и зеленый свет, попадающий в нее.

Желтая краска поглощает весь синий свет, который попадает в нее.

В идеальном мире это означает, что сочетание желтой и синей краски приведет к черной краске или, в лучшем случае, к грязной серой. На практике "синяя" краска имеет предвзятость к зеленому, поэтому вы получаете грязную зелень. Я никогда не видел примера смешивания желтого и синего, который производит удовлетворительный зеленый цвет. Википедия переходит к некоторым сложностям этого процесса: 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,255,0),(0,0,255))
(0, 255, 111)
>>> average_colors((255,255,0),(0,255,255))
(0, 255, 0)

Обратите внимание, что в этом ответе не эмулировать смешивание краски по причинам, указанным выше. Скорее, это дает интуитивное смешивание цветов, которое не заземлено ни в какой физической реальности мира.

Ответ 2

На самом деле, вы получаете зеленый цвет от смешивания (вычитательно) желтого и голубого. Желтый красный + зеленый (255, 255, 0), голубой - зеленый + синий (0, 255, 255). Теперь сделайте их противоположные цвета: синий (0, 0, 255) и красный (255, 0, 0). Смешайте их аддитивно, и вы получите фиолетовый (255, 0, 255). Сделайте свою противоположность, и вы получите зеленый (0, 255, 0).

Другими словами, вы можете получить субтрактивный микс, противоположный аддитивному сочетанию противоположностей ваших двух цветов.

Ответ 3

Цветовое пространство RBG основано на световом излучении, цветовое пространство красителей и пигментов основано на поглощении света.

например. Растение не выглядит зеленым, потому что они излучают зеленый свет, а потому, что поглощают все другие цвета света, отражающие только зеленый цвет.

Основываясь на этом, вы должны быть достаточно близки, делая преобразование из RGB в абсорбирующее цветовое пространство, делая "mix", а затем обратно.

Ответ 4

Вы хотите использовать субтрактивные CMY-цвета (голубой, пурпурный, желтый) (как делает LaC, не используя термин)

Преобразование вперед и назад прост: (C, M, Y) = (-R, -G, -B).
Таким образом, CMY (0,0,0) является белым, а CMY (FF, FF, FF) является черным.

Когда вы добавляете два CMY-цвета, существуют различные способы вычисления новых значений. Вы можете взять среднее, максимальное или что-то среднее между каждым значением цвета.
Например. для светофильтров вы всегда используете максимальное значение. Для краски, которую вы правильно используете, что-то ближе к среднему значению.

Как указывает LaC, вы не получаете зеленый цвет от смешивания желтого и синего, а от смешивания желтого и голубого. Желтый и синий на самом деле придает черный цвет при смешивании с максимальным значением (например, светофильтры). Вот почему вы можете использовать что-то ближе к среднему значению смешивания краски.

Вы не хотите использовать CMYK, если вы не хотите что-то печатать. Черный цвет "K" в основном используется в принтерах для экономии чернил, но не нужно представлять цвета.

Ответ 5

Используйте 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] 

При запуске такого типа кода:

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