컬러 영상 처리

Seungpil Choi·2022년 8월 16일
1

컬러 영상 처리

컬러란?

컬러를 사용하면 영상으로 부터 간단하게 특정 객체를 식별할 수 있다. 또한 인간은 본질적으로 명도보다는 컬러에 민감하다. 인간은 수천 개의 컬러를 식별할 수 있지만 명도 단계는 약 20개 정도만을 구분할 수 있다고 한다.

컬러 모델

영상 처리에는 다양한 컬러 모델이 사용된다. 컬러 모델마다 장점과 단점이 있으므로 영상 처리 알고리즘의 성능을 극대화하려면 적절한 컬러 모델을 사용하여야 한다.

RGB 컬러 모델

RGB 컬러 모델은 3원색을 서로 합하는 가산 컬러 모델(additive color model)이다. 최종 색상을 만들기 위하여 3개의 광선이 서로 합쳐져야 하기 떄문이다. 이것은 잉크나 페인트에 적용되는 감산 모델과는 완전히 반대이다. RGB 컬러 모델로 모든 색상을 표현할 수 있지는 않다. RGB는 장치 종속적인 컬러 모델이다. 하드웨어에 따라서 RGB값을 다르게 감지하거나 재현하기 때문이다. LCD 디스플레이가 표시할 수 있는 색역은 빨간색, 녹색, 파란색 소자에 사용되는 색상에 따라 다르다.

CMY 컬러 모델

CMY는 물감의 3원색이다. 컬러 프린터와 같이 물감을 사용하는 장치들은 CMY 컬러를 필요로 한다.
[C, M, Y] = [1, 1, 1] - [R, G, B]
여기서 모든 컬러값이 [0,1] 범위로 정규화되었다고 가정한다.

HSV 컬러 모델

RGB 컬러 모델은 직관적으로 컬러를 묘사하는 데는 적합하지 않다. 인간은 "진한 청색", "어두운 노란색"과 같은 단어를 사용한다. 그렇다면 인간이 가장 많이 사용하는 컬러 묘사 방법은 무엇일까? 바로 HSV 컬러 모델이다. 하나의 컬러를 색조, 채도, 명도로 표현하는 방법이다. Hue는 색조(색의 종류)를 나타낸다. Saturation(채도)는 그 색이 얼마나 순수한 색인지를 표현한다. Value(명도)는 밝기를 나타낸다.

영상처리에서 H, S, V는 0에서 255사이의 값으로 표현된다. 흔히 H값은 0도에서 180도까지의 각도로 표현된다. S값은 0에서 255 사이의 값으로 색의 선명도를 나타낸다. S값이 255이면 아무것도 섞지 않아 맑고 깨끗한 원색이다. S값이 0에 가까우면 백색이 많이 섞인 색이다. V값은 밝기의 정도를 나타낸다. 우리가 컬러 영상을 그레이스케일 영상으로 변환하면 바로 V만을 사용하는 것이다. HSV는 인간이 직관적으로 이해할 수 있는 컬러 모델로 영상 처리 프로그램을 개발하는 데 많이 사용된다.

YIQ 컬러 모델

컬러 텔레비전 방송에 쓰이는 컬러모델은 YIQ 컬러 시스템이다. OpenCV에서는 Y, U, V라고 한다. Y는 명시도(luminance)를 뜻한다. Y는 사람 눈의 감광성에 비례하여 빨간색, 녹색, 파란색 신호를 결합하여 만들어진다. I와 Q성분은 색차라고 부르는 성분으로 방송에 쓰이는 장비와의 호환성을 위해 선택되었다. I는 근본적으로 빨간색에서 시안색을 뺀 것이고 Q는 마젠타색에서 녹색을 뺀것이다. YIQ모델은 주로 방송이나 영상 압축 알고리즘인 MPEG에서도 사용된다. RGB신호를 YIQ신호로 바꾸는 것은 어렵지 않으며 정보가 유실되지 않는다. RGB와 YIQ는 모두 하드웨어 위주의 체계이다.

색상 공간 변환

img = cv2.imread("../Downloads/lena.png")

hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
array = cv2.split(hsv)

cv2.imshow("src", img)
cv2.imshow("hue",array[0])
cv2.imshow("saturation",array[1])
cv2.imshow("value",array[2])

cv2.waitKey(0)
cv2.destroyAllWindows()

컬러맵 사용하기

영상의 컬러들을 다시 매핑하여 영상의 분위기를 변경할 수 있다. 즉 영상의 배경이 사막 느낌나게 한다거나 겨울 분위기 등을 만들 수 있는 것이다. OpenCV에서는 applyColorMap()을 사용하면 그레이스케일 영상에도 컬러를 입힐 수 있다.

