본문 바로가기

머신러닝 & 딥러닝 공부/호기심 기록

[BeautyGAN] 화장해주는 인공지능 구현

반응형

 

 

 

안녕하세요~

27년차 진로탐색꾼 조녁입니다!!

 

오늘은 색다르게 개인프로젝트로 찾아왔습니다!!

텐서플로우 개발자 자격증 취득 후 실제로 사용해보면 좋겠다 싶어서 개인 프로젝트를 해볼까합니다!!

 

다행히 좋은 유튜브 , 깃허브 오픈소스 , 논문 등등 좋은 선생님들이 많아서 참 감사합니다 ㅎㅎ

(샤라웃투 빵형)

 

 

* 오늘의 과제 : 다른 사람의 화장을 내 얼굴에 입히는 Makeup transfer를 구현해봐요!

 

 

0. 이론 : BeautyGAN: Instance-level Facial Makeup Transfer with Deep Generative Adversarial Network

 

: 두장의 사진이 있다. 한장은 생얼(x)이고, 한장은 화장한 사진(y)이다. 이 두장을 통해 4장을 만드는데 x,y에 x+makeup / y-makeup 사진을 추가해준다. 이 때, x 와 x+makeup / y 와 y-makeup 비교하여 perceptual loss 계산 , makeup된 두 사진 x+makeup 과 y를 비교하여 makeup loss를 계산해준다.

 

이후, 다시 y-makeup+makeup을 해주고, x+makeup-makeup 해줘서 처음과 같이 돌려놓는다. 그리고 x 와 x+makeup-makeup / y와 y-makeup+makeup 비교하여 cycle consistency loss를 계산해준다. 

 

계산한 loss를 줄이면서 모델을 학습시킨다. 우리는 학습된 모델을 전이학습(Transfer Learning)을 통해 사용할 것이다.

 

 

 

실습 준비 )

-라이브러리 : dlib (이미지 처리 라이브러리) , matplotlib  , tensorflow , numpy 

-사진 및 모델 다운로드 : 저는 colab 환경에서 코드를 작성했기 떄문에 git_hub에서 model과 images 를 다운로드 받아서 제 구글 드라이브에 올린 후 Colab 과 구글 드라이브를 연동해서 사용하였습니다. 

 

#라이브러리
import dlib #이미지처리 라이브러리 , 페이스 디텍션, 랜드마크 디텍션, 페이스 얼라이브 
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import tensorflow as tf
import numpy as np

#Load Models
detector = dlib.get_frontal_face_detector()  #얼굴 영역 인식 모델 로드
sp = dlib.shape_predictor("/content/drive/MyDrive/01-BeautyGAN/models/shape_predictor_5_face_landmarks.dat")

#Load Images
img = dlib.load_rgb_image("/content/drive/MyDrive/01-BeautyGAN/images/05.jpg")

plt.figure(figsize=(16,10))
plt.imshow(img)

 

 

 

< 예시 이미지 > 

 

 

1. 페이스 디텍션(Face Detection) : 사진에서 얼굴 부분을 찾아낸다. 

 

 

img_result = img.copy()

dets = detector(img,1) #이미지에서 얼굴 영역을 찾는다.

if len(dets) == 0: #얼굴영역의 갯수가 0일 경우
  print('cannot find faces!')

fig, ax = plt.subplots(1, figsize=(16,10))

for det in dets: #det이라는 직사각형 정보에 대한 for문
  x, y, w, h = det.left(), det.top(), det.width(), det.height()

  rect = patches.Rectangle((x,y),w, h, linewidth=2, edgecolor='r', facecolor='none')
  ax.add_patch(rect)

ax.imshow(img_result)

 

 

2. 랜드마크 디텍션(Landmark Detection) : 페이스 디텍션한 부분에서 눈 양쪽끝과 코끝에 총 5개의 점을 찾아준다. 

 

 

fig, ax = plt.subplots(1, figsize=(16,10))

objs =dlib.full_object_detections() #얼굴 수평맞춰줄때 사용

for detection in dets:
  s = sp(img, detection) #sp() : 얼굴의 랜드마크를 찾는다.
  objs.append(s)

  for point in s.parts(): #5개의 점에 대한 for문
    circle = patches.Circle((point.x,point.y), radius=3, edgecolor='r',facecolor='r')
    ax.add_patch(circle)

ax.imshow(img_result)

 

 

3. 페이스 얼라인(Align Faces) : 5개의 랜드마크를 기준으로 얼굴의 수평을 맞춰준다.

 

 

faces = dlib.get_face_chips(img, objs, size=256, padding=0.3) #dilb.get_face_chips() : 얼굴을 수평으로 회전하여 얼굴 부분만 자른 이미지 반환

flg,axes = plt.subplots(1, len(faces)+1, figsize=(20,16))

axes[0].imshow(img) #원본이미지

