[opencv-python] ROI를 이용한 이미지 합성


ROI를 이용한 이미지 합성

logo 이미지를 background 이미지 정중앙에 합성하는 예제를 알아보겠습니다.


2개의 이미지 불러오기

import cv2

background = cv2.imread("image/bit_test.jpg")
logo = cv2.imread("image/logo.jpg")

cv2.imshow("background", background)
cv2.imshow("logo", logo)
cv2.waitKey()




ROI 영역 설정에 사용할 mask 생성

gray_logo = cv2.cvtColor(logo, cv2.COLOR_BGR2GRAY)
_, mask_inv = cv2.threshold(gray_logo, 10, 255, cv2.THRESH_BINARY_INV)

cv2.imshow("mask_inv", mask_inv)
cv2.waitKey()

cv2.cvtColor(logo, cv2.COLOR_BGR2GRAY)

Notes

Color-space를 변환하는 함수.
cv2.COLOR_BGR2GRAY를 통해 컬러인 logo 이미지를 gray 이미지로 변환합니다.

BGR to GRAY




cv2.threshold(gray_logo, 10, 255, cv2.THRESH_BINARY_INV)

Notes

임계값(thresh)를 넘으면 임계값을 넘었을 때 적용할 value(maxval)로 값을 변경하는 함수.
cv2.THRESH_BINARY_INV를 통해 이미지를 이진화합니다. (흑(0)과 백(255)으로 분리) # binary image
INV(inverse)가 사용되었음으로 분리된 흑과 백을 반대로 변경합니다 (흑->백, 백->흑) # binary_inverse image

cv2.threshold(gray_logo, 10, 255, cv2.THRESH_BINARY_INV)는
gray_logo에서 10(thresh)보다 큰 임계값들을 모두 255(maxval)로
10보다 작은 값들은 0으로 변경하여 이진화 하겠다는 뜻입니다. 

GRAY to BINARY_INV





ROI 영역 설정 (background 이미지 정중앙)

background_height, background_width, _ = background.shape # 400, 520, 3
logo_height, logo_width, _ = logo.shape # 308, 250, 3

x = (background_height - logo_height) // # /2의 몫만 가져옴 (정수만 가져오기 위해)
y = (background_width - logo_width) // 2

roi = background[x: x+logo_height, y: y+logo_width]
cv2.imshow("ROI", roi)
cv2.waitKey()

opencv-python 좌표평면

Notes

수학 좌표명면과 다르게 0, 0을 기준으로
오른쪽으로 갈수록 x값이 증가하고
아래쪽으로 갈수록 y값이 증가합니다.



하나의 좌표평면에 표시한 background, logo 이미지

Notes

background 정중앙에 logo 이미지를 위치시키기 위해
logo (0, 0) 좌표 변경이 필요합니다.



logo (0, 0) 좌표 수정

Notes

x = background_height - logo_height
y = background_width - logo_width
를 취해 나온 값으로 logo (0, 0)을 수정합니다.
(0, 0) -> (92, 270)



background 정중앙에 위치한 logo

Notes

x = (background_height - logo_height) // 2
y = (background_width - logo_width) // 2 를 취해
background 정중앙에 logo 이미지를 위치시킵니다.
이때 //2로 몫(정수 값)만 가져오는 이유는 좌표평면에 표시해야하기 때문입니다.

(92, 270)을 /2 해주어 (46, 135)로 중앙 좌표를 만듬.



ROI에서 logo 부분 추출

roi_logo = cv2.add(logo, roi, mask=mask_inv)
cv2.imshow("roi_logo", roi_logo)
cv2.waitKey()

Notes

ROI에서 logo 부분을 합성하는데 이때 mask 영역에 대해서만 합성을 합니다.

mask 영역이란 아래의 mask(binary inverse) image에서 하얀색(255) 부분 영역에 픽셀 범위입니다.
mask 영역에 대해 add하면 ROI + logo image의 검은부분(0)을 add하니 이미지 변화가 없습니다. ( 144 + 0 = 144 이기 때문에 값의 변화 X )

mask 영역에 대해서만 ROI 값과 logo 값을 add하기 때문에 ROI + 검정색 로고가 roi_logo image에 나타납니다.




ROI_logo와 logo 합성

result = cv2.add(roi_logo, logo)
cv2.imshow("result", result)
cv2.waitKey()

Notes

roi_logo와 logo를 합성합니다.
이미지 검은 영역의 픽셀 값은 0이기에 add 연산에 영향을 미치지 않습니다. ( 144 + 0 = 144이기 때문에 )




합성된 roi_logo의 값을 roi로 복사

np.copyto(roi, result)
cv2.imshow("result_background", background)
cv2.waitKey()

Notes

np.copyto()를 사용해 result의 있는 값들을 roi로 복사했습니다.

보다 자세한 np.copyto의 정보는 아래의 링크를 참조하세요.
https://daewoonginfo.blogspot.com/2019/05/python-numpycopyto.html


참고문헌




댓글

이 블로그의 인기 게시물

[opencv-python] 이미지 크기조절(resize) 하는 법

[python]파이썬: csv reader header skip (첫번째 행 무시하기, 안읽기)

[python] selenium close와 quit 차이점