Python/파이썬 OpenCV 공부

[파이썬 OpenCV] 마스크 연산과 ROI - cv2.copyTo 함수 이용 방법

AI 꿈나무 2020. 9. 25. 17:06
반응형

황선규 박사님의 OpenCV 강의를 공부하면서 정리하였습니다.

 


마스크 연산과 ROI

 마스크 연산과 ROI에 대해 알아보도록 하겠습니다.

 

ROI
 Reigion of Interest, 관심 영역
 영상에서 특정 연산을 수행하고자 하는 임의의 부분 영역을 의미합니다.

마스크 연산
 OpenCV는 일부 함수에 대해 ROI 연산을 지원하며, 이때 마스크 영상을 인자로 함께 전달해야 합니다.
 OpenCV 함수 (cv2.copyTo(), cv2.calcHist(), cv2.bitwise_or(), cv2.matchTemplater(), etc....)
 마스크 영상은 cv2.CV_8UC1 타입(그레이스케일 영상)
 마스크 영상의 픽셀 값이 0이 아닌 위치에서만 연산이 수행됩니다. -> 0과 1의 차이는 눈으로 확인하기 힘드므로 보통 마스크 영상으로는 0 또는 255로 구성된 이진 영상(binary image)을 사용한다고 합니다.

1. 마스크 연산을 지원하는 픽셀 값 복사 함수

 cv2.copyTo()함수를 이용하여 마스크 연산을 해보도록 하겠습니다.

 

cv2.copyTo(src, mask, dst=None) -> dst

 src(source) : 입력 영상

 mask : 마스크 영상, cv2.CV_8U. (numpy.unit8)

 dst(destination) : 출력 영상, 만약 src와 크기 및 타입이 같은 dst를 입력으로 지정하면 dst를 새로 생성하지 않고 연산을 수행합니다. 그렇지 않으면 dst를 새로 생성하여 연산을 수행한 후 반환합니다.

 

 

(1) 마스크 연산을 이용한 영상 합성

# 마스크 영상을 이용한 영상 합성
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()


# dst를 꼭 입력값으로 넣어줘야 합니다.
# src, mask, dst크기가 같아야 합니다.
# src, dst 크기가 다르다면 dst 영상을 추출하여 입력값으로 넣어주면 됩니다. (추출한 부분에 scr 형성)
cv2.copyTo(src, mask, dst)

cv2.imshow('src', src)
cv2.imshow('dst', dst)
cv2.imshow('mask', mask)
cv2.waitKey()
cv2.destroyAllWindows()

 

(2) 넘파이에서 제공하는 bool 인덱싱 이용

 넘파이에서 제공하는 bool 인덱싱을 이용해서 마스크 연산을 할 수 있습니다.

dst[mask > 0] = src[mask > 0]

 

[mask > 0] 의미

 mask 영상에서 픽셀이 0보다 큰 것을 다 찾습니다. mask 크기의 영상을 생성하고 True로 반환합니다. True로 반환된 인덱스만 가져올 수 있습니다.

 

 

2. 알파 채널을 마스크 영상으로 이용

 알파 채널은 투명도를 의미합니다. 따라서 4채널로 구성되어 있습니다.

 GIMP로 작업을 하면 투명도가 적용된 알파 채널이 생성될 수 있습니다.

 이 경우에 마스크 연산을 어떻게 하는지 알아보도록 하겠습니다.

 

 알파 채널을 불러올 때 cv2.IMREAD_UNCHANGED 명령어로 4채널 영상을 불러올 수 있습니다.

 

예제코드

src = cv2.imread('cat.bmp', cv2.IMREAD_COLOR)

# cv2.IMREAD_UNCHANGED로 4채널 영상을 불러올 때 이용
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는 알파 채널로 만든 마스크 영상
# 그레이스케일이어야 하므로 3마지막 값만 갖고 와서 1차원으로 만들어준다.
mask = logo[:, :, 3]

# logo는 b, g, r 3채널로 구성된 컬러, 4채널이므로 -1 까지 갖고옴
logo = logo[:, :, :-1]

h, w = mask.shape[:2]

# src와 dst의 크기가 다르다. 따라서 마스크 연산이 안됌
# src와 동일한 크기의 영상을 추출 = crop
crop = src[10:10+h, 10:10+w]  # logo, mask와 같은 크기의 부분 영상 추출, 좌표는 임의대로

cv2.copyTo(logo, mask, crop)
#crop[mask > 0] = logo[mask > 0] # bool 인덱싱도 이용 가능

 

 

반응형