J'ai besoin d'un algorithme ou d'une fonction pour mapper chaque longueur d'onde de la gamme visible du spectre à ses valeurs RVB équivalentes. Existe-t-il une relation structurelle entre le système RVB et la longueur d'onde d'une lumière? comme cette image:
(source: km sur www1.appstate.ed )
désolé si cela n'était pas pertinent: -]
Il existe une relation entre la fréquence et ce que l'on appelle la teinte, mais pour des raisons complexes de perception, de gamme de moniteurs et d'étalonnage, le meilleur que vous puissiez obtenir en dehors d'un équipement de laboratoire coûteux est une approximation grossière.
Voir http://en.wikipedia.org/wiki/HSL_and_HSV pour les mathématiques, et notez que vous devrez trouver votre meilleure estimation pour le mappage de fréquence Hue ⇔. Je m'attends à ce que cette cartographie empirique soit tout sauf linéaire.
J'ai récemment découvert que mes couleurs spectrales ne fonctionnaient pas correctement car elles étaient basées sur des données non linéaires et décalées. J'ai donc fait peu de recherches et de compilation de données et j'ai découvert que la plupart des images du spectre étaient incorrectes. De plus, les gammes de couleurs ne correspondent pas les unes aux autres, j'ai donc utilisé à partir de ce point uniquement des données de spectroscopie réelle linéarisées comme ceci
Voici la sortie rectifiée de la mienne:
Voici les graphiques RVB:
Il s'agit de la fusion des deux graphiques:
Maintenant, le code:
void spectral_color(double &r,double &g,double &b,double l) // RGB <0,1> <- lambda l <400,700> [nm]
{
double t; r=0.0; g=0.0; b=0.0;
if ((l>=400.0)&&(l<410.0)) { t=(l-400.0)/(410.0-400.0); r= +(0.33*t)-(0.20*t*t); }
else if ((l>=410.0)&&(l<475.0)) { t=(l-410.0)/(475.0-410.0); r=0.14 -(0.13*t*t); }
else if ((l>=545.0)&&(l<595.0)) { t=(l-545.0)/(595.0-545.0); r= +(1.98*t)-( t*t); }
else if ((l>=595.0)&&(l<650.0)) { t=(l-595.0)/(650.0-595.0); r=0.98+(0.06*t)-(0.40*t*t); }
else if ((l>=650.0)&&(l<700.0)) { t=(l-650.0)/(700.0-650.0); r=0.65-(0.84*t)+(0.20*t*t); }
if ((l>=415.0)&&(l<475.0)) { t=(l-415.0)/(475.0-415.0); g= +(0.80*t*t); }
else if ((l>=475.0)&&(l<590.0)) { t=(l-475.0)/(590.0-475.0); g=0.8 +(0.76*t)-(0.80*t*t); }
else if ((l>=585.0)&&(l<639.0)) { t=(l-585.0)/(639.0-585.0); g=0.84-(0.84*t) ; }
if ((l>=400.0)&&(l<475.0)) { t=(l-400.0)/(475.0-400.0); b= +(2.20*t)-(1.50*t*t); }
else if ((l>=475.0)&&(l<560.0)) { t=(l-475.0)/(560.0-475.0); b=0.7 -( t)+(0.30*t*t); }
}
//--------------------------------------------------------------------------
Où
l
est la longueur d'onde en [nm] les valeurs utilisables sont l = < 400.0 , 700.0 >
r,g,b
renvoient des composants de couleur dans la plage < 0.0 , 1.0 >
"Valeurs RVB approximatives pour les longueurs d'onde visibles" partielles
Crédit: Dan Bruton - Science des couleurs
Code FORTRAN d'origine @ ( http://www.physics.sfasu.edu/astro/color/spectra.html )
Rendra un spectre lisse (continu), lourd sur le côté rouge.
w - longueur d'onde, R, G et B - composantes de couleur
Ignorer les feuilles simples gamma et intensité:
if w >= 380 and w < 440:
R = -(w - 440.) / (440. - 380.)
G = 0.0
B = 1.0
Elif w >= 440 and w < 490:
R = 0.0
G = (w - 440.) / (490. - 440.)
B = 1.0
Elif w >= 490 and w < 510:
R = 0.0
G = 1.0
B = -(w - 510.) / (510. - 490.)
Elif w >= 510 and w < 580:
R = (w - 510.) / (580. - 510.)
G = 1.0
B = 0.0
Elif w >= 580 and w < 645:
R = 1.0
G = -(w - 645.) / (645. - 580.)
B = 0.0
Elif w >= 645 and w <= 780:
R = 1.0
G = 0.0
B = 0.0
else:
R = 0.0
G = 0.0
B = 0.0
Je pense que les réponses ne parviennent pas à résoudre un problème avec la question réelle.
Les valeurs RVB sont généralement dérivées de l'espace colorimétrique XYZ, qui est la combinaison d'une fonction d'observation humaine standard, d'un éclairage et de la puissance relative de l'échantillon à chaque longueur d'onde sur une plage de ~ 360 à 830.
Je ne suis pas sûr de ce que vous essayez de réaliser ici, mais il serait possible de calculer une valeur RVB relativement "précise" pour un échantillon où chaque bande discrète du spectre @ disons 10 nm était entièrement saturée. La transformation ressemble à ce spectre ->XYZ->RGB
. Consultez le site de Bruce Lindbloom pour les mathématiques. A partir du XYZ, vous pouvez également calculer facilement des valeurs de hue
, chroma
ou colorimetric
telles que L*a*b*
.
Si vous voulez une correspondance exacte, la seule solution consiste à effectuer une convolution des fonctions de correspondance des couleurs x, y, z avec vos valeurs spectrales afin d'obtenir enfin une représentation des couleurs XYZ (indépendante de l'appareil) que vous pourrez ensuite convertir en (appareil -dépendant) RGB.
Ceci est décrit ici: http://www.cs.rit.edu/~ncs/color/t_spectr.html
Vous pouvez trouver la fonction de correspondance des couleurs x, y, z pour la convolution ici: http://cvrl.ioo.ucl.ac.uk/cmfs.htm
C'est la plupart de ce que profils de couleurs traitent. Fondamentalement, pour un appareil donné (scanner, appareil photo, moniteur, imprimante, etc.), un profil de couleur indique quelles couleurs réelles de lumière seront produites par un ensemble spécifique d'entrées.
Notez également que pour la plupart des appareils réels, vous ne traitez qu'avec quelques longueurs d'onde de lumière discrètes, et les couleurs intermédiaires sont produites pas en produisant directement cette longueur d'onde, mais en mélangeant des quantités variables des deux longueurs d'onde voisines disponibles. Étant donné que nous percevons la couleur de la même manière, ce n'est pas vraiment un problème, mais selon la raison pour laquelle vous vous souciez, cela vaut peut-être la peine de le savoir de toute façon.
Sans profil de couleur (ou informations équivalentes), vous ne disposez pas des informations nécessaires pour mapper la valeur RVB aux couleurs. Une valeur RVB de rouge pur correspond normalement à la couleur la plus rouge que l'appareil est capable de produire/détecter (et de même, du bleu pur à la couleur la plus bleue) - mais cette "plus rouge" ou "la plus bleue" peut et peut varier (largement) en fonction de l'appareil.
Vous consultez d'abord un CIE 1964 Supplémentaire Standard Colorimetric Observer graphique ( archive )
et recherchez les valeurs de la fonction de correspondance des couleurs CIE pour la longueur d'onde souhaitée.
Par exemple, je veux obtenir la couleur de la lumière à 455 nm:
Pour notre longueur d'onde souhaitée:
| nm | CIE color matching functions | Chromacity coordinates |
| nm | X | Y | Z | x | y | z |
|-----|----------|----------|---------|---------|---------|---------|
| 455 | 0.342957 | 0.106256 | 1.90070 | 0.14594 | 0.04522 | 0.80884 |
Remarque: Les coordonnées de chromacité sont simplement calculées à partir des fonctions de correspondance des couleurs CIE:
x = X / (X+Y+Z)
y = Y / (X+Y+Z)
z = Z / (Z+Y+Z)
Étant donné que:
X+Y+Z = 0.342257+0.106256+1.90070 = 2.349913
nous calculons:
x = 0.342257 / 2.349913 = 0.145945
y = 0.106256 / 2.349913 = 0.045217
z = 1.900700 / 2.349913 = 0.808838
Votre lumière de 455 nm est spécifiée en utilisant deux espaces colorimétriques différents:
Nous pouvons également ajouter un troisième espace colorimétrique: xyY
x = x = 0.145945
y = y = 0.045217
Y = y = 0.045217
Nous avons maintenant la lumière de 455 nm spécifiée dans 3 espaces colorimétriques différents:
Nous avons donc converti une longueur d'onde de lumière émise monochromatique pure en une couleur [~ # ~] xyz [~ # ~] . Maintenant, nous voulons convertir cela en RVB.
[~ # ~] xyz [~ # ~] , xyz , et xyY sont des espaces colorimétriques absolus qui décrivent les couleurs en utilisant la physique absolue.
Pendant ce temps, tous les espaces de couleur pratiques que les gens utilisent:
dépend certains whitepoint. Les couleurs sont ensuite décrites comme étant relatives à ce point blanc.
Par exemple,
Mais il n'y a pas de couleur comme le blanc. Comment définissez-vous le blanc? La couleur du soleil?
Certaines personnes utilisent le blanc de leurs ampoules à incandescence (horriblement orange) pour signifier blanc. Certaines personnes utilisent la couleur de leurs lampes fluorescentes. Il n'y a pas de définition physique absolue du blanc - le blanc est dans nos cerveaux.
Nous devons choisir un blanc. (Vraiment vous devez choisir un blanc.) Et il y a beaucoup de blancs au choix:
Je vais choisir un blanc pour toi. Le même blanc que sRGB utilise:
Le D65 (qui a une couleur proche de 6504K, mais pas tout à fait à cause de l'atmosphère terrestre), a une couleur de:
Avec cela, vous pouvez convertir votre XYZ
en Lab
(ou Luv
) - un espace colorimétrique également capable d'exprimer toutes les couleurs théoriques. Et maintenant, nous avons une quatrième représentation de l'espace colorimétrique de notre émission de lumière monochromatique à 445 nm:
Lab
(et Luv
) sont des espaces colorimétriques relatifs à certains point blanc. Même si vous avez été forcé de choisir un point blanc arbitraire, vous pouvez toujours représenter toutes les couleurs possibles.
RGB n'est pas comme ça. Avec RVB:
Si vous spécifiez une couleur RVB de (255, 0, 0), vous dites que vous voulez "juste du rouge". Mais il n'y a pas de définition du rouge. Il n'y a rien de tel que "rouge", "vert" ou "bleu". L'arc-en-ciel est continu et ne vient pas avec une flèche disant:
C'est rouge
Et encore une fois cela signifie que nous devons choisir trois choisir trois couleurs primaires. Vous devez choisir vos trois couleurs primaires pour dire ce que sont "rouge", "vert" et "bleu". Et encore une fois, vous avez le choix entre de nombreuses définitions différentes de rouge, vert, bleu:
Je choisirai pour toi. Je vais choisir ces trois couleurs:
Ce sont aussi les primaires choisies par un comité international en 1996.
Ils ont créé une norme selon laquelle tout le monde devrait utiliser:
Et ils ont appelé cette norme sRGB
.
Maintenant que nous avons choisi notre
nous pouvons maintenant convertir votre couleur XYZ en RVB:
Malheureusement, il y a des problèmes avec cette valeur RVB:
Nous devons donc arrondir:
Et maintenant, nous avons l'approximation sRGB la plus proche de la longueur d'onde 455 nm de lumière:
Patapom a presque raison: pour chaque longueur d'onde, vous calculez les valeurs CIE XYZ, puis les convertissez en (disons) sRGB en utilisant des formules standard (si vous êtes chanceux, vous trouverez du code que vous pouvez simplement utiliser pour effectuer cette conversion). Donc, l'étape clé consiste à obtenir les valeurs XYZ. Heureusement, pour la lumière à une seule longueur d'onde, c'est facile: les fonctions de correspondance des couleurs XYZ sont simplement des tableaux répertoriant les valeurs XYZ pour une longueur d'onde donnée. Alors, regardez-le. Si vous aviez de la lumière avec un spectre plus compliqué, peut-être un corps noir, alors vous devriez faire la moyenne des réponses XYZ fois la quantité de chaque longueur d'onde dans la lumière.
Le code VBA est dérivé des "valeurs RVB approximatives pour les longueurs d'onde visibles" de Dan Bruton ([email protected]). Lien vers son code Fortran d'origine: http://www.physics.sfasu.edu/astro/color/spectra.html Programme Spectra: http://www.efg2.com/ Lab/ScienceAndEngineering/Spectra.htm
Sub Wavelength_To_RGB()
'Purpose: Loop thru the wavelengths in the visible spectrum of light
' and output the RGB values and colors to a worksheet.
' Wavelength range: 380nm and 780nm
Dim j As Long, CellRow As Long
Dim R As Double, G As Double, B As Double
Dim iR As Integer, iG As Integer, iB As Integer
Dim WL As Double
Dim Gamma As Double
Dim SSS As Double
Gamma = 0.8
CellRow = 1
For j = 380 To 780
WL = j
Select Case WL
Case 380 To 440
R = -(WL - 440#) / (440# - 380#)
G = 0#
B = 1#
Case 440 To 490
R = 0#
G = ((WL - 440#) / (490# - 440#))
B = 1#
Case 490 To 510
R = 0#
G = 1#
B = (-(WL - 510#) / (510# - 490#))
Case 510 To 580
R = ((WL - 510#) / (580# - 510#))
G = 1#
B = 0#
Case 580 To 645
R = 1#
G = (-(WL - 645#) / (645# - 580#))
B = 0#
Case 645 To 780
R = 1#
G = 0#
B = 0#
Case Else
R = 0#
G = 0#
B = 0#
End Select
'LET THE INTENSITY SSS FALL OFF NEAR THE VISION LIMITS
If WL > 700 Then
SSS = 0.3 + 0.7 * (780# - WL) / (780# - 700#)
ElseIf WL < 420 Then
SSS = 0.3 + 0.7 * (WL - 380#) / (420# - 380#)
Else
SSS = 1#
End If
'GAMMA ADJUST
R = (SSS * R) ^ Gamma
G = (SSS * G) ^ Gamma
B = (SSS * B) ^ Gamma
'Multiply by 255
R = R * 255
G = G * 255
B = B * 255
'Change RGB data type from Double to Integer.
iR = CInt(R)
iG = CInt(G)
iB = CInt(B)
'Output to worksheet
Cells(CellRow, 1).Interior.Color = RGB(iR, iG, iB)
Cells(CellRow, 2) = WL
Cells(CellRow, 3) = "(" & iR & "," & iG & "," & iB & ")"
CellRow = CellRow + 1
Next j
End Sub