잡다/시각·영상

파장을 칼라로 변환하기 (Wavelength to RGB color) (2/2)

산을좋아한라쯔 2019. 9. 14. 14:21
반응형

앞 페이지에서 파장의 크기를 RGB값으로 변환하는 비교적 단순한 방법을 알아봤다.

이 방법은 파장 vs. RGB값을, 대표적으로 알려진 몇 개의 포인트를 기준으로 하고, 그 사이의 파장에 대해서는 비례식으로 구하는 것이었다. 이 방법은 간단한 방법이면서도 파장별 칼라의 변환을 그럴싸하게 하는 장점이 있으나, 비례식을 사용하였기에 실제 파장에 따른 값이 아니라 근사값이라는 찝찝함이 있다.


좀 복잡하지만 그럴싸한 변환 방법이 있다.

CIE(국제 조명 위원회)에서 실험치로 얻어낸 칼라 매칭 함수 테이블을 이용하는 방법이다.


[방법2] Color Matching Function(CMF) 데이터 이용하여 변환

이 방법은 CIE(국제 조명 위원회)의 실제 실험 데이터를 이용해서 변환하는 것으로, 꽤 복잡하다.

그러나, 이 방법은 실제 데이터를 이용해서 변환 했기에 실측값에 가깝고, 또한 여러 파장을 합성했을 때의 RGB칼라값도 구할 수 있는 이점이 있다.


변환 방법을 도식화해보면 다음과 같다.


[그림] 파장 -->RGB 변환 도식도


변환 과정을 보면 전체 5단계의 과정으로 나눌 수 있다. 각 단계별로 설명한다.


(단계 1) 칼라 매칭 함수(Color Matching Function, CMF)에 의한 변환

단계 1은 단일 파장 빛의 색상을 어떤 RGB 조합을 통해서 만들 수 있는가에 대한 변환이다. 파장별 RGB값은 x', y', z'이라는 값으로 이미 알려진 값이 존재한다.


1931년에 CIE(국제 조명 위원회)에서는 각 파장별 빛이, Red, Green, Blue의 3가지 빛의 어떠한 조합에 의해서 생성되는지를 수치화한 실험을 실시했다. (모든 색은 R/G/B 3가지 색의 합성으로 만들 수 있다는 것은 이미 알려져 있는 상태였다.)


실험 방법은 이렇다. 왼 쪽은 5nm씩 파장을 조절하면서 빛이 나오게 하고, 오른 쪽은 R,G,B 빛의 양을 각각 조절하면서 왼쪽 편과 똑같은 색이 나오게 하고, 똑 같은 색상일 때의 오른편의 R,G,B값을 기록.


[그림] CIE의 칼라매칭함수(CMF)를 찾기 위한 실험


[실험 방법]

 a) 왼쪽 편에 파장 380nm의 빛이 나오게 한다.

 e) 왼쪽 편 파장값을 5nm 증가해서 b)~d)과정을 반복하는 것을 780nm가 될 때가지 시도한다.

 c) 오른편의 R, G, B 광원의 값을 변경해가면서, 왼쪽과 오른쪽 빛의 색깔이 같을 때의 값을 찾는다.

 d) 만약 오른편 R,G,B 값 변경에 의해서 동일한 상태값을 못 찾는다면, 왼쪽편에 R 광원을 추가해서 동일한 상태값을 찾는다.

 e) 왼쪽 편 파장값을 5nm 증가해서 b)~d)과정을 반복하는 것을 780nm가 될 때가지 시도한다.


이렇게 해서 얻은 값은 아래 그래프와 같은 모양이다.





