프로그래밍 언어 및 IT 정보/opencv_python

[opencv_python] 5. 이미지 컬러스페이스 (BGR,HSV,YUV)

Himer_torr 2022. 8. 3. 18:03
반응형

저번 포스팅에 이어 opencv로 기하학적 변환 두 번째 공부를 진행해보겠습니다.

이번 강의에는 이미지의 컬러 스페이스를 다뤄보겠습니다.

 

저는 Visual studio code와opencv 4.5.5 버전을 이용하였습니다.

 

Color 이미지와 다양한 색공간

opencv에서 이미지를 불러오게 되면 기본적으로 BGR 순서의 컬러 스페이스를 사용하고 있습니다.

컴퓨터로 이미지 색상을 표현하는 방법 중 제일 많이 사용되는 것이 RGB(Red, Green, Blue)입니다.

opencv 는 반대 순서를 사용하고 있죠.

 

import cv2
import matplotlib.pyplot as plt
img = cv2.imread('torr.jpg',)

plt.axis('off') 
plt.imshow(img)
plt.show()

예시 코드를 돌려보면 opencv와 matplotlib의 rgb 순서가 다른 것을 확인할 수 있습니다.

그렇다면 원래 색깔을 불러오기 위해선 컬러 스페이스 변환의 기본 함수인  cv.cvtColor함수를 사용해야 합니다.

cv2.cvtColor(src, code, dst=None, dstCn=None)

Parameters

  • src: 입력 영상
  • code: 어떤 색상으로 변환할 것인지를 결정 flag와 유사합니다.
  • dst: 결과 이미지. 선언해주지 않으면 결과 이미지를 return 합니다.
  • dstCn: 과 이미지의 채널 수. 0으로 선언하면 자동으로 설정된다. 경우에 따라 따로 설정해주지 않아도 됩니다.

code로 종류는 여러 가지가 있는데 아래를 참조하면 될 것 같습니다. 자주 쓰는 flag만 예시로 썼습니다.

  • cv2.COLOR_BGR2GRAY
  • cv2.COLOR_GRAY2BGR
  • cv2.COLOR_BGR2RGB
  • cv2.COLOR_BGR2HSV
  • cv2.COLOR_HSV2BGR
  • cv2.COLOR_BGR2YUV
  • cv2.COLOR_YUV2BGR

GrayScale

우리는 BGR컬러 영상을 GrayScale 영상으로 변환을 하여 영상처리를 대부분 진행합니다.

기본적으로 컬러 영상은 GrayScale 영상에 비해 3배 많은 메모리를 필요로 합니다. 또한 3개의 채널에 대한

연산을 수행하기 때문에 더 많은 연신 시간이 필요하게 됩니다. 그러므로 입력 영상에서 색상 정보의 활용도가 그리 높지 않은 경우에는 입력 영상을 그레이스케일 영상으로 변환하여 처리를 하게 됩니다.

import cv2
import numpy as np

img = cv2.imread('img/torr.jpg', cv2.IMREAD_COLOR)
gray = cv2.imread('img/torr.jpg', cv2.IMREAD_GRAYSCALE)
cv2.imshow('img', img)
cv2.imshow('Gray',gray)
cv2.waitKey(0)
cv2.destroyAllWindows()

 

이미지를 그레이스케일로 변환시키 것은 한 문장으로 끝납니다.

허나 '왜 opencv에서 이미지를 그레이스케일로 바꿀까' 라는 질문을 던져보는 게 좋습니다

이 차이를 아는 게 영상처리 공부에 도움이 될 것이라 생각합니다.

1. 이미지 프로세싱에서 색상은 필요로 하지 않을 경우 노이즈
2. 3채널에 대한 처리속도 및 메모리 개선 등등

HSV

HSV 색 모델은 색상(hue), 채도(saturation), 명도(value)로 색을 표현하는 방식입니다.

색상은 색의종류, 채도는 색의 순도 (높으면 맑은 선홍색, 낮으면 탁한 빨간색), 명도는 빛의 세기를 나타냅니다.

