< 4-1. Changing Colorspaces >
- 이 튜토리얼에서는 하나의 컬러 공간의 이미지를 다른 공간으로 변환하는지를 배울 것이다. (ex. BGR -> Gray / BGR -> HSV 등)
- 추가적으로, 비디오에서 색이 있는 객체를 추출하는 기능을 만들어 볼 것이다.
- cv2.cvtColor(), cv2.inRange()에 대해서 배울 것이다.
Changing Color-space
OpenCV에는 150개 이상의 색상 공간 변환 방법이 있다. 하지만 하지만 가장 자주 널리 사용되는 BGR -> Gray 와 BGR -> HSV를 볼 것이다.
색상 변환에서, cv2.cvtColor(input_img,flag) 함수를 사용하는데 flag는 변환의 종류를 결정한다.
BGR -> Gray 변환에 대해서는 cv2.COLOR_BGR2GRAY를 사용한다. 유사하게 BGR -> HSV에서는, cv2.COLOR_BGR2HSV flag를 사용한다. 다른 종류의 flag를 보고 싶다면 아래의 코드를 실행하면 된다.
import cv2
import numpy as np
flags = [i for i in dir(cv2) if i.startswith('COLOR_')]
print(flags)
총 274개의 flags가 존재하는 것을 확인할 수 있다.
HSV에서 색조(H)의 범위는 [0,179], 채도(S) 범위는 [0,255], 명도(V)의 범위는 [0,255]이다. 다른 소프트웨어에서는 다른 스케일을 사용한다. 그러니 OpenCV에서 그드를 비교하려면, 범위를 정규화하여야 한다.
Object Tracking
이제 BGR 이미지를 HSV로 변환하는 법을 알았으니, 채색된 객체를 추출하는데 사용할 수 있다. HSV는 RGB 색공간에서 보다 색을 표현하기가 쉽다. 우리의 기능에서는, 파랗게 채색된 객체를 추출하려 한다. 아래에 방법이 있다.
- 비디오에서 각각의 프레임을 받는다
- BGR에서 HSV 색 공간으로 변환한다
- 파란색 범위의 HSV 이미지를 기준점으로 설정한다.
- 파란색 객체만을 추출하고, 우리는 우리가 원하는 그 이미지로 무엇이든 할 수 있다.
아래 코드를 보자.
cap = cv2.VideoCapture(0)
while(1):
# 각 프레임을 받아들인다.
_ , frame = cap.read()
# BGR을 HSV로 변환한다.
hsv = cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
# HSV에서 파란색 범위를 정의한다.
lower_blue = np.array([110,50,50])
upper_blue = np.array([130,255,255])
# 파란색만 가져오도록 HSV이미지의 기준점을 정한다.
mask = cv2.inRange(hsv,lower_blue,upper_blue)
# bitwise_and 마스크 및 원본 이미지
res = cv2.bitwise_and(frame,frame,mask=mask)
cv2.imshow('frame',frame)
cv2.imshow('mask',mask)
cv2.imshow('res',res)
k = cv2.waitKey(5) & 0xFF
if k == 27:
break
cv2.destroyAllWindows()
원본 이미지
Mask 이미지
최종 결과 이미지
파란색 물건을 들고 카메라에 서니 파란색 계열만 인식하는 것을 볼 수 있다.
How to find HSV values to track?
이는 Stackoverflow에서 흔히 볼 수 있는 질문이다. cv2.cvtColor()을 사용하여 간단하게 알 수 있다. 이미지를 보내는 대신, 원하는 BGR 값을 보내면 된다. 예를 들어, HSV에서 초록색 값을 알고 싶다면 아래처럼 해보면 된다.
green = np.uint8([[[0,100,100]]])
yellow = np.uint8([[[0,255,255]]])
hsv_green = cv2.cvtColor(green,cv2.COLOR_BGR2HSV)
hsv_yellow = cv2.cvtColor(yellow,cv2.COLOR_BGR2HSV)
print(hsv_green)
import matplotlib.pyplot as plt
plt.subplot(2,2,1)
plt.title('Green')
plt.imshow(hsv_green[:,:,::-1])
plt.axis('off')
plt.subplot(2,2,2)
plt.title('Yellow')
plt.imshow(hsv_yellow[:,:,::-1])
plt.axis('off')
[H-10,100,100]을 최소값으로 [H+10,255,255]를 최대값으로 각각 준다. 이 방법외에도, 이러한 값을 찾기 위해 GIMP나 온라인 컨버터와 같은 이미지 편집 도구를 사용할 수 있지만 HSV 범위를 조정하는 것을 잊으면 안된다.
- 각 BGR 색만을 추출하여 인식하는 것을 만들기
cap = cv2.VideoCapture(0)
while(1):
# 각 프레임을 받아들인다.
_ , frame = cap.read()
# BGR을 HSV로 변환한다.
hsv = cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
# HSV에서 BGR의 범위를 각각 정의한다.
lower_blue = np.array([110,50,50])
upper_blue = np.array([130,255,255])
lower_green = np.array([50,100,100])
upper_green = np.array([70,255,255])
lower_red = np.array([-10,100,100])
upper_red = np.array([10,255,255])
# BGR을 각각 가져오도록 HSV이미지의 기준점을 정한다.
mask_b = cv2.inRange(hsv,lower_blue,upper_blue)
mask_g = cv2.inRange(hsv,lower_green,upper_green)
mask_r = cv2.inRange(hsv,lower_red,upper_red)
# bitwise_and 마스크 및 원본 이미지
res_b = cv2.bitwise_and(frame,frame,mask=mask_b)
res_g = cv2.bitwise_and(frame,frame,mask=mask_g)
res_r = cv2.bitwise_and(frame,frame,mask=mask_r)
cv2.imshow('Original',frame)
cv2.imshow('Blue',res_b)
cv2.imshow('Green',res_g)
cv2.imshow('Red',res_r)
k = cv2.waitKey(5) & 0xFF
if k == 27:
break
cv2.destroyAllWindows()
파란색 사진
위와 동일하다
초록색 사진
방에 초록색이 네이버밖에 없어서 네이버로 인식을 해봤다.
빨간색 사진
핸즈온 머신러닝이 빨간색이라 인식시켜 봤다.