본문 바로가기
OpenCV

OpenCV 마스크 연산& ROI

by Kwonys 2024. 3. 15.
728x90
반응형

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)을 사용

 

ex)

아래와 같이 흑백 형태의 이미지를 만드는 것을 마스크 연산이라고 하고

흰색 부분(관심영역)을 ROI라 한다.

 

import sys
import cv2
import os
os.chdir('C:\coding\OpenCV\ch02') # can't open/read file: check file path/integrity 오류 해결을 위해 경로 설정

# 마스크 이미지(영상)을 이용한 이미지(영상) 합성
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)  # 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[0:h, 0: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()

하나씩 자세히 살펴보자.

 

1. 마스크 이미지를 이용한 이미지 합성

위처럼 src, mask, dst 이미지 파일을 오른쪽의 dst처럼 합성하기 위한 방법

# 마스크 이미지(영상)을 이용한 이미지(영상) 합성
src = cv2.imread('airplane.bmp', cv2.IMREAD_COLOR)              # (400, 600, 3)
mask = cv2.imread('mask_plane.bmp', cv2.IMREAD_GRAYSCALE)       # (400, 600)
dst = cv2.imread('field.bmp', cv2.IMREAD_COLOR)                 # (400, 600, 3)

if src is None or mask is None or dst is None:
    print('Image load failed!')
    sys.exit()

cv2.copyTo(src, mask, dst)  # 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()

 

cv2.copyTo() ->  "src 이미지에서 / mask 부분을 통해 / dst에 만든다."

  • 실행결과: 아래와 같이 src의 mask 부분을 복사해서 dst 이미지에 넣은 것을 볼 수 있다.

 

2. 알파 채널을 이미지(영상)로 이용

# 알파 채널을 마스크 이미지(영상)으로 이용
src = cv2.imread('cat.bmp', cv2.IMREAD_COLOR)   # (480, 640, 3) B,G,R
logo = cv2.imread('opencv-logo-white.png', cv2.IMREAD_UNCHANGED)    # (222, 180, 4) B,G,R,alpha

if src is None or logo is None:
    print('Image load failed!')
    sys.exit()

mask = logo[:, :, 3]    # mask는 alpha 채널로 만든 마스크 이미지(영상)
logo = logo[:, :, :-1]  # logo는 alpha 채널을 제외한 B, G, A 3채널로 구성된 컬러 이미지(영상)
h, w = mask.shape[:2]
crop = src[0:h, 0: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 로고를 넣어줄 것이다.

src는 고양이 이미지, logo는 투명도(alpha)를 가진 OpenCV 로고이다.

1. 마스크 이미지를 이용한 이미지 합성에서는 같은 사이즈의 이미지를 .copyTo()하여 충돌 없이 동작했지만

위의 경우는 이미지 사이즈가 달라 crop을 통해 이미지를 합성하였다.

  • 실행 결과 :

728x90
반응형