Install OpenCV
pip install opencv-python
OpenCV는 오픈소스로 제공되는 컴퓨터 비전용 라이브러리이다. 다른 언어(C++,C,Java ...)에서도 사용가능하며, 영상 처리에 대한 고급 기능들이 구현되어 있어서 쉽게 불러 사용할 수 있다.
OpenCV tutorial
위 링크는 파이썬 튜토리얼 페이지링크이다. 여러 가지 고급 예제들이 설명되어 있다. 그 중 이미지에서 특정 색을 가진 영역만 추출하는 예제를 살펴보겠다.
앞선 포스팅에서 실습을 예제로, 이미지는 결국 [width, Height, Channel] 형태를 가지는 배열이고, 컴퓨터 비전이란 분야는 결국 이러한 배열 형태의 데이터를 처리하는 것이 중요 임무(?)라는 것을 알 수 있다.
이미지의 내용 중 관심 있는 부분이 특정 색을 가지고 있다면, 이 정보를 통해 원하는 부분을 배경과 구분하고, 관심 있는 부분만 따로 분리해 떼어낼 수 있다.
이번 포스팅에서는 이미지를 읽어 온 다음 파란색을 찾기 쉽도록 컬러스페이스를 BGR(RGB)에서 HSV로 변환한 뒤, 해당 색상과 맞는 영역만 표시하는 예제이다.
읽다 보니 이상할 것이다.
BGR???
OpenCV에서는 RGB가 아니라 BGR로 거꾸로 사용한다.
아래코드는 OpenCV 튜토리얼 사이트에 있는 예제이다.
import cv2 as cv
import numpy as np
cap = cv.VideoCapture(0)
while(1):
# Take each frame
_, frame = cap.read()
# Convert BGR to HSV
hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
# define range of blue color in HSV
lower_blue = np.array([110,50,50])
upper_blue = np.array([130,255,255])
# Threshold the HSV image to get only blue colors
mask = cv.inRange(hsv, lower_blue, upper_blue)
# Bitwise-AND mask and original image
res = cv.bitwise_and(frame,frame, mask= mask)
cv.imshow('frame',frame)
cv.imshow('mask',mask)
cv.imshow('res',res)
k = cv.waitKey(5) & 0xFF
if k == 27:
break
cv.destroyAllWindows()
하지만 우리 모두 알고있다.
video 데이터 따위... 가지고 있지 않다...
고로 우린... 사이트에 있는 이미지를 캡처할 것이다!!
그래서 변형한 코드는 밑에와 같다.
import os
import cv2 as cv # 눈치 챘겠지만 OpenCV를 import 할 때 이름을 cv2라고 해줘야한다.
import numpy as np
from matplotlib import pyplot as plt
%matplotlib inline
img_path = os.getcwd() + '/python_image_proc/data/practice.png'
img = cv.imread(img_path)
# Convert BGR to HSV
hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)
# define range of blue color in HSV
lower_blue = np.array([100,100,100])
upper_blue = np.array([130,255,255])
# Threshold the HSV image to get only blue colors
mask = cv.inRange(hsv, lower_blue, upper_blue)
# Bitwise-AND mask and original image
res = cv.bitwise_and(img, img, mask=mask)
# BGR은 OpenCV에서의 RGB표현이니 matplotlib에서 표현하려면 RGB로 다시 바꿔야한다.
# plt가 기본적으로 grid를 그려서 그래프를 표현하기 때문에 grid를 False로 설정해준다.
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
plt.grid(False)
plt.show()
plt.imshow(cv.cvtColor(mask, cv.COLOR_BGR2RGB))
plt.grid(False)
plt.show()
plt.imshow(cv.cvtColor(res, cv.COLOR_BGR2RGB))
plt.grid(False)
plt.show()
위 예제를 설명해보겠다.
cv.imread()
"Loads an image from a file."
파일로부터 이미지를 불러오는 함수이다.
링크
cvtColor()
"Converts an image from one color space to another."
컬러 스페이스 변환(convert)을 위한 함수이다.
링크
cv.inRange()
우리가 원하는 부분만 추출하기 위한 작업.
(lower_blue, upper_blue)를 적용하여, 해당하는 픽셀들에는 1, 그렇지 않은 픽셀들에는 0을 찍어놓은 배열을 반환.# 수치로 파란색 부분을 정의 lower_blue = np.array([100,100,100]) upper_blue = np.array([130,255,255]) # 위 값들을 기준으로 이미지에서 마스크를 생성한다. mask = cv.inRange(hsv, lower_blue, upper_blue)
cv.bitwise_and()
"computes bitwise conjunction of the two arrays (dst = src1 & src2) Calculates the per-element bit-wise conjunction of two arrays or an array and a scalar."# Bitwise-AND mask and original image res = cv.bitwise_and(img, img, mask=mask)
original이미지와 mask에 담긴 값들을 AND연산 해서 원하는 부분을 반환한다.
이미지 두 장을 받아서 AND 비트 연산을 한다는 건데, 위 코드를 살펴보면 이 기능이 미치도록(?) 필요한 게 아니니 두 장 다 같은 이미지(img, img)를 넣어서 결국 동일한 이미지가가 나온다. 대신 mask를 같이 넣어줘서, 해당 영역만 따온다.
링크
cvtColor()
BGR은 OpenCV에서 사용하는 RGB방식이며, matplotlib에선 RGB방식으로 돌려줘야한다.plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB)) plt.grid(False) plt.show() plt.imshow(cv.cvtColor(mask, cv.COLOR_BGR2RGB)) plt.grid(False) plt.show() plt.imshow(cv.cvtColor(res, cv.COLOR_BGR2RGB)) plt.grid(False) plt.show()