RGB 색 공간보다는 좀 더 우리들이 색을 판단하는 과정과 유사한 것이 HSV 색 공간입니다. 예를 들어 노란색을 표현하고자 하면, RGB 색 공간은 빨강과 초록 조합으로, 노랑을 표현해야 하기에 직관성이 떨어지지만 반면 HSV 색공간은 색들의 조합이 아닌 그 색깔 자체를 알려주므로 직관성이 좋습니다. 만약 색깔을 통해 이미지에서 어떤 물체를 검출하고 싶다면 , RGB공간보다 HSV공간이 더 적합할 겁니다.

색상 : H 0 ~ 360의 범위를 가지고 , 가장 파장이 긴 빨간색을 0도로 지정

채도 : S 0 ~ 100의 범위를 가지고, 색상이 가장 진한 상태를 100으로 하며, 진함의 정도를 나타냄

명도 : V 0 ~ 100의 범위를 가지고, 흰색, 빨간색을 100, 검은색이 0으로 밝은 정도를 나타냄

import cv2

src = cv2.imread("img/HSV.jpg", cv2.IMREAD_COLOR)
hsv = cv2.cvtColor(src, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(hsv)

cv2.imshow('src',src)
cv2.imshow("h", h)
cv2.imshow("s", s)
cv2.imshow("v", v)
cv2.waitKey()
cv2.destroyAllWindows()

import cv2

src = cv2.imread("img/hsv.png", cv2.IMREAD_COLOR)
hsv = cv2.cvtColor(src, cv2.COLOR_BGR2HSV)
h,s,v = cv2.split(hsv)
h = cv2.inRange(h,110,130)
blue = cv2.bitwise_and(hsv,hsv,mask=h)
blue = cv2.cvtColor(blue,cv2.COLOR_HSV2BGR)

cv2.imshow('blue',blue)
cv2.waitKey()
cv2.destroyAllWindows()

YUV

YUV 방식은 YCbCr 방식이라고도 불립니다. 

Y는 밝기 (Luma), U는 밝기와 파란색과의 색상 차(Chroma Blue,Cb), V는 밝기와 빨간색과으ㅟ 색상차 (Chroma Red, Cr)를 의미합니다.  Y(밝기)에는 많은 비트수를 할당하고 U(Cb)와 V(Cr)에는 적은 비트수를 할당하여 데이터를 압축하는 효과를 갖습니다. 아래는 Y=0.5일 때, V와 U에 따른 YUV 방식의 색상 이미지 영역입니다.

출처 : 위키백과 Y = 0.5 일때

import cv2
import numpy as np


dark = np.array([[[0,0,0]]], dtype=np.uint8)        # 3 채널 모두 0인 가장 어두운 픽셀
middle = np.array([[[127,127,127]]], dtype=np.uint8) # 3 채널 모두 127인 중간 밝기 픽셀
bright = np.array([[[255,255,255]]], dtype=np.uint8) # 3 채널 모두 255인 가장 밝은 픽셀

#---② BGR 컬러 스페이스를 YUV 컬러 스페이스로 변환
dark_yuv = cv2.cvtColor(dark, cv2.COLOR_BGR2YUV)
middle_yuv = cv2.cvtColor(middle, cv2.COLOR_BGR2YUV)
bright_yuv = cv2.cvtColor(bright, cv2.COLOR_BGR2YUV)

#---③ YUV로 변환한 픽셀 출력
print("dark:",dark_yuv)
print("middle:", middle_yuv)
print("bright", bright_yuv)
dark: [[[ 0 128 128]]]
middle: [[[127 128 128]]]
bright [[[255 128 128]]]

YUV 방식으로 변환하게 되면 이런 결과가 나오게 되는데, Y값이 밝기를 뜻하므로 점점 더 밝아지는 모습을 볼 수 있습니다. 밝기에 신경을 써야 하는 영상처리를 하게 된다면 BGR방식 보다 YUV 방식을 사용하는 것이 더 현명한 방법일 것 같습니다.

반응형