1. What is OpenCV?

OpenCV란 Computer Vision을 위한 프로그래밍 라이브러리이며, TensorFlow나 PyTorch등의 Deep Learning Framework를 지원한다.

자바, 매트립 등 다양한 언어에서 개발환경을 지원하며, 여기서는 Python언어로 OpenCV를 다루고자 한다.

OpenCV 라이브러리 설치법 : Windows 사용자라면 CMD창에서 pip3 install opencv-python를 입력해서 설치한다.

 

* 코드 실행 : Python 3.6.10 Version, OpenCV 4.2.0 Version

 

2. 이미지 출력과 저장

*Image Reference : github.com/customer-stories/mgm-resorts

1) 이미지 출력

# Image 출력
import cv2 #opencv 라이브러리 import
img = cv2.imread('image.jpg') #불러올 파일을 img 변수에 저장
cv2.imshow('Show Images', img) #출력 화면을 Show Images로 저장
cv2.waitKey() #waitKey : 키보드 바인딩을 위한 함수
cv2.destroyAllWindows()

imread() : 이미지를 출력하기 전, 이미지를 읽는 함수이다.

imshow() : 이미지를 모니터에 출력해주는 함수이다.

waitKey() : 인자로 키보드 입력 대기 시간을 지정할 수 있으며 인자가 없거나 0일 경우 무한정 기다리게 된다.

destroyAllWindows() : 입력이 끝나면 출력된 화면이 사라진다.

 

2) 원본 이미지를 흑백으로 출력

#흑백 모드로 image 출력
import cv2
img = cv2.imread('image.jpg')
gray_img = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE) #IMREAD_GRAYSCALE 플래그로 흑백으로 출력되게 함.
cv2.imshow('Gray Mode Show Images', gray_img)
cv2.waitKey()
cv2.destroyAllWindows()

 

3) 출력한 이미지 저장

#흑백모드로 출력한 이미지를 다른 이름으로 저장
cv2.imwrite('image_output.jpg', gray_img)

 

imwrite() : 출력한 이미지를 저장하는 함수이다.

 

3. Color Space 변환

Computer Vision과 관련된 분야에서는 다양한 Color 공간이 존재하며, 이를 활용하는 예로는 RGB, YUV, HSV 등이 있다.

RGB란 가장 일반적인 Color Space로 Red, Green, Blue의 가중합으로 나타난다. 각 화소값은 세 가지 숫자의 Tuple로 표시된다.

YUV에서 Y는 밝기, U/V는 Color Information으로, 흑백 정보를 표시할 때는 Y만 사용한다. RGB가 유용하긴 하나, 사람은 밝기와 색상을 다르게 인식하기 때문에 YUV라는 것도 종종 사용된다.

HSV는 Hue(색상), Saturation(채도), Value(명도)의 조합이다. YUV조차도 간혹 사용하기 불편한 점이 있어 Color를 3가지 특성으로 분리한 HSV라는 Color Space가 탄생했다.

 

1) YUV 변환

import cv2
img = cv2.imread('image.jpg')
yuv_img = cv2.cvtColor(img, cv2.COLOR_BGR2YUV) #cvtColor : color space 변환을 위한 함수
# 3개의 채널로 분리
cv2.imshow('Y channel', yuv_img[:,:,0]) # graysacle과 동일하게 출력 = 밝기
cv2.imshow('U channel', yuv_img[:,:,1]) # color information(Blue)
cv2.imshow('V channel', yuv_img[:,:,2]) # color information(Red)
cv2.waitKey()
cv2.destroyAllWindows()

기존 이미지를 밝기 및 청,적 정보로 분리해서 출력한다.

Y channel / U channel / V channel

각 정보마다 출력이 다르게 나타남을 확인할 수 있다.

yuv_img.shape

해당 이미지가 row * column * channel(533, 800, 3)의 3차원 배열임을 의미한다.

 

2) HSV 변환

hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
cv2.imshow('HSV image', hsv_img)
cv2.waitKey()
cv2.destroyAllWindows()

# 3개의 채널로 분리
cv2.imshow('H channel', hsv_img[:,:,0]) #색상
cv2.imshow('S channel', hsv_img[:,:,1]) #명도
cv2.imshow('V channel', hsv_img[:,:,2]) #채도
cv2.waitKey()
cv2.destroyAllWindows()

기존 이미지를 색상, 채도, 명도로 분리해서 출력한다.

H channel / S channel / V channel

4. Translation

Computer Vision에서 프레임 내에서 이미지를 이동하는 것을 Translation이라 한다.

1) 이미지 이동

import cv2
import numpy as np

img = cv2.imread('image.jpg') 
# 이미지 이동
row, col = img.shape[:2]
translation = np.float32([[1,0,40],[0,1,70]])
img_translation = cv2.warpAffine(img, translation, (row,col)) #warpAffine : 이동할 매트릭스(translation) 적용
cv2.imshow('Translation', img_translation)
cv2.waitKey()
cv2.destroyAllWindows()

위 코드에서 이미지의 변환은 x나 y 좌표를 더하거나 빼서 이동하게 된다.

