안녕하세요~
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 텐서플로우 , 파이썬, 깃아 친해지자!!
<참고자료>
-유튜브 : 빵형의 개발도상국
www.youtube.com/watch?v=Uhn3dmW1uuM&list=PL-xmlFOn6TUKlxlh3PIuAzHkJakFlcDvY&index=5
-논문 : BeautyGAN: Instance-level Facial Makeup Transfer with Deep Generative Adversarial Network
liusi-group.com/projects/BeautyGAN
-깃허브 : github.com/jonhyuk0922/01.BeautyGAN
-Tensorflow 공.홈 (version 1.x -> 2.x) : www.tensorflow.org/guide/migrate
'머신러닝 & 딥러닝 공부 > 호기심 기록' 카테고리의 다른 글
[딥러닝] 왜 CNN의 Input_shape 은 4D일까? (0) | 2021.04.23 |
---|---|
[Librosa] 음성인식 기초 및 음악분류 & 추천 알고리즘 (13) | 2021.04.15 |
나를 위한 딥러닝 용어정리 (0) | 2021.01.19 |
나를 위한 머신러닝 용어정리 (0) | 2021.01.19 |
[머신러닝]sklearn 활용해서 Iris(붓꽃) 분류 모델 구현 (0) | 2021.01.18 |