img = cv2.imread("../Downloads/lena.png")

img_color = cv2.applyColorMap(img, cv2.COLORMAP_HOT)
cv2.imshow("src", img)
cv2.imshow("img_color", img_color)

cv2.waitKey(0)
cv2.destroyAllWindows()

컬러를 이용한 객체 분할

객체 감지 및 분할은 컴퓨터 비전의 가장 중요하고 도전적인 기본 작업이다. 그러나 객체를 배경에서 분리하는 작업은 다양성과 복잡성으로 인해 여전히 열려있는 문제이다. 영상에서 객체를 감지하고 구분하는 가장 쉬운 방법은 색상 기반 방법이다. 색상 기반 방법을 사용하여 객체를 성공적으로 구분하기 위해서는 객체와 배경이 중요한 색상 차이를 가져야 한다.

  • inRange() 매개변수
    • src : 입력 영상
    • lowerb : 하부 경계값
    • upperb : 상부 경계값
image = cv2.imread("../Downloads/skyandmountain.jpg")
image = cv2.resize(image, (255,255))

imageHSV = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

imageThresholded = cv2.inRange(imageHSV, (100,0,0), (120,255,255))

cv2.imshow("Thresholded Image", imageThresholded)
cv2.imshow("Original", image)

cv2.waitKey(0)
cv2.destroyAllWindows()

일반적으로 RGB색상 공간이 색 기반 분할에 더 적합하다고 생각할 수 있으나 실제로는 HSV 색상을 기반으로 영상을 분할하는데 더 적합하다.
OpenCV에서 HUE, SATURATION, VALUE 값의 범위는 각각 0~179, 0~255, 0~255이다. HUE는 원래 360도이지만 OpenCV에서는 0에서 255까지만 표시할 수 있으므로 360을 2로 나누어서 0에서 180사이의 값으로 색조를 나타낸다. 위에서 하늘에 해당되는 색조는 대략 100에서 120사이라고 할 수 있다. SATURATION 및 VALUE는 환경의 조명 상태뿐만 아니라 대상물의 표면에 의존한다.

색상을 이용하여 객체를 분할하는 경우에 주의해야 하는 사항이 있다. 순수 색 정보는 밝기 값이 낮은 경우에는 불안정한 정보를 전달할 수 있다. 예를 들어서 B=1, G=0, R=0과 B=0, G=1, R=0 인 화소는 상식적으로 검은색으로 보여야 한다. 하지만 밝기 정보를 무시하고 순수한 색 정보만 가지고 판단하면 아주 다른 색상이 되는 것이다. 따라서 밝기가 어느 정도 이상일때만 순수 색상 정보를 비교하도록 하는 것도 좋은 방법이다.

크로마키 기법 구현하기

크로마키 합성(Chroma Key Composing)은 색조를 이용하여 2개의 영상 또는 비디오 스트림을 합성하는 기술이다.

chroma_img = cv2.imread("../Downloads/chromakey.jpg")
background_img = cv2.imread("../Downloads/beautiful-tropical-empty-beach-sea-ocean-with-white-cloud-blue-sky-background.jpg")

chroma_img = cv2.resize(chroma_img, (500,300))
background_img = cv2.resize(background_img, (500,300))


converted = cv2.cvtColor(chroma_img, cv2.COLOR_BGR2HSV)
green_screen = cv2.inRange(converted, (60-10, 100, 100), (60+10, 255, 255))

inverted = cv2.bitwise_not(green_screen)
dst = cv2.bitwise_and(chroma_img, chroma_img, mask=inverted)
dst1 = cv2.bitwise_or(dst, background_img, mask=green_screen)
dst1 = cv2.bitwise_or(dst, dst1)

cv2.imshow("chroma_img", chroma_img)
cv2.imshow("green", green_screen)
cv2.imshow("dst", dst)
cv2.imshow("dst1", dst1)

cv2.waitKey(0)
cv2.destroyAllWindows()

컬러를 이용한 객체 추적

cap = cv2.VideoCapture("../Downloads/hand_move.mp4")

if cap.isOpened() == False :
    print('ERROR FILE NOT FOUND! OR WRONG CODEC USED!')

while cap.isOpened():
    ret, frame = cap.read()
    
    if ret == True:
        imgHSV = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
        imgThreshold = cv2.inRange(imgHSV, (5, 10, 10), (38, 255, 100))
        cv2.imshow("hand_move",frame)
        cv2.imshow("Treshold_hand_move", imgThreshold)
        
        if cv2.waitKey(10) & 0xFF == ord('q'):
            break
    else:
        break
            
cap.release()
cv2.destroyAllWindows()
    

0개의 댓글