for i,face in enumerate(faces): #디텍션한 얼굴이 여러개면 여러개 찍어준다.
  axes[i+1].imshow(face)

 

 

4. 함수화(Functionalize) : 위에서 수행한 작업을 aligh_faces() 함수로 만들어 줍니다.

 

def align_faces(img):  #원본이미지를 넣으면 align 완료된 얼굴이미지 반환하는 함수
  dets = detector(img,1)

  objs = dlib.full_object_detections()

  for detection in dets:
    s = sp(img, detection)
    objs.append(s)
  
  faces = dlib.get_face_chips(img, objs, size=256, padding=0.35)

  return faces 

#test
test_img = dlib.load_rgb_image("/content/drive/MyDrive/01-BeautyGAN/images/02.jpg")

test_faces = align_faces(test_img)

fig, axes = plt.subplots(1, len(test_faces)+1, figsize=(20,16))
axes[0].imshow(test_img)

for i, face in enumerate(test_faces):
  axes[i+1].imshow(face)

 

 

>> test로 여러명의 사람이 있는 사진을 넣었을 때, for문을 통해 각 사람의 얼굴이 반환되는 것을 잘 볼 수 있습니다.

 

 

이제 준비를 마쳤으며, 본격적으로 BeautyGAN을 들어가보도록 하겠습니다.

 

 

5. 학습된 BeautyGAN 모델 불러오기(Load BeautyGAN Pretrained)

 

tf.compat.v1.disable_eager_execution()
#at the beginning of the program for complex migration projects from TensorFlow 1.x to 2.x.

 

with tf.compat.v1.Session() as sess:    #위 코드를 통해 즉시실행했기 때문에 with문으로 감싸줘야한다.
  sess.run(tf.compat.v1.global_variables_initializer())

sess = tf.compat.v1.Session()
saver = tf.compat.v1.train.import_meta_graph("/content/drive/MyDrive/01-BeautyGAN/models/model.meta")
saver.restore(sess, tf.train.latest_checkpoint("/content/drive/MyDrive/01-BeautyGAN/models"))
graph = tf.compat.v1.get_default_graph()

X = graph.get_tensor_by_name('X:0') #source
Y = graph.get_tensor_by_name('Y:0') #reference
Xs = graph.get_tensor_by_name('generator/xs:0') #output

 

6. 전처리 및 후처리 함수(Preprocess and Postprocess Functions)

 

def preprocess(img):
  return img.astype(np.float32) / 127.5 -1           #0 ~ 255 -> -1 ~ 1

def postprocess(img):
  return ((img+1.)*127.5).astype(np.uint8)           #-1 ~ 1 -> 0 ~ 255

 

7. 이미지 다운로드(Load Images) : Load img1(no_makeup) , img2(makeup) images

 

img1 = dlib.load_rgb_image("/content/drive/MyDrive/01-BeautyGAN/images/11.jpg")
img1_faces = align_faces(img1)

img2 = dlib.load_rgb_image("/content/drive/MyDrive/01-BeautyGAN/images/makeup/XMY-014.png")
img2_faces = align_faces(img2)

fig, axes = plt.subplots(1, 2, figsize=(16,10))
axes[0].imshow(img1_faces[0])
axes[1].imshow(img2_faces[0])

 

 

8. 실행(Run) : x: source (no-makeup) + y:reference (makeup) = xs: output

 

src_img = img1_faces[0] #소스 이미지 
ref_img = img2_faces[0] #레퍼런스 이미지

X_img = preprocess(src_img)
X_img = np.expand_dims(X_img,axis=0) #np.expand_dims() : 배열에 차원을 추가한다. 즉, (256,256,2) -> (1,256,256,3)

Y_img = preprocess(ref_img)
Y_img = np.expand_dims(Y_img,axis=0) #텐서플로에서 0번 axis는 배치 방향

output = sess.run(Xs, feed_dict={
    X: X_img,
    Y: Y_img
})

output_img = postprocess(output[0])

fig,axes =plt.subplots(1,3, figsize=(20,10))
axes[0].set_title('Source')
axes[0].imshow(src_img)
axes[1].set_title('Reference')
axes[1].imshow(ref_img)
axes[2].set_title('Result')
axes[2].imshow(output_img)

output : 

 

 

이렇게 소소한 프로젝트를 마쳤다. 빵형 유튜브를 따라가며 git_hub에서 파일을 불러오는 것도, 구글 드라이브에 마운트하는 것도 , tensorflow 버전처리를 위해 코드를 수정한 것도  처음이었다. 물론 이미지 디텍션, 얼라인, 전이학습(BeautyGAN) 을 직접 사용해본 것도 처음이었다. 직접 결과물까지 눈으로 볼 수 있어서 재밌었고, 주제자체가 신선했다. 잘 정리해서 차곡차곡 쌓아가야 겠다!! 

 

 

 

p.s 텐서플로우 , 파이썬, 깃아 친해지자!!  

 

<참고자료> 

더보기

 

 

반응형