본문 바로가기
OpenCV/OpenCV-basic

opencv-basic

by kiimy 2021. 12. 11.
728x90
728x90

https://076923.github.io/posts/Python-opencv-1/

 

Python OpenCV 강좌 : 제 1강 - OpenCV 설치

OpenCV

076923.github.io

OpenCV

Open Source Computer Vision Library

OpenCV는 BGR이미지

이미지 불러오기 (cv.imread)

import cv2 as cv

# 이미지 불러오기
img = cv.imread('cat.bmp')
(h,w,d) = img.shape
print(img.shape)

cv2.namedWindow("image", cv2.WINDOW_AUTOSIZE)
# WINDOW_NORMAL = 영상 크기가 클때(마우스로 크기를 줄이거나 키울 수 있음)
# WINDOW_AUTOSIZE = default
cv.imshow('image', img)
cv.waitKey()
cv2.destroyAllWindows()

## cv.imshow(), cv.waitKey()는 한 묶음

* cv2.imread(fileName, flags), flags

  • cv2.IMREAD_UNCHANGED : 원본 사용(+ alpha)
  • cv2.IMREAD_GRAYSCALE : 1 채널, 그레이스케일 적용
  • cv2.IMREAD_COLOR : 3 채널, BGR 이미지 사용(default)
  • cv2.IMREAD_ANYDEPTH : 이미지에 따라 정밀도를 16/32비트 또는 8비트로 사용
  • cv2.IMREAD_ANYCOLOR : 가능한 3 채널, 색상 이미지로 사용
  • cv2.IMREAD_REDUCED_GRAYSCALE_2 : 1 채널, 1/2 크기, 그레이스케일 적용
  • cv2.IMREAD_REDUCED_GRAYSCALE_4 : 1 채널, 1/4 크기, 그레이스케일 적용
  • cv2.IMREAD_REDUCED_GRAYSCALE_8 : 1 채널, 1/8 크기, 그레이스케일 적용
  • cv2.IMREAD_REDUCED_COLOR_2 : 3 채널, 1/2 크기, BGR 이미지 사용
  • cv2.IMREAD_REDUCED_COLOR_4 : 3 채널, 1/4 크기, BGR 이미지 사용
  • cv2.IMREAD_REDUCED_COLOR_8 : 3 채널, 1/8 크기, BGR 이미지 사용

이미지 회전(rotate), 대칭(flip)

img = cv.imread('.\\ch01\\cat.bmp')

(h,w,d) = img.shape

