반응형

Color 이미지와 색공간

OpenCV에서 이미지를 불러오면 기본적으로 BGR 순서의 컬러스페이스를 사용하고 있다. 하지만, 이미지 전처리를 하기위해서는 다양한 색공간을 사용할 필요가 있다. 그중 많이 사용하는것이 GrayScale, HSV, YCrCb가 있다. 여기서는 색공간을 핸들링하는 방법과, 3가지 색공간에 대해서 보다 자세히 알아보도록 한다.

 

채널 분리, 결합

cv2.split(m, mv=None)
  • m: 다채널로 구성된 컬러 영상
cv2.merge(mv, dst=None)
  • mv: 입력 영상 리스트나 튜플

채널의 분리 및 결합을 하는 이유는 특정 성분만 따로 전처리를 하기 위함이다. 예를들어 빨간색 캔디에 해당하는 색상만 다른색상으로 변경하려면 r 성분 채널을 추출해서 전처리하면 된다.

src = cv2.imread('candies.png')
b, g, r = cv2.split(src)
# 전처리가 진행된 후,
dst = cv2.merge([b, g, r])

왼쪽부터 순서대로 (원본, B, G, R)

 

GrayScale

cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)

GraySacle의 장점으로는 용량이 감소하고, 이미지 처리속도가 향상된다. 하지만 색상정보를 잃어버리기 때문에, 색깔이 주는 정보가 중요한 Task에서는 GrayScale을 사용하면 안된다. 가끔 GrayScale을 B, G, R 색상정보의 평균을 통해서 구하는것을 볼 수 있는데, 이는 정확한 표현방법이 아니다.


$$
Y = 0.299R + 0.587G + 0.114B
$$


위와 같은 산식이 정확한 GrayScale을 표현하는 방법이 되겠다. 약 3:6:1 비율로써, Green성분이 가장 중요하고 다음으로 Red성분, 마지막으로 Blue성분이 가장 덜 중요하다는것을 알 수있다.

 

HSV

cv2.cvtColor(src, cv2.COLOR_BGR2HSV)

HSV 색공간은 원통으로 보면 이해가 쉽다.

HSV는 Hue, Saturation, Value의 앞글자를 가지온 색공간이며, 기하학적으로 원통으로 표현할 수 있다. Hue는 색상의종류(빨강, 녹색, 파랑 등)를 각도로 표현한다. Saturation은 채도로 색상의 선명도를 나타내고 반지름에 해당한다. Value는 빛의 밝기를 나타내며 높이에 해당한다.

 

OpenCV를 통해 불러온 이미지는 uint8 타입이기 때문에 360까지의 값을 가지는 Hue를 표현할 수 없다. 색상표현 범위를 절반으로 Scaling하여 0~179까지 값으로 색상을 표현하게 되어있다. 예를들어 270도는 연보라색을 표현하는데 이 값을 2로 나누어 135로 표현한다.

src = cv2.imread('candies.png')
src = cv2.cvtColor(src, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(src)

왼쪽부터 순서대로 (원본, H, S, V)

 

YCrCb

cv2.cvtColor(src, cv2.COLOR_BGR2YCrCb)

2차원 좌표계에서 Cr,Cb. Y성분은 원점에서 z축으로 솟아있다.

YCrCb는 루마(밝기)에 해당하는 Y와 크로마(색상)에 해당하는 Cr,Cb성분으로 구성되어있다. Y는 GrayScale 이미지와 완벽하게 똑같으며, 색상정보가 추가로 있는 형태이다. 디지털 표준 TV에서 사용되는 색상인데, Y를 통해서 흑백화면을 송출할 수 있으며 Cr, Cb 색상을통해 나머지 한가지 색상을 자동으로 알 수 있기 때문에, 적은 정보량으로 흑백, 컬러 송출을 지원하기 때문이다.

src = cv2.imread('candies.png')
src = cv2.cvtColor(src, cv2.COLOR_BGR2YCrCb)
Y, Cr, Cb = cv2.split(src)

왼쪽부터 순서대로 (원본, Y, Cr, Cb)

 

특정 색상 영역 추출하기

캔디 이미지에서 녹색 영역만을 추출한다고 해보자. cv2.split함수를 배웠기 때문에 각각의 채널을 분리할 수 있다는것을 알았다. 이제 아래의 함수를 통해서 범위를 나누어 정보를 가지고 올 수 있다.

cv2.inRange(src, lowerb, upperb, dst=None)
  • lowerb: 하한값. 행렬 또는 스칼라값.
  • upperb: 상한값. 행렬 또는 스칼라값.

RGB 색공간에서의 녹색을 추출하기위해서 대략적으로 RGB의 값이 (0~100, 128~255, 0~100) 라고 해보자.

src = cv2.imread('candies.png')
dst = cv2.inRange(src, (0, 128, 0), (100, 255, 100))

마찬가지로 HSV 색공간에서도 동일하게 적용해보도록 한다. HSV는 (50~80, 150~255, 0~255) 라고 해보자.

src = cv2.imread('candies.png')
src = cv2.cvtColor(src, cv2.COLOR_BGR2HSV)
dst = cv2.inRange(src, (50, 150, 0), (80, 255, 255))

원본, RGB 색공간의 녹색영역, HSV 색공간의 녹색영역

언뜻보면 RGB 색공간에서 녹색을 찾은것이 더 결과가 좋은것 처럼 보인다. 하지만 이것은 매우 특수한 경우이고, 일반적인 상황에서 색추출은 HSV, YCrCb를 사용한다. 이미지에 난반사, 그림자, 조명과 같은 밝기 정보가 들어가있는경우에는 RGB 색공간에서 색추출하기가 매우 어렵기 때문이다.

 

밝기가 내려가니 RGB 색공간의 결과가 처참하다

아래와 같이 이미지의 밝기가 조금 내려간경우에는 RGB 색공간에서 녹색성분을 찾기란 여간 어려운일이 아니다. 따라서 HSV, YCrCb 색공간을 활용하여 추출하는것이 보다 정신건강에 이롭다.

 

추가로, HSV는 주로 무지개색(빨,주,노,초,파,남,보), 쨍한색, 단색과 같은 색상을 추출할때 주로 사용되며, YCrCb는 파스텔색, 복잡한색을 추출할때 주로 사용된다고 한다.

반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기