이미지 데이터 처리의 기본 - OpenCV

괴도소녀·2021년 7월 14일
0

데이터

목록 보기
13/14
post-thumbnail

Install OpenCV

pip install opencv-python

OpenCV는 오픈소스로 제공되는 컴퓨터 비전용 라이브러리이다. 다른 언어(C++,C,Java ...)에서도 사용가능하며, 영상 처리에 대한 고급 기능들이 구현되어 있어서 쉽게 불러 사용할 수 있다.
OpenCV tutorial
위 링크는 파이썬 튜토리얼 페이지링크이다. 여러 가지 고급 예제들이 설명되어 있다. 그 중 이미지에서 특정 색을 가진 영역만 추출하는 예제를 살펴보겠다.

앞선 포스팅에서 실습을 예제로, 이미지는 결국 [width, Height, Channel] 형태를 가지는 배열이고, 컴퓨터 비전이란 분야는 결국 이러한 배열 형태의 데이터를 처리하는 것이 중요 임무(?)라는 것을 알 수 있다.

이미지의 내용 중 관심 있는 부분이 특정 색을 가지고 있다면, 이 정보를 통해 원하는 부분을 배경과 구분하고, 관심 있는 부분만 따로 분리해 떼어낼 수 있다.
이번 포스팅에서는 이미지를 읽어 온 다음 파란색을 찾기 쉽도록 컬러스페이스를 BGR(RGB)에서 HSV로 변환한 뒤, 해당 색상과 맞는 영역만 표시하는 예제이다.
읽다 보니 이상할 것이다.
BGR???
OpenCV에서는 RGB가 아니라 BGR로 거꾸로 사용한다.

출처: https://docs.opencv.org/master/df/d9d/tutorial_py_colorspaces.html

아래코드는 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()

참고

0개의 댓글