마스크 연산과 ROI
ROI
- Region of Interest, 관심 영역
- 영상에서 특정 연산을 수행하고자 하는 임의의 부분 영역
마스크 연산
- OpenCV는 일부 함수에 대해 ROI 연산을 지원하며, 이때 마스크 영상을 인자로 함께 전달해야 함
(e.g.) cv2.copyTo(), cv2.calcHist(), cv2.bitwise_or(), cv2.matchTemplate(), etc. - 마스크 영상은 cv2.CV_8UC1 타입(그레이스케일 영상)
- 마스크 영상의 픽셀 값이 0이 아닌 위치에서만 연산이 수행됨
→ 보통 마스크 영상으로는 0 또는 255로 구성된 이진 영상(binary image)을 사용
✔ 마스크 연산을 지원하는 픽셀 값 복사 함수
dst = cv2.copyTo(src, mask, dst=None)
- src : 입력 영상
- mask : 마스크 영상. cv2.CV_8U. (numpy.uint8)
0이 아닌 픽셀에 대해서만 복사 연산을 수행. - dst : 출력 영상. 만약 src와 크기 및 타입이 같은 dst를 입력으로 지정하면 dst를 새로 생성하지 않고 연산을 수행.
그렇지않으면 dst를 새로 생성하여 연산을 수행한 후 반환함.
import sys
import cv2
# 마스크 영상을 이용한 영상 합성
src = cv2.imread('airplane.bmp', cv2.IMREAD_COLOR)
mask = cv2.imread('mask_plane.bmp', cv2.IMREAD_GRAYSCALE)
dst = cv2.imread('field.bmp', cv2.IMREAD_COLOR)
if src is None or mask is None or dst is None:
print('Image load failed!')
sys.exit()
cv2.copyTo(src, mask, dst)
# dst[mask > 0] = src[mask > 0]
cv2.imshow('src', src)
cv2.imshow('dst', dst)
cv2.imshow('mask', mask)
cv2.waitKey()
cv2.destroyAllWindows()
# 알파 채널을 마스크 영상으로 이용
src = cv2.imread('cat.bmp', cv2.IMREAD_COLOR)
logo = cv2.imread('opencv-logo-white.png', cv2.IMREAD_UNCHANGED)
if src is None or logo is None:
print('Image load failed!')
sys.exit()
mask = logo[:, :, 3] # mask는 알파 채널로 만든 마스크 영상
logo = logo[:, :, :-1] # logo는 b, g, r 3채널로 구성된 컬러 영상
h, w = mask.shape[:2]
crop = src[10:10+h, 10:10+w] # logo, mask와 같은 크기의 부분 영상 추출
cv2.copyTo(logo, mask, crop)
#crop[mask > 0] = logo[mask > 0]
cv2.imshow('src', src)
cv2.imshow('logo', logo)
cv2.imshow('mask', mask)
cv2.waitKey()
cv2.destroyAllWindows()
OpenCV 그리기 함수
❗ 그리기 함수 사용 시 주의할 점
- 그리기 알고리즘을 이용하여 영상의 픽셀 값 자체를 변경
- 원본 영상이 필요하면 복사본을 만들어서 그리기 & 출력 - 그레이스케일 영상에는 컬러로 그리기 안 됨
- cv2.cvtColor() 함수로 BGR 컬러 영상으로 변환한 후 그리기 함수 호출
✔ 직선 그리기
img = cv2.line(img, pt1, pt2, color, thickness=None, lineType=None, shift=None)
- img : 그림을 그릴 영상
- pt1, pt2 : 직선의 시작점과 끝점. (x, y) 튜플
- color : 선 색상 또는 밝기. (B, G, R) 튜플 또는 정수값
- thickness : 선 두께. 기본값은 1
- lineType : 선 타입. cv2.LINE_4, cv2.LINE_8, cv2.LINE_AA 중 선택. 기본값은 cv2.LINE_8
- shift : 그리기 좌표 값의 축소 비율. 기본값은 0
✔ 사각형 그리기
img = cv2.rectangle(img, pt1, pt2, color, thickness=None, lineType=None, shift=None)
img = cv2.rectangle(img, rec, color, thickness=None, lineType=None, shift=None)
- img : 그림을 그릴 영상
- pt1, pt2 : 사각형의 두 꼭지점 좌표. (x, y) 튜플
- rec : 사각형 위치 정보. (x, y, w, h) 튜플
- color : 선 색상 또는 밝기. (B, G, R) 튜플 또는 정수값
- thickness : 선 두께. 기본값은 1. 음수(-1)를 지정하면 내부를 채움
- lineType : 선 타입. cv2.LINE_4, cv2.LINE_8, cv2.LINE_AA 중 선택. 기본값은 cv2.LINE_8
- shift : 그리기 좌표 값의 축소 비율. 기본값은 0
✔ 원 그리기
cv2.circle(img,
center,
radius,
color,
thickness=None,
lineType=None,
shift=None)
- img : 그림을 그릴 영상
- center : 원의 중심 좌표. (x, y) 튜플
- radius : 원의 반지름
- color : 선 색상 또는 밝기. (B, G, R) 튜플 또는 정수값
- thickness : 선 두께. 기본값은 1. 음수(-1)를 지정하면 내부를 채움
- lineType : 선 타입. cv2.LINE_4, cv2.LINE_8, cv2.LINE_AA 중 선택. 기본값은 cv2.LINE_8
- shift : 그리기 좌표 값의 축소 비율. 기본값은 0
✔ 다각형 그리기
cv2.polylines(img,
pts,
isClosed,
color,
thickness=None,
lineType=None,
shift=None)
- img : 그림을 그릴 영상
- pts : 다각형 외곽 점들의 좌표 배열. numpy.ndarray의 리스트 (e.g.) [np.array([[10, 10], [50, 50], [10, 50]], dtype=np.int32)]
- isClosed : 폐곡선 여부. True 또는 False 지정
- color : 선 색상 또는 밝기. (B, G, R) 튜플 또는 정수값
- thickness : 선 두께. 기본값은 1. 음수(-1)를 지정하면 내부를 채움
- lineType : 선 타입. cv2.LINE_4, cv2.LINE_8, cv2.LINE_AA 중 선택. 기본값은 cv2.LINE_8
- shift : 그리기 좌표 값의 축소 비율. 기본값은 0
✔ 문자열 출력
cv2.putText(img,
text,
org,
fontFace,
fontScale,
color,
thickness=None,
lineType=None,
bottomLeftOrigin=None)
- img : 그림을 그릴 영상
- text : 출력할 문자열
- org : 영상에서 문자열을 출력할 위치의 좌측 하단 좌표. (x, y) 튜플
- fontFace : 폰트 종류. cv2.FONT_HERSHEY_ 로 시작하는 상수 중 선택
- fontScale : 폰트 크기 확대/축소 비율
- color : 선 색상 또는 밝기. (B, G, R) 튜플 또는 정수값
- thickness : 선 두께. 기본값은 1. 음수(-1)를 지정하면 내부를 채움
- lineType : 선 타입. cv2.LINE_4, cv2.LINE_8, cv2.LINE_AA 중 선택. 기본값은 cv2.LINE_8
- bottomLeftOrigin : True이면 영상의 좌측 하단을 원점으로 간주. 기본값은 False
➕ cv2.putText()에서 지원하는 fontFace 상수와 실제 출력 모양
한국어가 아닌 영어만 지원해준다.
✔ 다양한 그리기 함수 실행 예제
import numpy as np
import cv2
img = np.full((400, 400, 3), 255, np.uint8)
cv2.line(img, (50, 50), (200, 50), (0, 0, 255), 5)
cv2.line(img, (50, 60), (150, 160), (0, 0, 128))
cv2.rectangle(img, (50, 200, 150, 100), (0, 255, 0), 2)
cv2.rectangle(img, (70, 220), (180, 280), (0, 128, 0), -1)
cv2.circle(img, (300, 100), 30, (255, 255, 0), -1, cv2.LINE_AA)
cv2.circle(img, (300, 100), 60, (255, 0, 0), 3, cv2.LINE_AA)
pts = np.array([[250, 200], [300, 200], [350, 300], [250, 300]])
cv2.polylines(img, [pts], True, (255, 0, 255), 2)
text = 'Hello OpenCV ' + cv2.__version__
cv2.putText(img, text, (50, 350), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255),
1, cv2.LINE_AA)
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()
'OpenCV' 카테고리의 다른 글
[OpenCV] 기초 5 : 키보드 이벤트/ 마우스 이벤트 (0) | 2022.01.30 |
---|---|
[OpenCV] 기초 4 : 카메라와 동영상 처리 (0) | 2022.01.30 |
[OpenCV] 기초 2 (0) | 2022.01.30 |
[OpenCV] 기초 1 : 주요 함수 (0) | 2022.01.30 |
OpenCV 란? (1) | 2022.01.30 |