Python/OpenCV

[파이썬]OpenCV 두가지 이미지를 쉽게 합성해 보기

두잇(Do It) 2023. 5. 24. 02:30
반응형

이번시간에는 두가지 이미지를 합성해보도록 하겠습니다.
OpenCV에서 이미지를 합성 하는 방법에는 여러가지가 있지만
그중에서 가장 쉽게 합성할 수 있는 seamlessClone() 함수를 사용해서
이미지를 합성해 보도록 하겠습니다.
 

semlessClone 함수 뜯어보기

dst = cv2.seamlessClone(src, dst, mask, coords, flags[, output])
  • src : 입력 영상, 일반적으로 전경
  • dst : 대상 영상, 일반적으로 배경
  • mask : 마스크, src에서 합성하고자 하는 영역은 255, 나머지는 0
  • coords : src가 놓여지기 원하는 dst의 좌표(중앙)

 
코드에서 오류가 발생한다면
터미널에서 다음을 입력해서
라이브러리를 설치해보도록 합니다

pip install matplotlib

 

두가지 사진 합성하기

우선 두가지 사진입니다.

왼쪽이 배경으로 사용할 책상 이미지이고 오른쪽이 합성될 대상입니다.

 
코드를 살펴보도록 하겠습니다

import cv2
import numpy as np
import matplotlib.pylab as plt

img1 = cv2.imread('1.jpg')
img2 = cv2.imread('2.jpg')

mask = np.full_like(img2, 255)

height, width = img2.shape[:2]
center = (width//2, height//2)

normal = cv2.seamlessClone(img2, img1, mask, center, cv2.NORMAL_CLONE)
mixed = cv2.seamlessClone(img2, img1, mask, center, cv2.MIXED_CLONE)

# 이미지 크기 조절 x 0.2 배율, y 0.2 배율로 조정
resize_normal = cv2.resize(normal, dsize=(0, 0), fx=0.2, fy=0.2, interpolation=cv2.INTER_LINEAR)
resize_mixed = cv2.resize(mixed, dsize=(0, 0), fx=0.2, fy=0.2, interpolation=cv2.INTER_LINEAR)

cv2.imshow('normal', resize_normal)
cv2.imshow('mixed',resize_mixed)
cv2.waitKey()
cv2.destroyAllWindows()

img2를 img1에다가 mask에 지정된 영역만큼 center 좌표에 합성합니다.
이때 마스크는 img2의 전체 영역을 255로 채워서 해당 영역 전부가 합성의 대상임을 표현합니다.
가급적이면 합성하려는 영역을 제외하고 0으로 채우는것이 더 좋습니다
우선 아래의 결과부터 보도록 하겠습니다.

 
cv2.NORMAL_CLONE의 경우 원본 영역을 선명하게 표현하지만
어색하게 합성이 됩니다 배경이 비슷할때 괜찮을 것 같습니다
cv2.MIXED_CLONE의 경우에는 두 영상의 특징을 살려서 표현합니다
약간 투명해서 질감이 있는 물체의 경우에는 약간 티나게 표현됩니다
얇은 물체는 티가 안날수도^^
상당히 편리하게 합성할 수 있겠네요
 

이미지 합성하는 다른 방법

이번에 소개할 방법은 png파일을 이용해서 합성하는 방법입니다.
png파일의 특성은 투명도를 지원하는 알파채널을 포함하고 있어
배경이 없는 이미지를 쉽게 얻어낼 수 있습니다.
OpenCV의 로고 예제 파일입니다
 

2.png
0.00MB

 
뜯어보면 아래와 같습니다

 
합성한 결과를 보면 아주 깔끔하게 합성이 되는 것을 보실 수 있습니다.

고프로 사진 파일 사이즈가 너무커서 로고가 너무 작게 합성되긴 했네요..^^;;
 
다음은 코드 입니다

import cv2
import numpy as np

# 사진 파일 읽기
img_fg = cv2.imread('2.png', cv2.IMREAD_UNCHANGED)
img_bg = cv2.imread('2.jpg')

# 마스크와 역마스크 생성
_, mask = cv2.threshold(img_fg[:,:,3], 1, 255, cv2.THRESH_BINARY)
mask_inv = cv2.bitwise_not(mask)

# 배경 영상에서 ROI 잘라내기
img_fg = cv2.cvtColor(img_fg, cv2.COLOR_BGRA2BGR)
h, w = img_fg.shape[:2]
roi = img_bg[10:10+h, 10:10+w ]

# 마스크 이용해서 오려내기
masked_fg = cv2.bitwise_and(img_fg, img_fg, mask=mask)
masked_bg = cv2.bitwise_and(roi, roi, mask=mask_inv)

# 이미지 합성
added = masked_fg + masked_bg
img_bg[10:10+h, 10:10+w] = added

#이미지 크기 조정
resize_img=cv2.resize(img_bg, dsize=(0, 0), fx=0.2, fy=0.2, interpolation=cv2.INTER_LINEAR)

cv2.imshow('mask', mask)
cv2.imshow('mask_inv', mask_inv)
cv2.imshow('masked_fg', masked_fg)
cv2.imshow('masked_bg', masked_bg)
cv2.imshow('added', added)
cv2.imshow('result', resize_img)
cv2.waitKey()
cv2.destroyAllWindows()

 
이상으로 이미지를 합성하는 방법에 대하여 알아보았습니다
감사합니다

반응형