이동은 다음과 같은 변환 매트릭스가 적용된다.


변환행렬 T에서 trans-x, trans-y가 이동한 값으로, 이미지가 우측으로 x만큼, 아래쪽으로 y만큼 이동한 것을 의미한다.

warpAffine에서 마지막 인수는 행과 열의 수를 의미하며 출력하면 다음과 같이 잘린 모양이 나타난다.

이를 해결하기 위해 다음과 같이 코드를 작성한다.

 

2) 이미지를 원래대로 복원

# 원래대로 복원
img = cv2.imread('image.jpg') 
img_translation = cv2.warpAffine(img, translation, (col+40,row+70))
cv2.imshow('Translation2', img_translation)
cv2.waitKey()
cv2.destroyAllWindows()

4-1)에서 translation으로 40, 70만큼 이동한 것을 col과 row를 바꿔서 그대로 더해주면 이미지를 잘리지 않게 출력할 수 있다.

3) 이미지를 가운데에 위치하도록 조절

# 이미지가 가운데에 위치하도록 조절
img = cv2.imread('image.jpg') 
translation = np.float32([[1,0,40],[0,1,70]])
img_translation = cv2.warpAffine(img, translation, (col+40,row+70))
translation = np.float32([[1,0,-20],[0,1,-45]])
img_translation = cv2.warpAffine(img_translation, translation, (col+40+20,row+70+45))
cv2.imshow('Translation_center', img_translation)
cv2.waitKey()
cv2.destroyAllWindows()

4-2)에서 이미지가 잘리지 않게 출력되었지만, 한 쪽으로 쏠림 현상이 발생한다.

이를 해결하기 위해서, 기존에 우측 아래로 이동한 것을 다시 좌측 위로 이동시켜 가운데에 위치하도록 조정한다.

5. Rotation

이동에 이어 특정 각도만큼 회전하는 것을 살펴보고자 한다.

1) 이미지 회전

img = cv2.imread('image.jpg') 
row, col = img.shape[:2]
rotation = cv2.getRotationMatrix2D((col/2, row/2), 20, 1)
img_rotation = cv2.warpAffine(img, rotation, (col, row))
cv2.imshow('Rotation', img_rotation)
cv2.waitKey()
cv2.destroyAllWindows()

회전은 다음과 같은 변환 매트릭스를 통해 이루어진다.

yuv에서 살펴본 것처럼 shape는 row, column, channel로 구성되어 있고 img.shape[:2]는 row, column만 가져온다는 것을 의미한다.

getRotationMatrix2D() : 변환행렬을 만들고 회전을 하게 한다.

변환에서와 마찬가지로 warpAffine 함수가 사용되며, 경계를 넘어가면 잘린 모양이 나타난다.

이를 해결하기 위해 다음과 같이 코드를 작성한다.

 

2) 이미지를 잘리지 않게 출력

translation = np.float32([[1,0,(col/2)],[0,1,(row/2)]])
rotation = cv2.getRotationMatrix2D((col/2, row/2), 20, 1)
img_translation = cv2.warpAffine(img, translation, (col*2, row*2))
img_rotation = cv2.warpAffine(img_translation, rotation, (col*2, row*2))
cv2.imshow('Rotation2', img_rotation)
cv2.waitKey()
cv2.destroyAllWindows()

 

6. Scaling

스케일링이란 Computer Vision에서 가장 흔하게 사용되는 처리 방법 중 하나로, 이미지의 크기를 조절할 수 있다.

스케일링 방법으로는 선형(Linear) 보간법, 삼차(Cubic) 보간법, 특정 화소로 지정하는 조정이 대표적이다.

OpenCV에서 스케일링하는 함수로 resize를 사용한다. 

1) Linear Interpolation

img_scale = cv2.resize(img, None, fx=1.3, fy=1.3, interpolation = cv2.INTER_LINEAR)
cv2.imshow('Linear Interpolation', img_scale)
cv2.waitKey()
cv2.destroyAllWindows()

 

2) Cubic Interpolation

img_scale = cv2.resize(img, None, fx=1.3, fy=1.3, interpolation = cv2.INTER_CUBIC)
cv2.imshow('CUBIC Interpolation', img_scale)
cv2.waitKey()
cv2.destroyAllWindows()

 

3) Resize

img_scale = cv2.resize(img, (300, 200), interpolation = cv2.INTER_AREA)
cv2.imshow('Scaling Size', img_scale)
cv2.waitKey()
cv2.destroyAllWindows()

 

3가지 모두 출력형태는 맨 위에 기본 이미지와 동일하지만 경우에 따라 화질을 유지하기 위해 적절하게 조절할 필요가 있다.

영상 확대를 위해서는 Cubic interpolation이 적합하며, 축소를 위해서는 영역을 직접 지정하는 것이 적합하다.

Linear, Cubic 방식 모두 1.3배 확대하는 것은 동일하지만, Cubic 방식은 Linear 방식보다 속도가 늦지만 질적인 측면에서는 우수한 점에서 차이를 보인다.

728x90
반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 라이프코리아트위터 공유하기
  • shared
  • 카카오스토리 공유하기