[그림]CIE의 칼라 매칭함수 실험 데이터(출처:https://en.wikipedia.org/wiki/CIE_1931_color_space)


그래프에서 R값이 음수인 영역은, 실험에서 오른 쪽에 있는 RGB 값을 변형해서 동일한 빛을 찾아내지 못하고, 왼편에 R램프를 부가해야만 같은 빛이 나오는 경우를 말한다.

이를, R값이 모두 양수가 되도록 임의로 변형하면 다음과 같이된다.


[그림] R값이 보정된 칼라 매칭함수 그래프



이렇게 구한 파장별 R, G, B값을 상대적인 색체 값을 가지는 r, g, b 값으로 변형할 수 있다.

     r = R / (R+G+B), g = G/(R+G+B), b = B/(R+G+B)=1-(r+b)

 

어떤 빛에 대해, 위와 같은 식에 의해 계산된 r,g,b 값으로 표현하게 되면, 이 때 각 r,g,b의 값은 상대적을 R,G,B값이 얼마나 많은 지를 나타내게 된다. 예를 들어 (r,g,b) = (0.3 , 0.7, 0) 이면 R값이 전체 색 량에서 30%, G값이 70% 있다는 의미가 된다.

또한, r+b+g=1 이기에, r과 g값을 알게되면 b값은 자연히 알게 되기에, r과 g 두 개의 값을 가지고 표현할 수 있게된다.

아래는 1931년도 CIE 데이터의 r, g 값을 그래프로 나타낸 것이다.


[그림] r과 g를 이용해서 표현 (출처:https://medium.com/hipster-color-science/a-beginners-guide-to-colorimetry-401f1830b65a)


이 r, g 그래프를 보면 값이 음수인 영역이 존재한다. 이를 모두 양수가 되도록 변환을 할 수 있다.


   


변환되는 값을 x,y,z라고 하면, 위와 같은 행렬식을 r,g,b값에 곱함으로써 모두 양수인 x,y,z를 구할 수 있을 것이다. 이렇게 구한 x,y,z 값은, 역시 x+y+z = 1이 성립하기에, z=1-(x+y)이고, 따라서 x와 y만으로 값을 표현할 수 있다.





이제 위에서 변환되었던 과정을 차분히 생각해 보면, 먼저 실험을 통해서 단일 파장에 의한 색상과 동일한 색상이 되는 R,G,B 조합 값을 구했다. 즉, 파장별로 어느 만큼의 R,G,B 값으로 합성하면 그 파장의 색이 나오는 지를 실험치로 알아냈다. 이를 상대적인 값인 r,g,b값으로 변환해봤고, 이 r,g,b값이 음수인 경우가 있기에 이를 양수 값만을 가지도록 선형변환을 해서 x,y,z 값으로 바꿀 수 있었다.

R,G,B <--> r,g,b의 대응과 같은 원리로 X,Y,Z <--> x,y,z인 값을 생각할 수 있고, 결국 R,G,B <--> X, Y, Z로 변환할 수 있다.


즉, R,G,B가 아닌 X,Y,Z의 값으로 표현하면 상대적인 값 표시인 x,y,z를 했을 때 음수없이 표현할 수 있기에, 1931년도 CIE의 실험에서는, 실험에 의해서 구해진 R,G,B 값을 X,Y,Z로 변환해서 표현했고, 이 X, Y, Z가 대부분의 칼라 표현 시스템에서 기본으로 삼는 값으로 여겨지게 되었다.


아래 csv 파일은 CIE 1931년도의 파장별 X, Y, Z 값이다. (파장은 5nm 간격으로 구해짐)


CIE_1931_XYZ.csv


(데이터 출처: http://cvrl.ucl.ac.uk/cmfs.htm)


파장별 X,Y,Z 값을 그려보면 다음과 같다.

[그림] 파장에 따른 X,Y,Z (1931 CIE 데이터)


X,Y,Z 값의 의미를 좀 생각해 봐야한다. X,Y,Z값은 R,G,B 값을 선형변환 한 것이기에, 그냥 R,G,B 값으로 생각해도 무방하다.


어떤 빛의 파장에 따른 색은 정해져 있다. 근데, 이 색을 Red인 빛, Blue인 빛, Green의 빛을 어느 정도 비율로 섞으면, 그 해당 파장의 색과 같이 되는 지가 CIE의 R,G,B 값이었고, 이 R,G,B값을 선형변환한 것이 X,Y,Z 값이다.

따라서, 누군가가 R,G,B 색의 조명기구를 가지고 있고, 특정 파장의 색을 표현하고 싶으면, CIE 데이터 테이블을 참조해서, 해당 파장에 해당하는 X,Y,Z 만큼의 값이되게 R,G,B 램프를 비추면, 해당 파장의 색이 재현될 수 있다는 의미이다.   



(단계 2) 스펙트럼

스펙트럼은 광원에서 나오는 빛에 대한 파장별 에너지 값을 나타낸다. 이 값은 CIE에서 표준값으로 제시한 데이터에서 찾을 수 있다.


광원이라 함은 태양, 조명기구 등 빛을 발산하는 물체이다. 각 광원은 단일 파장의 빛을 내는 경우도 있고 여러 파장의 빛을 가지는 경우도 있다.

CIE에서는 몇 가지 표준 스펙트럼을 제시하고 있는데, 대표적인 것이 D65이다. D65는 일반적인 맑은 날의 야외에서와 같은 조명이다. 즉, 그 때 야외에서 검출되는 각 파장별 세기만큼을 값으로 나타낸 것이다.


D65의 데이터는 아래 D65.CSV 파일과 같고, 파장별 값을 그래프로 나타내면 아래와 같다.


D65.csv




[그림] D65 데이터



(단계 3) XYZ의 계산

광원에서 나오는 파장별 값과 칼라 매칭 함수의 파장별 x', y', z'값을 곱하면 X, Y, Z값이 나오게 된다. 이것을 식을 나타내면 아래와 같다.

 


우리가 햇빛 아래에서 어떤 물체의 색을 인지하는 과정을 생각해 보면, 햇빛이 파장별 값이 존재하고 이러한 빛이 어떤 물체에 비추어져서 반사되어서 각 파장이 우리 눈에 들어와서 눈에 있는 시각세포에 반응해서, 그 물체의 색상을 인지하게 된다.

단계 2에서 정의한 스펙트럼이 어떤 광원이 내뿜는 각 파장별 값인 것이고, 단계 1에서 얘기한 x' y' z' 값이 우리 눈이 반응하는 RGB값에 관계된 값인 것이다.

따라서, 어떤 광원하에서 어떤 물체가 어떤 빛을 내는 가를 알려면, R과 유사한 값인 X의 값은, 광원이 가지는 각 파장값에 x'값을 곱한 것을 전부 합하면 되는 것이다. 마찬가지로 G에 유사한 Y값은 y'값을, B에 해당하는 Z값은 z'값을 곱해서 합을 구하면 되는 것이다.


만일 광원이 단일 파장이라면(λ1), P(λ)값에대해 특정 파장 값만 존재하고 나머지 값은 0이기에 X = x'(λ1), Y=y'(λ1), Z=z'(λ1) 이 될 것이다.


엑셀을 이용해서 XYZ을 계산해보면 이해가 쉽다.


엑셀에서 아래와 같이 만든다. x' y' z'은 CIE_1931 데이터이고, P_D65는 D65.CSV에 있는 데이터이다.

(실습에 사용한 엑셀 파일은 XYZ.xlsx)


XYZ.xlsx



파장

x'

y'

z'

P_D65

X(λ)

Y(λ)

Z(λ)

380

0.001368

0.000039

0.006450001

49.9755

 

 

 

385

0.002236

0.000064

0.01054999

52.3118

 

 

 

...

...

...

...

...

 

 

 

775

5.87065E-05

0.0000212

0

65.0941

 

 

 

780

4.15099E-05

0.00001499

0

63.3828

 

 

 

XYZ

 

 

 

XYZ/△λ

 

 

 



X(λ)=x'(λ) x P(λ), Y(λ)=y'(λ) x P(λ), Z(λ)=z'(λ) x P(λ)이기에, 각 파장별로 x' x P, y' x P, z' x P를 하고, 그 값을 모두 더하면 X, Y, Z값이 나오게 된다. 이 X, Y, Z값은 모든 파장에 대한 합이어서 너무 큰 수가 나오기에 이를 파장범위인 △λ=780-380을 하게되면 적절한 X,Y,Z값을 구할 수 있다. 


(단계 4) RGB의 계산

앞에서 구한 X,Y,Z는 CIE에서 정의한 칼라 스페이스의 값이고 이는 인간이 인지하는 R, G, B 색상의 감도와 관련된 값이다. 이를 다시 모니터나 프린터에서 사용될 수 있는 R,G,B 값으로 사용하기 위해서는 X,Y,Z값을 변환해야한다.


RGB 칼라 스페이스는 여러 종류가 있다. Adobe RGB, Microsoft의 sRGB 등이 그 것인데, CIE의 X,Y,Z 값으로부터 유도된 x, y평면과 각 칼라 스페이스와의 관계는 다음과 같다.



[그림]CIE의 xy값과 여러 RGB칼라 스페이스와의 관계 (출처:https://en.wikipedia.org/wiki/Color_space)


여기서는 sRGB로 변환해보겠다.


XYZ 값을 sRGB값으로 변환하는 것은 아래 연산으로 가능하다. (출처:https://www.image-engineering.de/library/technotes/958-how-to-convert-between-srgb-and-ciexyz)



 


V는 R,G,B 값이고, V'은 R', G', B' 값이다.

V'을 V로 바꾸는 것은 일종의 감마 보정(Gamma Correction)이다.

감마 보정은, 인간의 눈이 자극에 대해 선형적인 인식을 하는것이 아니고 로그곡선과 같은 인식을 보인다는 것에 근거한 보정으로, 원래의 값에 지수승을 해서 원래의 값이 클 수록 더 커지도록 보정을 하는 것이다. 이래야 우리 눈이 색상의 변화를 오히려 선형적으로 부드럽게 증감하는 것으로 느끼게 된다.


이렇게 구해진 R,G,B값을 0~255까지의 디지털 값으로 바꿀때는, 0보다 작은 값은 0으로, 1보다 큰 값은 255, 0~1 사이 값은 255를 곱하면 된다.


[실습1] CIE1931_5nm 값을 이용해서 각 파장별 RGB칼라 구하기

CIE 1931 데이터는 5nm 파장 크기 단위로, 각 파장별 X, Y, Z 값이 구해져 있다. 이 데이터를 이용해서 각 파장별 RGB칼라 값을 구해보자.


엑셀을 이용해서 아래와 같이 만든다.

(최종 완성된 엑셀파일은, sRGB.xlsm)


sRGB.xlsm



파장

x'

y'

z'

X

Y

Z

R'

G'

B'

R

G

B

R
(0~255)

G
(0~255)

B
(0~255)

380

0.001368

0.000039

0.006450001

 

 

 

 

 

 

 

 

 

 

 

 

385

0.002236

0.000064

0.01054999

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

775

   0.0000587065

0.0000212

0

 

 

 

 

 

 

 

 

 

 

 

 

780

   0.0000415099

0.00001499

0

 

 

 

 

 

 

 

 

 

 

 

 


1)XYZ 계산

각 파장별 RGB값을 구한다는 것은, 단일파장의 빛에 대한 값을 구하는 것이기에, 해당 파장의 값만 있고 나머지 파장 값은 없는 광원이 비쳐진다고 생각할 수 있다. 따라서, X, Y, Z 값은 x' x P, y' x P, z' x P 이고, P의 값을 1로 두면, X=x', Y=y', Z=z'이라고 해도 무방하다.


2)R' G' B' 계산

R', G', B'은 위 쪽 [단계 4]에서 언급된 행렬식에 의해 계산된다.


엑셀에서 행렬곱 함수는 MMULT 이고, 가로 방향의 값을 세로 방향의 값으로 변형시키는 함수는 TRANSPOSE이기에, 아래와 같이 계산식을 세울 수 있다.


X

Y

Z

R'

0.1368

0.0039

0.6450001

=TRANSPOSE(MMULT($H$2:$J$4,TRANSPOSE(E7:G7)))



위 식에서 $H$2:$J$4에 있는 행렬값은,

3.240454

-1.53714

-0.49853

-0.96927

1.876011

0.041556

0.055643

-0.20403

1.057225


G'과 B'도 같은 방법으로 구한다.


G'

B'

=TRANSPOSE(MMULT($H$2:$J$4,TRANSPOSE(E7:G7)))

=TRANSPOSE(MMULT($H$2:$J$4,TRANSPOSE(E7:G7)))


3)R G B 계산 (감마 보정)

감마 보정식은,

K,L,M열에 있는 R,G,B값을 아래식으로 구한다.

R
=IF(H7<0.0031308,H7*12.92,(1.055*H7^(1/2.4))-0.055)


G
=IF(I7<0.0031308,I7*12.92,(1.055*I7^(1/2.4))-0.055)


B
=IF(J7<0.0031308,J7*12.92,(1.055*J7^(1/2.4))-0.055)


4)0~255까지의 디지털 값으로 변환

N, O, P열에 R(0~255), G(0~255), B(0~255)값을 구한다.

R(0~255)
=IF(K7<=0,0,IF(K7>=1,255,INT(K7*255)))


G(0~255)
=IF(L7<=0,0,IF(L7>=1,255,INT(L7*255)))


B(0~255)
=IF(M7<=0,0,IF(M7>=1,255,INT(M7*255)))


5)칼라 색상

