Algorithme pour trouver la couleur entre deux autres - dans l'espace des couleurs peintes

en mélangeant du bleu et du jaune, le résultat est une sorte de vert.

j'ai deux couleurs rgb:

Bleu = (0, 0, 255)

et jaune = (255, 255, 0)

Quel est l'algorithme pour trouver la couleur RVB qui est le résultat du mélange des deux couleurs, comme ils apparaissent lors de l'utilisation de la peinture? Les couleurs résultantes de l'algorithme ne doit pas être terriblement exacte. Pour l'exemple ci-dessus ne devrait plus ressembler à une sorte de vert.

Merci d'avance.

modifier: cette fonction, écrite en Go, a fonctionné pour moi, d'après la réponse de bac.

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 cela arrive à mélanger le cyan et le jaune, le mélange entre le bleu et le jaune devient noir, ce qui ne semble pas juste. Je cherche toujours un algorithme qui fonctionne.

Edit #3 voici un exemple de travail complet dans Go, en utilisant le colorspace HLS: http://go.pastie.org/1976031 . Merci Mark Ransom.

Edit #4 Il semble que la voie à suivre, même pour un meilleur mélange des couleurs serait d'utiliser la Kubelka-Munk équation

26
demandé sur Alexander 2011-05-26 00:38:23

5 réponses

peinture fonctionne par absorption. On commence avec la lumière blanche (255,255,255) et on la multiplie par les facteurs d'absorption.

la peinture bleue absorbe toute la lumière rouge et verte qui la frappe.

la peinture jaune absorbe toute la lumière bleue qui la frappe.

dans un monde parfait, cela signifie que la combinaison de la peinture jaune et bleue résulterait en une peinture noire, ou au mieux un gris boueux. En pratique, la peinture "bleue" a un penchant pour le vert, donc vous prends un vert boueux. Je n'ai jamais vu un exemple de mélange de jaune et de bleu qui produit satisfaisant vert. Wikipedia entre dans certaines des complexités de ce processus: http://en.wikipedia.org/wiki/Primary_color#Subtractive_primaries

je pense que ce que vous demandez vraiment est comment interpoler les couleurs le long d'une roue de couleur. Cela devrait être indépendant de si les couleurs sont absorbantes comme dans la peinture, ou émissive comme dans les écrans RVB.

Edit: en travaillant dans l'espace couleur HSL vous pouvez obtenir le genre de résultats que vous recherchez. Voici un code en Python qui implémente l'algorithme; la moyenne des teintes est délicate, et est basée sur une réponse précédente de la mienne pour la moyenne des 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)

notez que cette réponse n'est pas émule le mélange de peinture, pour les raisons indiquées ci-dessus. Il donne plutôt un mélange intuitif de des couleurs qui ne sont pas ancrées dans la réalité physique du monde.

12
répondu Mark Ransom 2017-05-23 12:30:17

en fait, on obtient du vert en mélangeant (soustractivement) du jaune et du cyan. Le jaune est rouge + vert (255, 255, 0), le cyan est vert + bleu (0, 255, 255). Maintenant faire leurs couleurs opposées: bleu (0, 0, 255) et rouge (255, 0, 0). Mélangez-les additivement et vous obtenez pourpre (255, 0, 255). Faites son contraire et vous obtenez Vert (0, 255, 0).

En d'autres termes, vous pouvez obtenir un mélange soustractif comme le contraire de l'additif mélange des contraires de vos deux couleurs.

9
répondu LaC 2011-05-25 21:02:09

L'espace de couleur RBG est basé sur la lumière émission , l'espace de couleur des colorants et des pigments est basé sur la lumière absorption .

p.ex. les végétaux n'ont pas l'air vert parce qu'ils émettent de la lumière verte, mais parce qu'ils absorbent toutes les couleurs de lumière autres , réfléchissant uniquement le vert.

basé sur cela, vous devriez être en mesure d'obtenir assez proche en faisant une conversion de RGB à un espace de couleur absorbant, en faisant le "mélange" puis de nouveau.

4
répondu Bevan 2011-05-25 21:02:27

Tu veux utiliser soustractive CMY-couleurs (Cyan, Magenta, Jaune) (que le LaC est en train de faire, sans utiliser le terme)

la conversion en va-et-vient est simple: (C,M,Y) = (- R, - G, - B).

Donc CMY (0,0) est blanc et CMY (FF,FF,FF) est noir.

lorsque vous ajoutez deux couleurs CMY, il y a différentes façons de calculer les nouvelles valeurs. Vous pouvez prendre la moyenne, max ou quelque chose entre pour chaque valeur de couleur.

Par exemple. pour les filtres de lumière, vous utilisez toujours la valeur max. Pour la peinture que vous voulez utiliser correctement, quelque chose plus proche de la valeur moyenne.

comme le souligne LaC, on n'obtient pas le vert en mélangeant le jaune et le bleu, mais en mélangeant le jaune et le cyan. Le jaune et le bleu donnent en fait noir, lorsque le mélange par la valeur max (par exemple. la lumière des filtres). C'est pourquoi, vous pourriez vouloir utiliser quelque chose de plus proche de la valeur moyenne pour mélanger la peinture.

vous ne voulez pas utiliser CMYK, à moins que vous voulez imprimer quelque chose. La couleur Noire "K" est principalement utilisée dans les imprimantes pour économiser l'encre, mais elle n'est pas nécessaire pour représenter les couleurs.

2
répondu Tobber 2011-05-25 21:48:43

utiliser convertir:: couleur pour produire ce genre de sortie:

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] 

lors de l'exécution de ce type de 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;;
}
1
répondu tchrist 2011-05-26 00:58:28