可視スペクトル範囲の各波長を同等のRGB値にマッピングするアルゴリズムまたは機能が必要です。 RGBシステムと光の波長の間に構造的な関係はありますか?この画像のように:
(ソース: kms at www1.appstate.ed )
これが関係ない場合はご容赦ください:-]
周波数と色相として知られているものの間には関係がありますが、知覚、色域の監視、およびキャリブレーションの複雑な理由により、高価なラボ機器の外で達成できる最善の方法は大まかな近似です。
数学については http://en.wikipedia.org/wiki/HSL_and_HSV を参照してください。Hue⇔Frequencyマッピングの最良の推測を考え出す必要があることに注意してください。私はこの経験的なマッピングが線形以外のものになると期待しています。
最近、私のスペクトル色は非線形でシフトされたデータに基づいているため、適切に機能しないことがわかりました。それで、私はほとんど研究とデータ編集をしませんでした、そして、そこにあるほとんどのスペクトル画像が間違っていることがわかりました。また、色の範囲が互いに一致しないため、この時点から線形化された実際の分光データのみを使用しました like this
ここに私の修正された出力があります:
以下はRGBグラフです。
これは両方のグラフのマージです:
今のコード:
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); }
}
//--------------------------------------------------------------------------
どこ
l
はl = < 400.0 , 700.0 >
と同様に使用可能な値[nm]の波長ですr,g,b
は範囲< 0.0 , 1.0 >
の色成分を返します部分的な「可視波長の近似RGB値」
クレジット:Dan Bruton-Color Science
元のFORTRANコード@( http://www.physics.sfasu.edu/astro/color/spectra.html )
赤側が重い滑らかな(連続した)スペクトルを返します。
w-波長、R、G、B-色成分
ガンマと強度の単純な葉を無視する:
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
私は答えが実際の質問の問題に対処できないと思います。
RGB値は通常、標準的な人間の観察者機能、照明、および〜360〜830の範囲の各波長でのサンプルの相対出力の組み合わせであるXYZ色空間から導出されます。
ここで何を達成しようとしているのかはわかりませんが、10 nmなどのスペクトルの各離散帯域が完全に飽和しているサンプルの比較的「正確な」RGB値を計算することは可能です。変換は、このスペクトル->XYZ->RGB
のようになります。数学については、Bruce Lindbloomのサイトをご覧ください。 XYZから、L*a*b*
などのhue
、chroma
、またはcolorimetric
の値も簡単に計算できます。
完全一致が必要な場合は、x、y、zカラーマッチング関数とスペクトル値の畳み込みを実行して、最終的に(デバイスに依存しない)XYZカラー表現を取得して、後で(デバイス-依存)RGB。
これはここで説明されています: http://www.cs.rit.edu/~ncs/color/t_spectr.html
畳み込みのx、y、zカラーマッチング関数は、次の場所にあります。 http://cvrl.ioo.ucl.ac.uk/cmfs.htm
これは、ほとんどの カラープロファイル が扱うものです。基本的に、特定のデバイス(スキャナー、カメラ、モニター、プリンターなど)について、カラープロファイルは、特定の入力セットによって生成される実際の光の色を示します。
また、ほとんどの実際のデバイスでは、少数の離散波長の光のみを処理し、その波長を直接生成することで中間色が生成されることに注意してくださいnotさまざまな量の利用可能な2つの隣接する波長を混合します。私たちが同じように色を知覚することを考えると、それは実際には問題ではありませんが、気にする理由によっては、とにかく知る価値があるかもしれません。
カラープロファイル(または同等の情報)がなければ、RGB値を色にマッピングするために必要な情報が不足しています。純粋な赤のRGB値は、通常、デバイスが生成/検知できる最も赤い色(および同様に、純粋な青が最も青い色)にマッピングされますが、「最も赤く」または「最も青い」色は(広く)変化する可能性がありますデバイスに基づきます。
まず、 CIE 1964 Supplementary Standard Colorimetric Observer chart( archive )を参照します
目的の波長のCIEカラーマッチング関数値を検索します。
たとえば、455 nmの光の色を取得したい:
希望する波長の場合:
| 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 |
注:色度座標は、CIEカラーマッチング関数から単純に計算されます。
x = X / (X+Y+Z)
y = Y / (X+Y+Z)
z = Z / (Z+Y+Z)
とすれば:
X+Y+Z = 0.342257+0.106256+1.90070 = 2.349913
計算します:
x = 0.342257 / 2.349913 = 0.145945
y = 0.106256 / 2.349913 = 0.045217
z = 1.900700 / 2.349913 = 0.808838
2つの異なる色空間を使用して、455 nmの光を指定します。
3番目の色空間を追加することもできます:xyY
x = x = 0.145945
y = y = 0.045217
Y = y = 0.045217
これで、455 nmの光が3つの異なる色空間で指定されました。
そのため、純粋な単色放射光の波長を[〜#〜] xyz [〜#〜]色に変換しました。次に、それをRGBに変換します。
[〜#〜] xyz [〜#〜]、xyz、およびxyYは、絶対物理学を使用して色を記述する絶対色空間です。
一方、人々が使用するすべての実用的な色空間:
いくつかのホワイトポイントに依存します。色は、その白色点に相対的であると説明されます。
例えば、
しかし、白のような色はありません。白をどう定義しますか?日光の色?
一部の人々は、白を意味するために(恐ろしくオレンジ色の)白熱電球の白を使用します。蛍光灯の色を使用する人もいます。白の絶対的な物理的定義はありません-白は私たちの脳の中にあります。
私たちは白をpickしなければなりません。 (本当にyouは白を選ぶ必要があります。)たくさんの白を選択できます:
私はあなたのために白を選びます。 sRGBが使用するものと同じ白:
D65(6504Kに近い色ですが、地球の大気のせいではありません)の色は次のとおりです。
これにより、XYZ
をLab
(またはLuv
)に変換できます。これは、理論上のすべての色を同等に表現できる色空間です。これで、445 nmの単色発光の4番目の色空間表現ができました。
Lab
(およびLuv
)は、some白色点に相対的な色空間です。任意のホワイトポイントを選択するように強制された場合でも、可能なすべての色を表すことができます。
RGBはそうではありません。 RGBの場合:
(255、0、0)のRGBカラーを指定した場合、「ちょうど赤」が欲しいと言っていることになります。しかし、赤の定義はありません。 「赤」、「緑」、「青」などはありません。虹は連続的であり、次のような矢印は付いていません。
これは赤です
繰り返しますが、これは、pick3原色を選択する必要があることを意味します。 「赤」、「緑」、「青」が何であるかを言うには、3つの原色を選択する必要があります。繰り返しますが、赤、緑、青のさまざまな定義から選択できます。
あなたのために選びます。 これらの3色: を選択します
これらは、1996年に国際委員会によって選ばれた予備選挙でもありました。
彼らは誰もが使うべきだと言う標準を作成しました:
そして、彼らはその標準sRGB
を呼び出しました。
これで、
残念ながら、そのRGB値にはいくつかの問題があります。
したがって、丸める必要があります。
これで、波長455 nmの光に最も近いsRGBが得られました。
Patapomはほぼ正しい:各波長についてCIE XYZ値を計算し、標準の式を使用して(たとえば)sRGBに変換します(運がよければ、この変換に使用できるコードが見つかるでしょう)。そのため、重要なステップはXYZ値を取得することです。幸いなことに、単一波長の光の場合、これは簡単です。XYZカラーマッチング関数は、特定の波長のXYZ値をリストした単なるテーブルです。調べてみてください。より複雑なスペクトル(おそらく黒体)の光がある場合は、XYZ応答と光の各波長の量を平均する必要があります。
VBAコードは、Dan Bruton([email protected])による「可視波長のRGB値」から得られます。オリジナルのFortranコードへのリンク: http://www.physics.sfasu.edu/astro/color/spectra.html スペクトルプログラム: 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