본문 바로가기
데이터 과학 관련 스터디/OpenCV

[OpenCV] RGBA 이미지 & 이미지 컬러 스페이스 변환

by inhovation97 2022. 3. 22.
본 글은 파이썬으로 만드는 OpenCV프로젝트 서적의 내용을 포스팅하는 내용입니다. 
4.2장 컬러 스페이스

해당 실습은 cv2 라이브러리를 이용하여 진행합니다.

1. RGBA 이미지
2. 이미지 컬러 스페이스 변환
3. 다양한 이미지 데이터 포맷

 

1. RGBA 이미지

 

RGBA 이미지

보통 이미지는 R,G,B 3채널을 갖는 데이터이지만, 추가로 alpha 채널을 갖는 이미지 데이터도 존재합니다. 

가끔씩 보면, 위 이미지 처럼 배경이 투명한 이미지를 볼 수 있는데, 이게 알파 채널을 활용한 이미지인 것을 저도 이번에 알았네요. 

 

실습

import cv2
import numpy as np

img = cv2.imread('../CV2/img/opencv_logo.png')                   # 기본 값 옵션
bgr = cv2.imread('../CV2/img/opencv_logo.png', cv2.IMREAD_COLOR) # IMREAD_COLOR 옵션

# IMREAD_UNCHANGED 옵션
bgra = cv2.imread('../CV2/img/opencv_logo.png', cv2.IMREAD_UNCHANGED)

# 각 옵션에 따른 이미지 shape
print('default:', img.shape, 'color:', bgr.shape, 'unchanged:', bgra.shape)

cv2.imshow('bgr',bgr)
cv2.imshow('bgra',bgra)
cv2.imshow('alpha',bgra[:,:,3]) # 알파 채널만 표시
cv2.waitKey(0)
cv2.destroyAllWindows()

결과창

bgra 이미지를 alpha 채널까지 읽는 방법은 cv.IMREAD_UNCHANGED 옵션을 추가해줍니다. 

unchanged로 읽은 이미지는 채널이 4개인 것을 확인할 수 있습니다.

알파채널만 따로 띄어보니 로고와 글씨를 제외하고는 전부 검은색인데, 이러한 특성 때문에 마스크 채널이라고도 불립니다.

 

 

 

 

2. 이미지 컬러 스페이스 변환

 

import cv2
import numpy as np

img = cv2.imread('../CV2/img/img1.png') 
img2 = img.astype(np.uint16) # dtype 변경

b,g,r = cv2.split(img2) # 채널별로 분리하여 3채널을 각각 튜플로 반환
gray1 = ((b+g+r)/3).astype(np.uint8) # 평균 값 연산 후 dtype 변경

gray2 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # BGR을 그레이 스케일로 변경
cv2.imshow('original',img)
cv2.imshow('gray1',gray1)
cv2.imshow('gray2',gray2)

cv2.waitKey(0)
cv2.destroyAllWindows()

결과창

컬러 이미지를 그레이 스케일로 변환하는 것은 이밎 연산의 양을 줄여서 속도를 높이는 데에 꼭 필요합니다.

애초에 그레이 스케일로 읽을 때에는 cv2.imread(img, cv2.IMREAD_GRAYSCALE)을 이용하면 되지만,

여기서는 맨 처음 컬러로 읽은 이미지를 cv2.cvtColor 함수를 이용하여 그레이 스케일로 바꾸는 실습과 함수를 이용하지 않고 기본적인 원리를 통한 채널 평균 연산으로 변환하는 2가지 방법을 실습합니다.

 

평균으로 계산한 코드를 살펴보면, 3채널을 모두 더하면 255보다 큰 값이 나올 수 있으므로 uint16으로 바꾸어 채널축으로 평균한 뒤 uint8로 변경하여 이미지를 그레이 스케일로 변환합니다.

 

사실 직접 평균낸 이미지랑 cvtColor 함수를 이용한 이미지랑 픽셀 값이 위처럼 완전히 동일하지는 않습니다. 더욱 정확한 명암 같은 것을 위해서는 정교한 연산이 필요하다고 하네요.

대략적인 원리만 짚고 갑니다!

 

 

 

 

 

3. 다양한 이미지 데이터 포맷

 

cv2.cvtColor 함수에 적용할 수 있는 옵션 상수들의 리스트입니다. 

위 실습에서는 cv2.COLOR_BGR2GRAY 플래그를 옵션으로 넣어 그레이 스케일로 바꿨는데, 그외에 300개가 넘는 상수들이 존재합니다. 

이미지 데이터가 RGB 뿐만 아니라 RGBA처럼 각 용도나 목적에 맞게 정말 다양한 포맷으로 저장된 형태가 많더라구요. 그 중 책에서는 HSV랑 YUV를 대표로 다룹니다. 실용성이 너무 떨어지고 접할 일도 없을 것 같아서 HSV만 한 번 다뤄 보겠습니다.

 

HSV, HSI, HSL

HSV 포맷은 RGB와 마찬가지로 3채널로 컬러 이미지를 표시합니다.

H(Hue, 색조), S(Saturation, 채도), V(Value, 명도)입니다. 비슷한 포맷으로 HSI, HSL이 있는데 약간 다르다고 합니다.

위 그림이 HSV를 이해하는 데에 가장 좋은 이미지라고 하는데, 

OpenCV에서는 dtype 최대 값이 255를 넘기지 못하므로 360도를 반으로 줄여 0~180으로 색을 표현한다고 합니다. 

따라서 H 채널은 빨강 : 165~180, 0~15, 초록 : 45~75, 파랑 : 90~120 정도로 값을 갖게 된다고 합니다.

 

S 채널의 값은 채도, 포화도, 순도로 해석 가능한데, 0~255로 255에 가까울 수록 순수한 색상이 표현된다고 합니다.

 

V 채널은 명도로서 0~255로 255가 가장 밝고, 0이 가장 어두운 값으로 표현된다고 합니다.

BGR 포맷과 HSV 포맷 간 변환은 cv2.cvtColor() 함수에 cv2.COLOR_BGR2HSV와 cv2.COLOR_HSV2BGR 플래그 상수를 이용합니다. 

 

import cv2
import numpy as np

# BGR 컬러 스페이스로 원색 픽셀 생성
red_bgr = np.array([[[0,0,255]]], dtype=np.uint8)
green_bgr = np.array([[[0,255,0]]], dtype=np.uint8)
blue_bgr = np.array([[[255,0,0]]], dtype=np.uint8)
yellow_bgr = np.array([[[0,255,255]]], dtype=np.uint8)

# BGR 컬러 스페이스를 HSV로 변환
red_hsv = cv2.cvtColor(red_bgr, cv2.COLOR_BGR2HSV);
green_hsv = cv2.cvtColor(green_bgr, cv2.COLOR_BGR2HSV);
blue_hsv = cv2.cvtColor(blue_bgr, cv2.COLOR_BGR2HSV);
yellow_hsv = cv2.cvtColor(yellow_bgr, cv2.COLOR_BGR2HSV);

# HSV로 변환한 픽셀 출력
print('HSV채널은 차례대로 H:색상(0~180), S:색의 순도, V:명암')
print('red:',red_hsv)    
print('green:',green_hsv)
print('blue:',blue_hsv)
print('yellow:',yellow_hsv)

결과

BGR 포맷에서는 3채널에서 255를 갖는 빨간색이 HSV 포맷에서는 1채널에서 0으로 표현되고 있습니다. 

위에서 제가 설명한 그대로 포맷간 변환이 일어났습니다! 

솔직히 나중에 쓸 지는 모르겠네요! 

댓글