😏이미지 색상변환

이미지 색상 표현 방식

이미지 처리 작업에서 적절한 색상 공간을 선택하는 것은 성능과 결과에 큰 영향을 미칩니다.

BGR과 BGRA 색상 방식

BGR 기본 개념

일반적으로 색상 표현에는 RGB(Red, Green, Blue) 방식이 사용되지만, OpenCV는 BGR(Blue, Green, Red) 순서로 색상을 표현합니다.

  • 각 색상 채널은 0~255 범위의 값을 가집니다

  • 값이 클수록 해당 색상이 밝아집니다

  • BGR = (255, 255, 255)은 흰색, BGR = (0, 0, 0)은 검은색입니다

  • 빨간색: RGB (255, 0, 0) → BGR (0, 0, 255)

BGRA 방식 (알파 채널 포함)

BGRA는 BGR에 A(Alpha, 투명도) 채널이 추가된 형식입니다.

  • A 값은 배경의 투명도를 나타냅니다

  • A = 255: 불투명(흰색), A = 0: 투명(검은색)

  • 알파 채널은 마스크 채널(mask channel)이라고도 불립니다

BGR/BGRA 이미지 읽기

import cv2
import numpy as np

# 기본 옵션 (BGR로 읽기)
img = cv2.imread('../img/opencv_logo.png')

# 명시적으로 BGR 옵션 지정
bgr = cv2.imread('../img/opencv_logo.png', cv2.IMREAD_COLOR)

# 알파 채널 포함하여 읽기 (BGRA)
bgra = cv2.imread('../img/opencv_logo.png', cv2.IMREAD_UNCHANGED)

# 각 이미지의 차원 확인
print("default", img.shape)        # (240, 195, 3)
print("color", bgr.shape)          # (240, 195, 3) 
print("unchanged", bgra.shape)     # (240, 195, 4)

# 이미지 표시
cv2.imshow('bgr', bgr)
cv2.imshow('bgra', bgra)
cv2.imshow('alpha', bgra[:,:,3])   # 알파 채널만 표시

cv2.waitKey(0)
cv2.destroyAllWindows()

주요 특징:

  • cv2.IMREAD_COLOR와 기본 옵션은 동일한 결과를 제공합니다

  • BGRA 이미지는 4개 채널을 가지므로 shape가 (높이, 너비, 4)입니다

  • 알파 채널만 표시하면 전경과 배경을 명확히 구분할 수 있습니다


BGR을 회색조로 변환하기

컬러 이미지를 회색조로 변환하면 연산량을 줄여 처리 속도를 향상시킬 수 있습니다.

방법 1: 평균값을 이용한 직접 구현

import cv2
import numpy as np

img = cv2.imread('../img/yeosu.jpg')

# dtype을 uint16으로 변경 (오버플로우 방지)
img2 = img.astype(np.uint16)

# 채널별로 분리
b, g, r = cv2.split(img2)
# 또는 슬라이싱 사용: b, g, r = img2[:,:,0], img2[:,:,1], img2[:,:,2]

# 평균값 계산 후 uint8로 변환
gray1 = ((b + g + r) / 3).astype(np.uint8)

cv2.imshow('original', img)
cv2.imshow('gray1', gray1)
cv2.waitKey(0)
cv2.destroyAllWindows()

방법 2: OpenCV 함수 사용 (권장)

# BGR을 회색조로 변환
gray2 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

cv2.imshow('gray2', gray2)
cv2.waitKey(0)
cv2.destroyAllWindows()

주요 cvtColor 플래그

cv2.cvtColor() 함수에서 자주 사용되는 플래그들:

  • cv2.COLOR_BGR2GRAY: BGR → 회색조

  • cv2.COLOR_GRAY2BGR: 회색조 → BGR (차원 맞추기용)

  • cv2.COLOR_BGR2RGB: BGR → RGB

  • cv2.COLOR_BGR2HSV: BGR → HSV

  • cv2.COLOR_HSV2BGR: HSV → BGR

  • cv2.COLOR_BGR2YUV: BGR → YUV

  • cv2.COLOR_YUV2BGR: YUV → BGR