구한 RGB 값에 의한 실제 색상을 보기위해 R열에 있는 각 셀의 색상을 해당 RGB값으로 나타내본다.

이를 위한 매크로 프로그래밍은 다음과 같다.


Sub DisplayRGBColor()
  Const COLOR_COLUMN = 17
  Const START_ROW = 7, END_ROW = 87
  Dim r As Long, c As Long
  Dim red As Integer, green As Integer, blue As Integer
  Sheets("sRGB").Activate
  c = COLOR_COLUMN
  For r = START_ROW To END_ROW
    red = Cells(r, c - 3).Value
    green = Cells(r, c - 2).Value
    blue = Cells(r, c - 1).Value
    Cells(r, c).Interior.Color = RGB(red, green, blue)
  Next r
End Sub


위 프로그램을 실행하면 17칼럼(Q열)에 각 파장에 따른 RGB값으로 셀 색상이 바뀌게 된다.

이 셀값을 가로로 바꿔서 보면 다음과 같은 색상 막대로 보일 것이다. ( sRGB.xlsm의 "sRGB"시트에서 발견할 수 있을 것임)




위에서 사용한 데이터는 5nm 간격의 파장에 대한 데이터이다. 이를 0.1nm 간격의 데이터를 사용하면, 좀 더 세밀한 구분이 되는 파장 대 RGB값을 구할 수 있을 것이다. sRGB_detailed.xlsm에 그 값을 작성해봤다. 참조.


