빅데이타 & 머신러닝/머신러닝

얼굴 인식 모델을 만들어보자 #3 - 학습된 모델로 예측하기

Terry Cho 2017. 6. 19. 14:53

 

얼굴 인식 모델을 만들어보자

#3 - 학습된 모델로 예측하기


조대협 (http://bcho.tistory.com)


앞글에 걸쳐서 얼굴 인식을 위한 데이타를 수집 및 정재하고, 이를 기반으로 얼굴 인식 모델을 학습 시켰다.

 

 

이번글에서는 학습이 된 데이타를 가지고, 사진을 넣어서 실제로 인식하는 코드를 만들어보자

전체 소스 코드는 https://github.com/bwcho75/facerecognition/blob/master/2.%2BFace%2BRecognition%2BPrediction%2BTest.ipynb 와 같다.

모델 로딩 하기

 

모델 학습에 사용한 CNN 모델을 똑같이 정의한다. conv1(),conv2(),conv3(),conv4(),fc1(),fc2(), build_model() 등 학습에 사용된 CNN 네트워크를 똑같이 정의하면 된다.

 

다음으로 이 모델에 학습된 값들을 채워 넣어야 한다.

# build graph

images = tf.placeholder(tf.float32,[None,FLAGS.image_size,FLAGS.image_size,FLAGS.image_color])

keep_prob = tf.placeholder(tf.float32) # dropout ratio

 

예측에 사용할 image 를 넘길 인자를  images라는 플레이스홀더로 정의하고, dropout 비율을 정하는 keep_prob도 플레이스 홀더로 정의한다.

 

prediction = tf.nn.softmax(build_model(images,keep_prob))

 

그래프를 만드는데, build_model에 의해서 나온 예측 결과에 softmax 함수를 적용한다. 학습시에는 softmax 함수의 비용이 크기 때문에 적용하지 않았지만, 예측에서는 결과를 쉽게 알아보기 위해서  softmax 함수를 적용한다. Softmax 함수는 카테고리 별로 확률을 보여줄때 전체 값을 1.0으로 해서 보여주는것인데, 만약에 Jolie,Sulyun,Victora 3개의 카테코리가 있을때 각각의 확률이 70%,20%,10%이면 Softmax를 적용한 결과는 [0.7,0.2,0.1] 식으로 출력해준다.

 

sess = tf.InteractiveSession()

sess.run(tf.global_variables_initializer())

 

다음 텐서플로우 세션을 초기화 하고,

 

saver = tf.train.Saver()

saver.restore(sess, 'face_recog')

 

마지막으로 Saver의 restore 함수를 이용하여 ‘face_recog’라는 이름으로 저장된 학습 결과를 리스토어 한다. (앞의 예제에서, 학습이 완료된 모델을 ‘face_recog’라는 이름으로 저장하였다.)

 

예측하기

로딩 된 모델을 가지고 예측을 하는 방법은 다음과 같다. 이미지 파일을 읽은 후에, 구글 클라우드 VISION API를 이용하여, 얼굴의 위치를 추출한후, 얼굴 이미지만 크롭핑을 한후에, 크롭된 이미지를 텐서플로우 데이타형으로 바꾼후에, 앞서 로딩한 모델에 입력하여 예측된 결과를 받게 된다.

 

얼굴 영역 추출하기

먼저 vision API로 얼굴 영역을 추출하는 부분이다. 앞의 이미지 전처리에 사용된 부분과 다르지 않다.

 

import google.auth

import io

import os

from oauth2client.client import GoogleCredentials

from google.cloud import vision

from PIL import Image

from PIL import ImageDraw

 

FLAGS.image_size = 96

 

# set service account file into OS environment value

os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "/Users/terrycho/keys/terrycho-ml.json"

 

위와 같이 구글 클라우드 Vision API를 사용하기 위해서 억세스 토큰을 Service Account 파일로 다운 받아서 위와 같이 GOOGLE_APPLICATION_CREDENTIALS 환경 변수에 세팅 하였다.

 

visionClient = vision.Client()

print ('[INFO] processing %s'%(imagefile))

 

#detect face

image = visionClient.image(filename=imagefile)

faces = image.detect_faces()

face = faces[0]

 

다음 vision API 클라이언트를 생성한 후에, detect_faces() 를 이용하여 얼굴 정보를 추출해낸다.

 

print 'number of faces ',len(faces)

 

#get face location in the photo

left = face.fd_bounds.vertices[0].x_coordinate

top = face.fd_bounds.vertices[0].y_coordinate

right = face.fd_bounds.vertices[2].x_coordinate

bottom = face.fd_bounds.vertices[2].y_coordinate

rect = [left,top,right,bottom]

 

추출된 얼굴 정보에서 첫번째 얼굴의 위치 (상하좌우) 좌표를 리턴 받는다.

얼굴 영역을 크롭하기

앞에서 입력 받은 상하좌우 좌표를 이용하여, 이미지 파일을 열고,  크롭한다.

 

fd = io.open(imagefile,'rb')

image = Image.open(fd)

 

import matplotlib.pyplot as plt

# display original image

print "Original image"

plt.imshow(image)

plt.show()

 

 

# draw green box for face in the original image

print "Detect face boundary box "

draw = ImageDraw.Draw(image)

draw.rectangle(rect,fill=None,outline="green")

 

plt.imshow(image)

plt.show()

 

crop = image.crop(rect)

im = crop.resize((FLAGS.image_size,FLAGS.image_size),Image.ANTIALIAS)

plt.show()

im.save('cropped'+imagefile)

 

크롭된 이미지를 텐서플로우에서 읽는다.

 

print "Cropped image"

tfimage = tf.image.decode_jpeg(tf.read_file('cropped'+imagefile),channels=3)

tfimage_value = tfimage.eval()

 

크롭된 파일을 decode_jpeg() 메서드로 읽은 후에, 값을 tfimage.eval()로 읽어드린다.

 

tfimages = []

tfimages.append(tfimage_value)

 

앞에서 정의된 모델이 한개의 이미지를 인식하는게 아니라 여러개의 이미지 파일을 동시에 읽도록 되어 있기 때문에, tfimages라는 리스트를 만든 후, 인식할 이미지를 붙여서 전달한다.

 

plt.imshow(tfimage_value)

plt.show()

fd.close()

 

p_val = sess.run(prediction,feed_dict={images:tfimages,keep_prob:1.0})

name_labels = ['Jessica Alba','Angelina Jolie','Nicole Kidman','Sulhyun','Victoria Beckam']

i = 0

for p in p_val[0]:

   print('%s %f'% (name_labels[i],float(p)) )

   i = i + 1

 

tfimages 에 이미지를 넣어서 모델에 넣고 prediction 값을 리턴 받는다. dropout은 사용하지 않기 때문에, keep_prob을 1.0으로 한다.

나온 결과를 가지고 Jessica, Jolie,Nicole Kidman, Sulhyun, Victoria Beckam 일 확률을 각각 출력한다.


전체 코드는 https://github.com/bwcho75/facerecognition/blob/master/2.%2BFace%2BRecognition%2BPrediction%2BTest.ipynb


다음은 설현 사진을 가지고 예측을 한 결과 이다.


 

이 코드는 학습된 모델을 기반으로 얼굴을 인식이 가능하기는 하지만 실제 운영 환경에 적용하기에는 부족하다. 파이썬 모델 코드를 그대로 옮겼기 때문에, 성능도 상대적으로 떨어지고, 실제 운영에서는 모델을 업그레이드 배포 할 수 있고, 여러 서버를 이용하여 스케일링도 지원해야 한다.

그래서 텐서플로우에서는 Tensorflow Serving 이라는 예측 서비스 엔진을 제공하고 구글 클라우에서는 Tensorflow Serving의 매니지드 서비스인, CloudML 서비스를 제공한다.

 

앞의 두 글이 로컬 환경에서 학습과 예측을 진행했는데, 다음 글에서는 상용 서비스에 올릴 수 있는 수준으로 학습과 예측을 할 수 있는 방법에 대해서 알아보도록 하겠다.

 

그리드형