앞서 OpenCV가 어떤방면에서 사용되는지 , 특징은 어떠한지 알아보았다. 직접 OpenCV를 활용하기 위해서 기초적인 사용법에 대해서 알아보자.
OpenCV에서는 선, 사각형, 원, Text 와 같은 도형을 그리는 기능을 제공한다 아래의 사용법을 살펴보자.
cv2.line(img, start, end , color, thickness)
cv2.rectangle(img, start, end , color, thickness)
cv2.circle(img, center, radius, color, thickness)
cv2.text(img, text, org, font, fontScale, color)
OpenCV를 통해 여러가지 도형 및 텍스트를 그린 모습.
color 같은경우에는 BGR 값으로 정의할 수 있다.
컴퓨터 비전에서 이미지 파일을 다루는것은 당연한 일이기 때문에, 이미지 파일을 어떻게 다루는지 아는것은 필수적이다.
cv2.imread(filename,flags)
여기서 flags 에는 이미지를 읽을 때 적용되는 옵션을 지정하는 매개변수이다.
IMREAD_COLOR, IMREAD_GRAYSCALE, IMREAD_UNCHANGED 과 같은 옵션을 선택하여 이미지를 불러올 수 있다.
cv2.imshow(window_title,image)
window title 이름을 지정하고 image를 창으로 띄울 수 있다.
cv2.imwrite(filename, image)
filename으로 이미지를 저장 할 수 있다.
IMREAD_COLOR로 생성한 그림.
IMREAD_GRAYSCALE로 생성한 그림.
OpenCV 이미지는 픽셀로 구성되어 있고, 가로선 * 세로선 으로 읽을 수 있다. 아래의 예시코드를 통해 특정 픽셀을 찾는 방법을 알아보자.
import cv2
import numpy as np
#img = cv2.imread('src/ex_codes/opencv_ex/spot.png', cv2.IMREAD_GRAYSCALE)
img = cv2.imread('src/ex_codes/opencv_ex/grim.png', cv2.IMREAD_COLOR)
#height
h = img.shape[0]
w = img.shape[1]
print("The image dimension is %d x %d" % (w, h))
for i in range(0, h - 1):
for j in range(0, w - 1):
if np.array_equal(img[i, j],[255,255,255]):
print(img[i, j])
print(i, j)
cv2.imshow('spot', img)
cv2.waitKey(1000)
OpenCV에서 이미지를 불러오는 방식이 height, width 좌표의 픽셀의 BGR 값들로 구성된 array로 읽어들인다. img.shape 를 통해 해당 값을 알 수 있다.
그렇기 때문에 특정 색깔을 찾고자 할때 해당 픽셀의 좌표와 원하는 BRG 값을 대조하면 원하는 색깔의 위치를 찾을 수 있다.
위 코드에서는 검정색을 찾을 수 있다.
그리고 IMREAD_GRAYSCALE
로 불러온 파일은 무채색이기 때문에 색상의 밝기로만 픽셀을 구분 할 수 있다. 그래서 픽셀에 저장되는 값이 0~255 사이의 값이다.
이미지를 처리할때 관심범위를 지정하여 작업을 할 수있다.
cv2.imshow(window_title,image[a:b, c:d])
잘라내는 범위는 당연히 원본이미지 값 보다 크면 안된다.
OpenCV에서는 BGR 색상 모델을 사용하기도 하지만, 때때로 HSV 라는 색상 표현 방식을 사용하기도 한다.
H(Hue, 색상) , S(Saturation, 채도), V(Value, 명도) 로 표현하며 , 객체를 분할해 내기 용이한 장점이 있다.
아래의 코드를 통해 BGR을 HSV로 변환 할 수 있다.
cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
Hue 범위 : 0 ~ 179 (색상스펙트럼 각도)
Saturation 범위 : 0 ~ 255
Value 범위 : 0~255
도로의 색상은 주로 어두운색(검정색)이고, 차선은 밝은 색이기 때문에, 명도를 활용하면 구분해내기 쉽다.
아래의 코드와 입력하면 어떤 이미지에서 흰색으로 인식할 범위를 설정하여 inRange 함수를 통해 흰색 픽셀의 범위를 알아 낼 수 있다.
예시코드
import cv2
import numpy as np
img = cv2.imread('cars.png')
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower_white = np.array([0,0,150])
upper_white = np.array([179,255,255])
mask = cv2.inRange(hsv, lower_white, upper_white)
cv2.imshow('line', mask)
cv2.waitKey(10000)
위와 같이 image를 HSV로 변한 한 뒤 범위내의 색상을 흰색 영역으로 추출하여 이미지를 변환 한 것을 확인 할 수 있다.
value range 를 바꿔가면서 실행화면을 확인해보았을때 150~255 범위에서 차선을 잘 인식하는 것을 확인 할 수 있었다.
외부환경 및 상황을 고려하여 명도 값을 조절하여 차선을 인식하게 끔 바꾸는 것이 좋을 것 같다.
번외로 차선 외에 이미지의 특정 색상을 검출해내는 것도 시도해보았다.
응용하면 위와같이 파란부분의 영역만 골라서 확인 할 수도 있다.
cv2.bitwise_and(img, img, mask=blue_mask)
위 코드를 통해 원본이미지의 파란부분만 강조 표시 할수도 있다.
다른 이미지 예시.
openCV에서 이미지 뿐만아니라 동영상 및 실시간 화면을 처리해야하는 경우가 많다.
아래에서 동영상 파일을 핸들링 하는방법에 대해서 알아보자.
video.py
import cv2
vid = cv2.VideoCapture('src/ex_codes/opencv_ex/small.avi')
while True:
ret, frame = vid.read()
if not ret:
#once
break
#if want roof
#vid.set(cv2.CAP_PROP_POS_FRAMES,0)
#continue
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('video', frame)
if cv2.waitKey(1) > 0:
break
vid.release()
# cv2.waitKey(20000)
cv2.destroyAllWindows()