sRGB_detailed.xlsm



--------------------------------------------------------------------------

위에서 파장별 RGB값 변환을, 단일 파장의 빛이라고 가정하고 계산해서 구했다.

파장 간격을 1nm로 했을 때 380nm~780nm이면 최대 400개의 다른 색상이 나올 수 있을 것이고, 0.1nm로 하면 최대 4000개의 다른 RGB값이 나올 수 있을 것이다.

그러나, RGB값이 각가 0~255의 값을 가질 수 있기에, 순수하게 RGB값이 가질 수 있는 색상 수는 16,777,216개이다. (물론 인간이 이를 다 구분 할 수 있는 색감 능력이 있다는 얘기는 아니다.)


위 사실을 가지고 생각해보면, 단일 파장을 구분해서 RGB값이 가질 수 있는 1677만여개의 색상을 만들어내는 것은 말이 안되는 얘기다. 가능한 방법이 있을까?

다른 값을 가지는 여러 파장의 빛을 혼합하면 가능할 것이다. 위쪽에서 X, Y, Z의 값이 다음과 같이 구해진다고 했다.


X의 값은 380nm~780nm까지의 가시광선 영역에서의 x'값에 P(λ) 값을 곱해서 전체를 합한 것이다. 여기서 x'(λ)는 고정된 값이기에 P(λ)를 일종의 필터로 생각한다면, 어떤 값 X가 나오게 하기 위해서 어떤 필터 P(λ)를 사용하면 되는가의 문제로 바뀌게 된다. 마찬가지고 Y와 Z에 대해서도 같이 생각할 수 있고, 결국은 목적하는 RGB값에 해당하는 XYZ값이 있을 때, 이 XYZ값을 나오게 하는(혹은 가장 근접한 값이 나오는) 필터 P(λ)를 선택하는 문제가된다.


    P = x' / X = y' / Y = z' / Z  ==> 이 식을 만족하는 P를 구하면 됨   


목표하는 RGB값에 대해 어떤 P를 선택하면되는지, 어떻게 구할 수 있는 지 대략 아이디어는 있는데 지금 이것을 구할 시간이 없다. 다음에, 다음에 구해봐야겠다.



D65.csv
0.0MB
CIE_1931_XYZ.csv
0.0MB
sRGB.xlsm
0.85MB
XYZ.xlsx
0.03MB
sRGB_detailed.xlsm
2.08MB
반응형