참고: cv2.COLOR_GRAY2BGR은 실제로 회색조를 컬러로 변환하는 것이 아니라,
2차원 배열을 3개 채널이 모두 같은 값을 갖는 3차원 배열로 변환합니다.


HSV 색상 방식

HSV는 H(Hue, 색조), S(Saturation, 채도), V(Value, 명도)로 구성된 색상 표현 방식입니다.

HSV 채널 설명

  • H (색조): 어떤 색상인지를 나타냄 (0~179)

  • S (채도): 색상의 순수성, 진함의 정도 (0~255)

  • V (명도): 색상의 밝기 (0~255)

HSV의 장점

  • 색상 식별이 용이: H 값 하나만으로도 기본 색상을 파악할 수 있습니다

  • RGB/BGR에서는 3개 채널을 모두 확인해야 하지만, HSV에서는 H 값만 보면 됩니다

BGR to HSV 변환 예제

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)

# 결과 출력
print("red:", red_hsv)        # [[[ 0 255 255]]]
print("green:", green_hsv)    # [[[60 255 255]]]
print("blue:", blue_hsv)      # [[[120 255 255]]]
print("yellow:", yellow_hsv)  # [[[30 255 255]]]

결과 분석:

  • 빨간색 BGR (0, 0, 255) → HSV (0, 255, 255)

  • H 값으로 색상을 쉽게 구분할 수 있습니다

  • 색상 기반 객체 검출이나 필터링에 매우 유용합니다


YUV 색상 방식

YUV(또는 YCbCr)는 Y(밝기), U(Cb, 파란색 색차), V(Cr, 빨간색 색차)로 구성됩니다.

YUV 채널 설명

  • Y (Luma): 밝기 정보

  • U (Cb): 밝기와 파란색의 색상 차이

  • V (Cr): 밝기와 빨간색의 색상 차이

YUV의 장점

  • 데이터 압축 효과: Y에 많은 비트를 할당하고 U, V에는 적은 비트를 할당

  • 밝기 정보 중심: 밝기가 중요한 작업에 적합

  • 비디오 압축에서 널리 사용됩니다

BGR to YUV 변환 예제

import cv2
import numpy as np

# 서로 다른 밝기의 BGR 픽셀 생성
dark = np.array([[[0,0,0]]], dtype=np.uint8)           # 어두운 픽셀
middle = np.array([[[127,127,127]]], dtype=np.uint8)   # 중간 밝기
bright = np.array([[[255,255,255]]], dtype=np.uint8)   # 밝은 픽셀

# 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)

# 결과 출력
print("dark:", dark_yuv)      # [[[  0 128 128]]]
print("middle:", middle_yuv)  # [[[127 128 128]]]
print("bright:", bright_yuv)  # [[[255 128 128]]]

결과 분석:

  • Y 값(첫 번째 값)만 0 → 127 → 255로 변화합니다

  • U, V 값은 모두 128로 동일합니다 (중간값)

  • 밝기 정보가 Y 채널에 집중되어 있음을 확인할 수 있습니다


색상 방식 선택 가이드

각 색상 방식의 적합한 사용 상황:

BGR/BGRA 방식

  • 일반적인 이미지 처리 작업

  • OpenCV의 기본 색상 방식

  • 대부분의 함수들이 BGR을 기본으로 지원

HSV 방식

  • 색상 기반 객체 검출

  • 색상 필터링 및 분할

  • 특정 색상 범위 추출

  • H 값만으로 색상 식별이 필요한 경우

YUV 방식

  • 밝기가 중요한 작업

  • 비디오 처리 및 압축

  • 조명 변화에 강인한 처리가 필요한 경우

  • 데이터 압축이 중요한 응용

회색조 (Grayscale)

  • 연산 속도가 중요한 경우

  • 단순한 형태 검출

  • 에지 검출, 코너 검출

  • 텍스처 분석


참고 자료