center = (w //2, h//2)

# cv.getRotationMatrix2D(중심점, 각도, 비율= 확대 및 축소 비율)
M = cv.getRotationMatrix2D(center, -45, 1)
rotated = cv.warpAffine(img, M, (w,h))

# image flip
flip = cv.flip(img, 0)
'''
flipCode < 0은 XY 축 대칭(상하좌우 대칭)
flipCode = 0은 X 축 대칭(상하 대칭)
flipCode > 0은 Y 축 대칭(좌우 대칭)
'''
cv.imshow('rotated', rotated)
cv.imshow('flip', flip)
cv.waitKey()

## 좌표 회전 행렬은 원점을 중심으로 좌푯값을 회전시켜 매핑하며,

    좌표 축 회전 행렬은 원점을 중심으로 행렬 자체를 회전시켜 새로운 행렬의 값을 구성


이미지 확대(pyrUp, pyrDown) = Image Pyramid, 도형그리기

import cv2 as cv

# 이미지 확대( image pyramid )
img = cv.imread('code001\\cat.bmp')

# 가우시안 피라미드(Gaussian Pyramid), 라플라시안 피라미드(Laplacian pyramid)
(h, w, d) = img.shape

# cv.pyrUp('이미지', '출력크기', '테두리 외삽법')
# 테두리 외삽법(borderType)은 이미지를 확대하거나 축소할 경우, 이미지 영역 밖의 픽셀은 추정해 값을 할당
dst = cv.pyrUp(img, (w*2, h*2), borderType= cv.BORDER_DEFAULT)
dst2= cv.pyrDown(img)

# draw image + linetype = cv.LINE_AA = 라인을 더 부드럽게 그림
output = img.copy()
# cv.rectangle(img, 시작 좌표(pt1)부터 도착 좌표(pt2), color, 두께)
# pt1, pt2 X ==> *rec 좌표 설정시(x, y, w, h)*
rect1 = cv.rectangle(img, (50, 200, 150, 100), (0, 255, 0), 2)
rect2 = cv.rectangle(output, (300,20), (420,100), (0,0,255), 1)

# cv.circle(img, '중심점', '반지름', color, 두께= -1 공간채움)
circle = cv.circle(output, (h//2, w//2), 20, (0,255,0), -1)

# cv.line(img, 시작 좌표(pt1)부터 도착 좌표(pt2), color, 두께)
line = cv.line(output, (60, 20), (400, 200), (0, 255, 255), 5)

# cv.putText(img, text, '좌측 상단 모서리(org)', fontFace, fontScale, color)
# 추가로 선형 타입(lineType), 기준 좌표(bottomLeftOrigin)를 설정가능( 한글 깨짐 )
puttext = cv.putText(output, 'draw image', (10,25) ,cv.FONT_HERSHEY_COMPLEX, 2, (0, 255, 255), 3)

# cv.namedWindow('Rectangle', cv.WINDOW_NORMAL) = 마우스로 이미지 크기 조절 가능
cv.imshow('dst', dst)
cv.imshow('dst2', dst2)
cv.imshow('Rectangle, Circle, line, puttext', puttext)
cv.waitKey()
만약 알고리즘에서 요구하는 해상도가 있다면 입력 이미지의 크기를 변경해 영상 처리를 진행
또한, 검출하려는 객체가 너무 작거나 입력 이미지가 너무 큰 경우 입력 이미지 자체를 변환해서
영상 처리를 진행할 수도 있다.
* 원본 이미지에서 크기를 확대하는 것을 업 샘플링이라 하며 하위 단계의 이미지를 생성
 = BORDER_DEFAULT만 사용 가능

* 원본 이미지에서 크기를 축소하는 것을 다운 샘플링이라 하며, 상위 단계의 이미지를 생성
 = BORDER_CONSTANT를 제외한 나머지 flag 사용 가능

* borderType

cv2.BORDER_CONSTANT iiiiii | abcdefgh | iiiiiii
cv2.BORDER_REPLICATE aaaaaa | abcdefgh | hhhhhhh
cv2.BORDER_REFLECT fedcba | abcdefgh | hgfedcb
cv2.BORDER_WRAP cdefgh | abcdefgh | abcdefg
cv2.BORDER_REFLECT_101 gfedcb | abcdefgh | gfedcba
cv2.BORDER_REFLECT101 gfedcb | abcdefgh | gfedcba
cv2.BORDER_DEFAULT ( O ) gfedcb | abcdefgh | gfedcba
cv2.BORDER_TRANSPARENT uvwxyz | abcdefgh | ijklmno
cv2.BORDER_ISOLATED 관심 영역 (ROI) 밖은 고려하지 않음

이미지 크기 조절 resize

## cv2.resize(src, dstSize, fx, fy, interpolation)

## 상대크기 fx, fy 설정시 dsize =(0, 0)

## img.shape (세로 * 가로) / dsize (가로 * 세로)

 

* Interpolation

cv2.INTER_NEAREST 이웃 보간법
cv2.INTER_LINEAR ( O ) 쌍 선형 보간법
cv2.INTER_LINEAR_EXACT 비트 쌍 선형 보간법
cv2.INTER_CUBIC ( O ) 바이큐빅 보간법
cv2.INTER_AREA ( O ) 영역 보간법
cv2.INTER_LANCZOS4 Lanczos 보간법

일반적으로 (쌍 선형 보간법)이 가장 많이 사용

이미지를 확대하는 경우, (바이큐빅 보간법)이나 (쌍 선형 보간법)을 가장 많이 사용

이미지를 확대하는 경우, (이웃 보간법 = 영역 보간법)

이미지를 축소하는 경우, (영역 보간법)을 가장 많이 사용


이미지 모폴리지 변환 Morphological Transformations

Erosion(침식), Dilation(팽창)

img = cv.imread('code005\\tetris_blocks.png')

# 예외처리
if img is None:
    print('image load failed')
    sys.exit()

img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, dst = cv.threshold(img_gray, 225, 255, cv.THRESH_BINARY_INV)
mask = dst.copy()

# cv.erode = iterations이 클 수록 작아짐
# (img, kernel, iterations=1)
erode = cv.erode(mask, None, iterations=5)

# cv.dilate = iterations이 클 수록 커짐
# (img, kernel, iterations=1)
dilate = cv.dilate(mask, None, iterations=5)

Erosion


이미지 bitwise_and(+이미지 합성) 

## cv.bitwise_and(gray, threshold)

## cv.bitwise_and(img, img, mask=mask)

## cv.copyTo()

img = cv.imread('.\\tetris_blocks.png')

if img is None:
    print('Image load failed')
    sys.exit()

img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, dst = cv.threshold(img_gray, 225, 250, cv.THRESH_BINARY_INV)

mask = dst.copy()
# mask 지정을 해줘야함
output = cv.bitwise_and(img, img, mask=mask)

# cv.copyTo

src = cv.imread('ch02\\airplane.bmp')
mask = cv.imread('ch02\\mask_plane.bmp', cv.IMREAD_GRAYSCALE)
dst = cv.imread('ch02\\field.bmp')

## image 합성(원본, mask, 합성할 이미지(return))
cv.copyTo(src, mask, dst) # return dst 값으로 나옴

cv.imshow('src', src)
cv.imshow('mask', mask)
cv.imshow('dst', dst)
cv.imshow('hsv', hsv)
cv.imshow('hsv_mask', hsv_mask)
cv.waitKey()

이미지 윤곽선 검출 

= (Canny, sobel, Threshold(이진화))

import cv2 as cv

img = cv.imread('.\\tetris_blocks.png')
img = cv.resize(img, (500,500))
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # grayscale변환 필요

# Edge Dectection(가장자리 검출)
# cv.Canny 가장 흔히 사용됨
canny = cv.Canny(gray, 80, 100)

# cv.Sobel(src, '출력 이미지 정밀도(ddepth)', dx, dy, 커널 크기(ksize))
# X 방향 미분 차수와 Y 방향 미분 차수는 합이 1 이상이여야 하며, 
# 0의 값은 해당 방향으로 미분하지 않음을 의미
sobel = cv.Sobel(gray, cv.CV_8U, 0, 1, 3)

# Thresholding(이진화) 
# cv.THRESH_BINARY = 도형이 검은색, cv.THRESH_BINARY_INV = 도형이 흰색
# 설정 임곗값(retval)과 결과 이미지(dst)를 반환
# 도형 검출 시 object가 흰색성질을 띄도록 변환(INV)
ret, dst = cv.threshold(gray, 225, 255, cv.THRESH_BINARY_INV)
'''
어느 지점을 기준으로 값이 높거나 낮은 픽셀의 값을 대상으로 특정 연산을 수행할 때 사용
일반적으로 값이 높거나 낮은 픽셀을 검은색 또는 흰색의 값으로 변경
'''

## cv2.threshold(src, thresh, maxval, type) = thresh(임계값), maxval(최대값)

임곗값을 초과한 값은 최댓값으로 변경하고 임곗값 이하의 값은 0으로 바꾸는 등의 연산을 적용

픽셀의 값이 임계값(225)을 초과하는 경우에는 255의 값으로 변경되며, 100 이하의 값은 0으로 변경

* Type

cv2.THRESH_BINARY ( O ) dst = (src > thresh) ? maxval : 0
(임곗값을 초과할 경우 maxval, 아닐 경우 0)
cv2.THRESH_BINARY_INV ( O ) dst = (src > thresh) ? 0 : maxval
(임곗값을 초과할 경우 0, 아닐 경우 maxval)

 

## cv2.Canny() = Edge Dectection(가장자리 검출) 

## cv2.Canny(src, threshold1, threshold2, apertureSize, L2gradient)
가장자리는 픽셀의 밝기가 급격하게 변하는 부분으로 간주할 수 있다.
가장자리를 찾기 위해 미분(Derivative)과 기울기(Gradient) 연산을 수행하며,
이미지 상에서 픽셀의 밝기 변화율이 높은 경계선 찾는다. 

픽셀이 상위 임곗값보다 큰 기울기를 가지면 픽셀을 가장자리로 간주하고,
하위 임곗값보다 낮은 경우 가장자리로 고려하지 x

 

728x90

'OpenCV > OpenCV-basic' 카테고리의 다른 글

이미지 연산, 배열 정합(addWeighted)  (0) 2021.12.12
모폴로지 연산(Morphology)  (0) 2021.12.12
opencv-VideoCapture, VideoWriter  (0) 2021.12.11
opencv-HSV, YCrCb(특정 색 추출)  (0) 2021.12.11
opencv-findContours  (0) 2021.12.11

댓글