OpenCV란? 개념부터 활용까지
OpenCV, 누구냐 너
I. Inroduction of OpenCV
코로나가 끝나 마스크를 벗고 생활하니, 최근들어 아이폰의 Face ID를 많이 이용하고 있습니다.
Face ID의 핵심기술인 Face Detection Algorithm은 대표적인 Computer Vision 분야입니다.
Computer Vision의 대표적인 라이브러리인 OpenCV를 설명하려합니다.
OpenCV는 Open Source Computer Vision의 약자로 컴퓨터 비전 또는 머신러닝 오픈소스 라이브러리입니다.
쉽게 말해 컴퓨터 비전 기술을 구현하기 위한 알고리즘을 모여져있습니다.
openCV 는 line detection
, object detection
부터 자율주행, 딥러닝에도 많이 사용됩니다.
자율주행에서, 도로선을 확인하는 line detection
, 사람, 차 등을 확인하는 object detion
은 openCV의 활용이라고 할 수 있습니다.
II. Breif history of OpenCV
OpenCV는 1999년, 인텔에서 시작하여 현재의 Computer Vision, Machin Learning, AI 분야에 상당한 기여를 했습니다. 특히 Python을 공식적으로 지원한 이래 딥러닝 관련 분야에서 자주 사용되는 라이브러리입니다.
OpenCV was initially an Intel research initiative to advise CPU-intensive applications.
It was officially launched in 1999.
In the year 2006, its first major version,
OpenCV 1.0 was released.
In October 2009, the second major version, OpenCV 2 was released.
In August 2012, OpenCV was taken by a nonprofit organization OpenCV.org.
III. Basic of OpenCV
OpenCV의 다양한 기본 함수를 다룹니다.* OpenCV 이미지 읽기, 색상 변환
import cv2
cv2.imread(file_name, flag)
# 이미지를 읽어 Numpy 객체로 만드는 함수
cv2.imshow(title, image)
# 특정한 이미지를 화면에 출력하는 함수
cv2.cvtColor(image, flag)
# 이미지를 색상 형태를 변경하는 함수
import cv2
import matplotlib.pyplot as plt
img_basic = cv2.imread('./peppertons.png', cv2.IMREAD_COLOR)
#이미지를 읽어 Numpy 객체로 만드는 함수
#OpenCV는 BGR (RGB의 R과 B를 바꾼)
plt.imshow(img_basic) #matplot에서는 RGB순서
plt.show()
plt.imshow(cv2.cvtColor(img_basic, cv2.COLOR_BGR2RGB)) #BGR2RGB 필요
plt.show()
img_basic = cv2.cvtColor(img_basic, cv2.COLOR_BGR2GRAY) #convert color를 통해 BGR를 바꿈
plt.imshow(cv2.cvtColor(img_basic, cv2.COLOR_GRAY2RGB))
plt.show()
* 이미지 크기 및 픽셀 정보 확인
import cv2
import matplotlib.pyplot as plt
import time
image = cv2.imread('./peppertons.png')
# 픽셀 수 및 이미지 크기 확인
print(image.shape)
# > (1000, 980, 3)
print(image.size)
# > 2940000
# 이미지 Numpy 객체의 특정 픽셀을 가리킵니다.
px = image[100, 100]
# B, G, R 순서로 출력됩니다.
# (단, Gray Scale인 경우에는 B, G, R로 구분되지 않습니다.)
print(px)
# > [ 77 91 112]
# R 값만 출력하기
print(px[2])
# > 112
* OpenCV를 활용한 특정 범위 픽셀 변경
image = cv2.imread('./peppertons.png')
start_time = time.time()
for i in range(0, 100):
for j in range(0, 100):
image[i, j] = [255, 255, 255]
# --> 0~100 width, height 픽셀을 [255,255,255]로 변경 (흰 색으로 채워져서 나옴)
print("--- %s seconds ---" % (time.time() - start_time))
# > --- 총 걸린 시간 : 0.0030770301818847656 seconds ---
start_time = time.time()
image[0:100, 0:100] = [0, 0, 0] # --> 0~100 width, height 픽셀을 [0,0,0]로 변경 (검은 색으로 채워져서 나옴)
print("--- %s seconds ---" % (time.time() - start_time))
# > --- 총 걸린 시간 : 0.00042510032653808594 seconds ---
# 연산속도가 훨씬 빠름(약 8배)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.show()
* OpenCV를 활용한 ROI(Region of Interest: 관심 있는 영역) 추출
import cv2
import matplotlib.pyplot as plt3-7=[937-98693]
image = cv2.imread('./peppertons.png')
# Numpy Slicing: ROI 처리 가능
roi = image[200:350, 50:200]
# width : 200~350이고, height가 50~200인 정사각형 선택
# ROI 단위로 이미지 복사하기
image[0:150, 0:150] = roi
# 0~150,0~150 영역에 위의 정사각형 덮어쓰기
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.show()
* OpenCV를 활용한 픽셀별 색상 다루기
import cv2
import matplotlib.pyplot as plt
image = cv2.imread('./peppertons.png')
image[:, :, 2] = 0 #BGR에서 [2] = R에 해당하는 부분을 모두 0으로 바꿈
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.show()
* OpenCV 이미지 합치기
- cv2.add(): Saturation 연산을 수행합니다.
- Saturation: 0보다 작으면 0, 255보다 크면 255로 표현합니다.
- np.add(): Modulo 연산을 수행합니다.
- Modulo: 256은 0, 257은 1로 표현합니다.
import cv2
import matplotlib.pyplot as plt
image_1 = cv2.imread('../../images/image_1.png')
image_2 = cv2.imread('../../images/image_2.png')
result = cv2.add(image_1, image_2)
plt.imshow(cv2.cvtColor(result, cv2.COLOR_BGR2RGB))
plt.show()
result = image_1 + image_2
plt.imshow(cv2.cvtColor(result, cv2.COLOR_BGR2RGB))
plt.show()
두 이미지가 사이즈가 같지 않거나, 다른 형태의 파일 (ex: png + jpeg)이라면 아래의 에러가 발생합니다.
에러 해결을 위해서는 같은 형태, 사이즈를 맞춰야합니다.
error: (-209:Sizes of input arguments do not match) The operation is neither ‘array op array’ (where arrays have the same size and the same number of channels), nor ‘array op scalar’, nor ‘scalar op array’ in function ‘arithm_op’
* OpenCV threshold, 기준에 따른 구분
- cv2.threshold(image, thresh, max_value, type): 임계값을 기준으로 흑/백으로 분류하는 함수
- image: 처리할 Gray Scale 이미지
- thresh: 임계 값 (전체 픽셀에 적용)
- max_value: 임계 값을 넘었을 때 적용할 값
- type: 임계점을 처리하는 방식
- type
- THRESH_BINARY: 임계 값보다 크면 max_value, 작으면 0
- THRESH_BINARY_INV: 임계 값보다 작으면 max_value, 크면 0
- THRESH_TRUNC: 임계 값보다 크면 임계 값, 작으면 그대로
- THRESH_TOZERO: 임계 값보다 크면 그대로, 작으면 0
- THRESH_TOZERO_INV: 임계 값보다 크면 0, 작으면 그대로
import cv2
import matplotlib.pyplot as plt
image = cv2.imread('gray_image.jpg', cv2.IMREAD_GRAYSCALE)
images = []
ret, thres1 = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)
# 127보다 크면 255(흑), 작으면 0 (백)
ret, thres2 = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY_INV)
# 127보다 크면 0(백), 크면 25 (백)
ret, thres3 = cv2.threshold(image, 127, 255, cv2.THRESH_TRUNC)
# 127보다 크면 임계값, 127보다 작으면 그대로
ret, thres4 = cv2.threshold(image, 127, 255, cv2.THRESH_TOZERO)
# 127보다 크면 그대로, 127보다 작으면 0
ret, thres5 = cv2.threshold(image, 127, 255, cv2.THRESH_TOZERO_INV)
# 127보다 크면 0, 127보다 작으면 그대로
images.append(thres1)
images.append(thres2)
images.append(thres3)
images.append(thres4)
images.append(thres5)
for i in images:
plt.imshow(cv2.cvtColor(i, cv2.COLOR_GRAY2RGB))
plt.show()
- Adaptive Threshold를 이용하면, 전체 픽셀을 기준으로 임계 값을 적용하지 않습니다.
import cv2
image = cv2.imread('hand_writing_image.jpg', cv2.IMREAD_GRAYSCALE)
ret, thres1 = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)
thres2 = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 21, 3)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_GRAY2RGB))
plt.show()
plt.imshow(cv2.cvtColor(thres1, cv2.COLOR_GRAY2RGB)) # THRESH_BINARY
plt.show()
plt.imshow(cv2.cvtColor(thres2, cv2.COLOR_GRAY2RGB)) # ADAPTIVE_THRESH_MEAN_C
# 보다 정확한, 정밀한 구분 가능
plt.show()
* OpenCV Tracker를 통한 Object Tracking
import cv2
import numpy as np
def change_color(x):
r = cv2.getTrackbarPos("R", "Image")
g = cv2.getTrackbarPos("G", "Image")
b = cv2.getTrackbarPos("B", "Image")
image[:] = [b, g, r]
cv2.imshow('Image', image)
image = np.zeros((600, 400, 3), np.uint8)
cv2.namedWindow("Image")
cv2.createTrackbar("R", "Image", 0, 255, change_color)
cv2.createTrackbar("G", "Image", 0, 255, change_color)
cv2.createTrackbar("B", "Image", 0, 255, change_color)
cv2.imshow('Image', image)
cv2.waitKey(3)
Tracker 클래스 종류
KCF : 빠르게 작동
MOSSE : 빠르게 작동
CSRT : 연산은 느리지만 강인하게 추적
GOTURN : 딥러닝 기반, 가중치 파일을 다운받아 저장해야지 작동 가능
**(ex) cv2.TrackerXXX_create() ->
**
* OpenCV로 도형 그리기
-
cv2.line(image, start, end, color, thickness): 하나의 직선을 그리는 함수
- start: 시작 좌표 (2차원)
- end: 종료 좌표 (2차원)
- thickness: 선의 두께
import cv2 import numpy as np import matplotlib.pyplot as plt image = np.full((512, 512, 3), 255, np.uint8) #512, 512 사이즈로, RGB 3가지 색깔을 가지고, 모든 색깔을 255로 설정 image = cv2.line(image, (0, 0), (255, 255), (255, 0, 0), 3) #RGB(255,0,0) -> 빨간색, 두께 3 # 0,0에서 255,255까지 Line으로 두께가 3인 직선 plt.imshow(image) plt.show()
-
cv2.rectangle(image, start, end, color, thickness): 하나의 사각형을 그리는 함수
- start: 시작 좌표 (2차원)
- end: 종료 좌표 (2차원)
- thickness: 선의 두께 (채우기: -1)
import cv2
import numpy as np
import matplotlib.pyplot as plt
image = np.full((512, 512, 3), 255, np.uint8)
image = cv2.rectangle(image, (20, 20), (255, 255), (255, 0, 0), 3)
#시작점 : (20, 20), 종료점: (255, 255), 두께=3
plt.imshow(image)
plt.show()
-
cv2.circle(image, center, radian, color, thickness): 하나의 원을 그리는 함수
- center: 원의 중심 (2차원)
- radian: 반지름
- thickness: 선의 두께 (채우기: -1)
import cv2
import numpy as np
import matplotlib.pyplot as plt
image = np.full((512, 512, 3), 255, np.uint8)
image = cv2.circle(image, (255, 255), 30, (255, 0, 0), 3)
#중심 (255,255), 반지름 30, color(255,0,0) , 두께 3
plt.imshow(image)
plt.show()
-
cv2.polylines(image, points, is_closed, color, thickness): 하나의 다각형을 그리는 함수
- points: 꼭지점들
- is_closed: 닫힌 도형 여부
- thickness: 선의 두께 (채우기: -1)
import cv2 import numpy as np import matplotlib.pyplot as plt image = np.full((512, 512, 3), 255, np.uint8) points = np.array([[5, 5], [128, 258], [483, 444], [400, 150]]) image = cv2.polylines(image, [points], True, (0, 0, 255), 4) plt.imshow(image) plt.show()
-
cv2.putText(image, text, position, font_type, font_scale, color)
- position: 텍스트가 출력될 위치
- font_type: 글씨체
- font_scale: 글씨 크기 가중치
import cv2
import numpy as np
import matplotlib.pyplot as plt
image = np.full((512, 512, 3), 255, np.uint8)
image = cv2.putText(image, 'Hello World', (0, 200), cv2.FONT_ITALIC, 2, (255, 0, 0))
plt.imshow(image)
plt.show()
* OpenCV Contours,외곽과 테두리를 잘 구분하자
-
cv2.findContours(image, mode, method): 이미지에서 Contour들을 찾는 함수
- mode: Contour들을 찾는 방법
- RETR_EXTERNAL: 바깥쪽 Line만 찾기
- RETR_LIST: 모든 Line을 찾지만, Hierarchy 구성 X
- RETR_TREE: 모든 Line을 찾으며, 모든 Hierarchy 구성 O
- method: Contour들을 찾는 근사치 방법
- CHAIN_APPROX_NONE: 모든 Contour 포인트 저장
- CHAIN_APPROX_SIMPLE: Contour Line을 그릴 수 있는 포인트만 저장
- cv2.drawContours(image, contours, contour_index, color, thickness): Contour들을 그리는 함수
import cv2
import matplotlib.pyplot as plt
image = cv2.imread('../images/gray_image.jpg')
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(image_gray, 127, 255, 0) #127보다 큰 값은 255로, 그렇지않은값은 0으로
plt.imshow(cv2.cvtColor(thresh, cv2.COLOR_GRAY2RGB))
plt.show()
contours = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[0]
# RETR_TREE: 모든 Line을 찾으며, 모든 Hierarchy 구성 O
# CHAIN_APPROX_SIMPLE: Contour Line을 그릴 수 있는 포인트만 저장
image = cv2.drawContours(image, contours, -1, (0, 255, 0), 4)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.show()
* OpenCV Filtering, 흐릿하게 만들기
Method 1 : 직접 커널을 생성하여 필터 적용하기
import cv2
import matplotlib.pyplot as plt
import numpy as np
image = cv2.imread('../images/gray_image.jpg')
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.show()
size = 4
kernel = np.ones((size, size), np.float32) / (size ** 2)
# 4 x 4 형태로 모두 같은 값을 가지도록
# 1/16 1/16 1/16 1/16
# 1/16 1/16 1/16 1/16
# 1/16 1/16 1/16 1/16
# 1/16 1/16 1/16 1/16
print(kernel)
dst = cv2.filter2D(image, -1, kernel)
plt.imshow(cv2.cvtColor(dst, cv2.COLOR_BGR2RGB))
plt.show()
Method 2 : Basic Blurring 필터 적용하기
import cv2
import matplotlib.pyplot as plt
image = cv2.imread('../images/gray_image.jpg')
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.show()
dst = cv2.blur(image, (4, 4)) # 위와 동일한 basic blurring
plt.imshow(cv2.cvtColor(dst, cv2.COLOR_BGR2RGB))
plt.show()
위 생성한 Filter와 정확하게 일치
Method 3 : Gaussian Blurring 필터 적용하기
import cv2
image = cv2.imread('../images/gray_image.jpg')
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.show()
# kernel_size: 홀수
dst = cv2.GaussianBlur(image, (5, 5), 0)
plt.imshow(cv2.cvtColor(dst, cv2.COLOR_BGR2RGB))
plt.show()
이상으로 "OpenCV란? 개념부터 활용까지" 게시물을 마무리하겠습니다.
다음 게시물은 학습한 OpenCV를 토대로 [2017 삼성전자 해킹방어대회]를 해결해보도록 하겠습니다.