본문 바로가기

AIFFLE/PROJECT

[CV] 인물사진 만들기 - 기본편 (OpenCV, semantic segmentation)

728x90
학습 내용
  • 인물사진의 구현 방식을 이해해본다
  • instance segmentation을 이해한다
  • cv2 완벽 활용기

 

 

개요

  • 인물사진의 구현 방식에 대해 이해하면서 OpenCV에 대해 이해해보자
  • 기존 모델을 불러와서 인물사진을 만드는 기본적인 방식을 이해해보는 시간을 가졌다

 

인물 사진 구현방식 요약

  1. 이미지/모델 불러오기
  2. 피사체 분리 (image segmentation으로 사람만 분리해내자)
  3. 배경 흐리게
  4. 이미지 합성

 

이미지 불러오기

import os
import urllib
import cv2
import numpy as np

from pixellib.semantic import semantic_segmentation
from matplotlib import pyplot as plt

img_path = os.getenv('HOME')+'/aiffel/human_segmentation/images/cat.jpeg'  
img_orig = cv2.imread(img_path) 

plt.imshow(cv2.cvtColor(img_orig, cv2.COLOR_BGR2RGB))
plt.show()

  • cv2.COLOR_BGR2RGB: 이미지 색상 채널을 변경 (BGR 형식을 RGB 형식으로 변경)
  • plt.imshow(): 저장된 데이터를 이미지의 형식으로 표시, 입력은 RGB(A) 데이터 혹은 2D 스칼라 데이터

 

 

모델 불러오기

  • urllib 패키지 내에 있는 request 모듈의 urlretrieve 함수를 이용
  • model_url에 있는 파일을 다운로드 해서 model_file 파일명으로 저장
# 저장할 파일 이름을 결정
model_dir = os.getenv('HOME')+'/aiffel/human_segmentation/models' 
model_file = os.path.join(model_dir, 'deeplabv3_xception_tf_dim_ordering_tf_kernels.h5') 

# PixelLib가 제공하는 모델의 url입니다
model_url = 'https://github.com/ayoolaolafenwa/PixelLib/releases/download/1.1/deeplabv3_xception_tf_dim_ordering_tf_kernels.h5' 

# 다운로드 시작
urllib.request.urlretrieve(model_url, model_file)

 

  • PixelLib 라이브러리 에서 가져온 클래스를 가져와서 semantic segmentation을 수행하는 클래스 인스턴스를 만듦
  • pascal voc에 대해 훈련된 예외 모델(model_file)을 로드하는 함수를 호출
  • 입력된 이미지를 분할, 분할 출력의 배열을 가져옴, 분할 은 pacalvoc 데이터로 학습된 모델을 이용
model = semantic_segmentation() 
model.load_pascalvoc_model(model_file)
segvalues, output = model.segmentAsPascalvoc(img_path)

 

pascalvoc 데이터의 라벨종류

LABEL_NAMES = [
    'background', 'aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus',
    'car', 'cat', 'chair', 'cow', 'diningtable', 'dog', 'horse', 'motorbike',
    'person', 'pottedplant', 'sheep', 'sofa', 'train', 'tv'
]
len(LABEL_NAMES) # 21개

 

Segmentation 결과확인

plt.imshow(output)
plt.show()

#segvalues에 있는 class_ids를 담겨있는 값을 통해 pacalvoc에 담겨있는 라벨을 출력
for class_id in segvalues['class_ids']:
    print(LABEL_NAMES[class_id])
background
cat
person
  • 사람손까지 아주 잘 인식한 것을 볼 수 있다

 

컬러맵 만들기

colormap = np.zeros((256, 3), dtype = int)
ind = np.arange(256, dtype=int)

for shift in reversed(range(8)):
    for channel in range(3):
        colormap[:, channel] |= ((ind >> channel) & 1) << shift
    ind >>= 3

colormap[:20] #생성한 20개의 컬러맵 출력
array([[  0,   0,   0],
       [128,   0,   0],
       [  0, 128,   0],
       [128, 128,   0],
       [  0,   0, 128],
       [128,   0, 128],
       [  0, 128, 128],
       [128, 128, 128],
       [ 64,   0,   0],
       [192,   0,   0],
       [ 64, 128,   0],
       [192, 128,   0],
       [ 64,   0, 128],
       [192,   0, 128],
       [ 64, 128, 128],
       [192, 128, 128],
       [  0,  64,   0],
       [128,  64,   0],
       [  0, 192,   0],
       [128, 192,   0]])
 
  • 위 코드를 통해 컬러맵을 만들었고 라벨과 인덱스가 일치하는 형태이다
    • 예를 들어 colormap[15] 는 사람이고 colormap[8] 은 고양이 이다
colormap[8] # 고양이

array([64,  0,  0])

 

 

색상순서 변경

  • colormap의 배열은 RGB 순이며 output의 배열은 BGR 순서로 채널 배치가 되어 있어서 색상 순서를 변경해줘야 한다
  • 고양이 컬러맵이 [64, 0, 0]이므로 (0, 0, 64)를 저장한다
seg_color = (0,0,64) 

# output의 픽셀 별로 색상이 seg_color와 같다면 1(True), 다르다면 0(False)이 된다
# seg_color 값이 cat을 나타내는 값이므로 고양이가 있는 위치를 제외하고는 gray로 출력
# cmap 값을 변경하면 다른 색상으로 확인이 가능함
seg_map = np.all(output==seg_color, axis=-1) 
print(seg_map.shape) 
plt.imshow(seg_map, cmap='gray')
plt.show()

고양이가 잘 뽑힌 것을 볼 수 있다

배경 흐리게 하기

img_orig_blur = cv2.blur(img_orig, (13,13))

# cv2.COLOR_BGR2RGB: 원본이 BGR 순서로 픽셀을 읽다보니 이미지 색상 채널을 변경해야함 (BGR 형식을 RGB 형식으로 변경)   
plt.imshow(cv2.cvtColor(img_orig_blur, cv2.COLOR_BGR2RGB))
plt.show()

 

최종 결과물

  • np.where(조건, 참일때, 거짓일때)
  • 세그멘테이션 마스크가 255인 부분만 원본 이미지 값을 가지고 오고 아닌 영역은 블러된 이미지 값을 사용합니다.
img_concat = np.where(img_mask_color==255, img_orig, img_bg_blur)

plt.imshow(cv2.cvtColor(img_concat, cv2.COLOR_BGR2RGB))
plt.show()

 

최종 정리

 

  • instance segmentation을 통해 어떻게 인물 사진을 구현하는지 기본적인 방식에 대해 이해해 볼 수 있었다.
  • 이후에는 추가적으로 현재 방식의 문제점을 파악해보고 이에 대한 개선 방향에 대해 이야기 해보고자 한다

 

 

 

 

 

참고자료 / 최종 결과물

 

실습 과정 코드

728x90