Skip to content

CIELAB color space

Lab 색 공간은 인간 시각의 길항 이론에 의거하여, CIE XYZ 색 공간을 비선형 변환하여 만들어진 색 공간이다.

원래 Lab 색 공간이라는 용어는 Hunter 1948 Lab 색 공간을 가리켰으나, 현대에 들어 CIE 1976 Lab* 색 공간을 가리키게 되었다. 두 색 공간 모두 인간의 색채 지각에 대한 연구를 바탕으로 한 CIE XYZ 색 공간을 변환하여 만들어졌다. 두 색 공간의 차이는, Hunter 1948 색 공간은 2차함수를 바탕으로 한 변환이며, CIE 1976 색 공간은 3차함수를 바탕으로 한 변환이라는 차이가 있다. 또한, 양쪽 모두 먼셀 색 체계에 영향을 받아, XYZ 색 공간보다 균일한 색 체계를 목표로 하였다. 여기서 균일한 색 체계는, 색 공간에서 같은 거리만큼 떨어진 색채가, 인간의 눈에 같은 크기만큼의 색 차이로 인지되는 것을 목표로 했다는 의미이다.

Lab 색 공간은 XYZ에서 정의된 흰색에 대한 상대값으로 정의되어 있다. 따라서 흰색의 값에 따라 서로 다른 색을 가리킬 수 있다. 보통 CIE 표준 광원인 D50이 많이 쓰이지만, 환경에 따라 서로 다른 광원을 사용할 수 있다.

Lab* 색 공간은 RGB나 CMYK가 표현할 수 있는 모든 색역을 포함하며, 인간이 지각할 수 없는 색깔도 포함하고 있다.

장점

Lab 색 공간의 가장 큰 장점은 RGB나 CMYK와 달리 매체에 독립적이라는 것이다. 디스플레이 장비나 인쇄 매체에 따라 색이 달라지는 색 공간과 달리 Lab* 색 공간은 인간의 시각에 대한 연구를 바탕으로 정의되었다. 특히 휘도 축인 L 값은 인간이 느끼는 밝기에 대응하도록 설계되었다.

Lab 색 공간의 색역은 컴퓨터 디스플레이나 인쇄 매체는 물론 인간이 지각할 수 있는 색 영역보다도 훨씬 크다. 따라서 RGB나 CMYK보다 더 정밀한 값으로 표현해야 한다. 80년대까지 대부분의 이미지 포맷은 8비트만을 지원하였으므로 Lab 색 공간을 표현하기에 부적합했으나, 지금은 대부분의 포맷이 16비트 이미지를 지원하므로 이러한 문제가 없다.

CIE Lab*

CIE Lab* 색 공간에서

  • L 값은 밝기를 나타낸다. L = 0 이면 검은색이며, L* = 100 이면 흰색을 나타낸다.
  • a은 빨강과 초록 중 어느쪽으로 치우쳤는지를 나타낸다. a이 음수이면 초록에 치우친 색깔이며, 양수이면 빨강/보라 쪽으로 치우친 색깔이다.
  • b은 노랑과 파랑을 나타낸다. b이 음수이면 파랑이고 b*이 양수이면 노랑이다.

또한, 인간의 색 지각이 비선형이라는 연구 결과에 따라, Lab* 색 공간은 실제 빛의 파장과 비선형적 관계를 갖는다.

또한 Lab* 공간에서 서로 다른 두 색의 거리는 인간이 느끼는 색깔의 차이와 비례하도록 설계되었다.

RGB 및 CMYK 색 공간은 매체에 독립적이지 않기 때문에, 이들 색 공간을 Lab* 색 공간으로 변환하려면 먼저 sRGB나 어도비 RGB 등의 절대 색 공간으로 변환해야 한다.

공식 및 OpenCV 에서 변환 결과

\(RGB \leftrightarrow CIE L*a*b* ( CV_BGR2Lab, CV_RGB2Lab, CV_Lab2BGR, CV_Lab2RGB )\)

In case of 8-bit and 16-bit images, R, G, and B are converted to the floating-point format and scaled to fit the 0 to 1 range.

\(\begin{bmatrix} X \\ Y \\ Z \end{bmatrix} \leftarrow \begin{bmatrix} 0.412453 & 0.357580 & 0.180423 \\ 0.212671 & 0.715160 & 0.072169 \\ 0.019334 & 0.119193 & 0.950227 \end{bmatrix} \cdot \begin{bmatrix} R \\ G \\ B \end{bmatrix}\)

\(X \leftarrow X/X_n, \text{where} X_n = 0.950456\)

\(Z \leftarrow Z/Z_n, \text{where} Z_n = 1.088754\)

\(L \leftarrow \left\{ \begin{matrix} \begin{align} & 116*Y^{1/3}-16 & \textrm{for} \; Y>0.008856 \\ & 903.3*Y & \textrm{for} \; Y \le 0.008856 \end{align} \end{matrix} \right.\)

\(a \leftarrow 500 (f(X)-f(Y)) + delta\)

\(b \leftarrow 200 (f(Y)-f(Z)) + delta\)

where

\(f(t)= \left\{ \begin{matrix} \begin{align} & t^{1/3} & \textrm{for} \; t > 0.008856 \\ & 7.787t+16/116 & \textrm{for} \; t \leq 0.008856 \end{align} \end{matrix} \right.\)

and

\(delta = \left\{ \begin{matrix} \begin{align} & 128 & \textrm{for} \; 8-bit images \\ & 0 & \textrm{for} \; floating-point images \end{align} \end{matrix} \right.\)

This outputs \(0 \leq L \leq 100, -127 \leq a \leq 127, -127 \leq b \leq 127\). The values are then converted to the destination data type:

8-bit images
\(L \leftarrow L*255/100, \; a \leftarrow a + 128, \; b \leftarrow b + 128\)

즉,

  • L 값은 0 ~ 255
  • a 값은 0 ~ 128
  • b 값은 0 ~ 128

Python 코드:

result = cv2.cvtColor(image, cv2.COLOR_BGR2LAB)

See also

Favorite site