Note: 최신 버전의 라이브러리를 사용하기 때문에 책의 내용과 결과가 다를 수 있습니다
import numpy as np
import matplotlib.pyplot as plt
import numpy as np
import os
from scipy.stats import norm
import pandas as pd
from models.VAE import VariationalAutoencoder
from utils.loaders import load_model, ImageLabelLoader
Using TensorFlow backend.
# run params
section = 'vae'
run_id = '0001'
data_name = 'faces'
RUN_FOLDER = 'run/{}/'.format(section)
RUN_FOLDER += '_'.join([run_id, data_name])
DATA_FOLDER = './data/celeb/'
IMAGE_FOLDER = './data/celeb/img_align_celeba/'
INPUT_DIM = (128,128,3)
att = pd.read_csv(os.path.join(DATA_FOLDER, 'list_attr_celeba.csv'))
imageLoader = ImageLabelLoader(IMAGE_FOLDER, INPUT_DIM[:2])
att.head()
image_id | 5_o_Clock_Shadow | Arched_Eyebrows | Attractive | Bags_Under_Eyes | Bald | Bangs | Big_Lips | Big_Nose | Black_Hair | ... | Sideburns | Smiling | Straight_Hair | Wavy_Hair | Wearing_Earrings | Wearing_Hat | Wearing_Lipstick | Wearing_Necklace | Wearing_Necktie | Young | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 000001.jpg | -1 | 1 | 1 | -1 | -1 | -1 | -1 | -1 | -1 | ... | -1 | 1 | 1 | -1 | 1 | -1 | 1 | -1 | -1 | 1 |
1 | 000002.jpg | -1 | -1 | -1 | 1 | -1 | -1 | -1 | 1 | -1 | ... | -1 | 1 | -1 | -1 | -1 | -1 | -1 | -1 | -1 | 1 |
2 | 000003.jpg | -1 | -1 | -1 | -1 | -1 | -1 | 1 | -1 | -1 | ... | -1 | -1 | -1 | 1 | -1 | -1 | -1 | -1 | -1 | 1 |
3 | 000004.jpg | -1 | -1 | 1 | -1 | -1 | -1 | -1 | -1 | -1 | ... | -1 | -1 | 1 | -1 | 1 | -1 | 1 | 1 | -1 | 1 |
4 | 000005.jpg | -1 | 1 | 1 | -1 | -1 | -1 | 1 | -1 | -1 | ... | -1 | -1 | -1 | -1 | -1 | -1 | 1 | -1 | -1 | 1 |
5 rows × 41 columns
vae = load_model(VariationalAutoencoder, RUN_FOLDER)
WARNING:tensorflow:From /home/haesun/github/GDL_code/env/lib/python3.7/site-packages/tensorflow/python/framework/op_def_library.py:263: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version. Instructions for updating: Colocations handled automatically by placer. WARNING:tensorflow:From /home/haesun/github/GDL_code/env/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:3445: calling dropout (from tensorflow.python.ops.nn_ops) with keep_prob is deprecated and will be removed in a future version. Instructions for updating: Please use `rate` instead of `keep_prob`. Rate should be set to `rate = 1 - keep_prob`.
n_to_show = 10
data_flow_generic = imageLoader.build(att, n_to_show)
example_batch = next(data_flow_generic)
example_images = example_batch[0]
z_points = vae.encoder.predict(example_images)
reconst_images = vae.decoder.predict(z_points)
fig = plt.figure(figsize=(15, 3))
fig.subplots_adjust(hspace=0.4, wspace=0.4)
for i in range(n_to_show):
img = example_images[i].squeeze()
sub = fig.add_subplot(2, n_to_show, i+1)
sub.axis('off')
sub.imshow(img)
for i in range(n_to_show):
img = reconst_images[i].squeeze()
sub = fig.add_subplot(2, n_to_show, i+n_to_show+1)
sub.axis('off')
sub.imshow(img)
Found 202599 images.
z_test = vae.encoder.predict_generator(data_flow_generic, steps = 20, verbose = 1)
x = np.linspace(-3, 3, 100)
fig = plt.figure(figsize=(20, 20))
fig.subplots_adjust(hspace=0.6, wspace=0.4)
for i in range(50):
ax = fig.add_subplot(5, 10, i+1)
ax.hist(z_test[:,i], density=True, bins = 20)
ax.axis('off')
ax.text(0.5, -0.35, str(i), fontsize=10, ha='center', transform=ax.transAxes)
ax.plot(x,norm.pdf(x))
plt.show()
20/20 [==============================] - 4s 177ms/step
n_to_show = 30
znew = np.random.normal(size = (n_to_show,vae.z_dim))
reconst = vae.decoder.predict(np.array(znew))
fig = plt.figure(figsize=(18, 5))
fig.subplots_adjust(hspace=0.4, wspace=0.4)
for i in range(n_to_show):
ax = fig.add_subplot(3, 10, i+1)
ax.imshow(reconst[i, :,:,:])
ax.axis('off')
plt.show()
def get_vector_from_label(label, batch_size):
data_flow_label = imageLoader.build(att, batch_size, label = label)
origin = np.zeros(shape = vae.z_dim, dtype = 'float32')
current_sum_POS = np.zeros(shape = vae.z_dim, dtype = 'float32')
current_n_POS = 0
current_mean_POS = np.zeros(shape = vae.z_dim, dtype = 'float32')
current_sum_NEG = np.zeros(shape = vae.z_dim, dtype = 'float32')
current_n_NEG = 0
current_mean_NEG = np.zeros(shape = vae.z_dim, dtype = 'float32')
current_vector = np.zeros(shape = vae.z_dim, dtype = 'float32')
current_dist = 0
print('label: ' + label)
print('images : POS move : NEG move :distance : 𝛥 distance')
while(current_n_POS < 10000):
batch = next(data_flow_label)
im = batch[0]
attribute = batch[1]
z = vae.encoder.predict(np.array(im))
z_POS = z[attribute==1]
z_NEG = z[attribute==-1]
if len(z_POS) > 0:
current_sum_POS = current_sum_POS + np.sum(z_POS, axis = 0)
current_n_POS += len(z_POS)
new_mean_POS = current_sum_POS / current_n_POS
movement_POS = np.linalg.norm(new_mean_POS-current_mean_POS)
if len(z_NEG) > 0:
current_sum_NEG = current_sum_NEG + np.sum(z_NEG, axis = 0)
current_n_NEG += len(z_NEG)
new_mean_NEG = current_sum_NEG / current_n_NEG
movement_NEG = np.linalg.norm(new_mean_NEG-current_mean_NEG)
current_vector = new_mean_POS-new_mean_NEG
new_dist = np.linalg.norm(current_vector)
dist_change = new_dist - current_dist
print(str(current_n_POS)
+ ' : ' + str(np.round(movement_POS,3))
+ ' : ' + str(np.round(movement_NEG,3))
+ ' : ' + str(np.round(new_dist,3))
+ ' : ' + str(np.round(dist_change,3))
)
current_mean_POS = np.copy(new_mean_POS)
current_mean_NEG = np.copy(new_mean_NEG)
current_dist = np.copy(new_dist)
if np.sum([movement_POS, movement_NEG]) < 0.08:
current_vector = current_vector / current_dist
print('Found the ' + label + ' vector')
break
return current_vector
def add_vector_to_images(feature_vec):
n_to_show = 5
factors = [-4,-3,-2,-1,0,1,2,3,4]
example_batch = next(data_flow_generic)
example_images = example_batch[0]
example_labels = example_batch[1]
z_points = vae.encoder.predict(example_images)
fig = plt.figure(figsize=(18, 10))
counter = 1
for i in range(n_to_show):
img = example_images[i].squeeze()
sub = fig.add_subplot(n_to_show, len(factors) + 1, counter)
sub.axis('off')
sub.imshow(img)
counter += 1
for factor in factors:
changed_z_point = z_points[i] + feature_vec * factor
changed_image = vae.decoder.predict(np.array([changed_z_point]))[0]
img = changed_image.squeeze()
sub = fig.add_subplot(n_to_show, len(factors) + 1, counter)
sub.axis('off')
sub.imshow(img)
counter += 1
plt.show()
BATCH_SIZE = 500
attractive_vec = get_vector_from_label('Attractive', BATCH_SIZE)
mouth_open_vec = get_vector_from_label('Mouth_Slightly_Open', BATCH_SIZE)
smiling_vec = get_vector_from_label('Smiling', BATCH_SIZE)
lipstick_vec = get_vector_from_label('Wearing_Lipstick', BATCH_SIZE)
young_vec = get_vector_from_label('High_Cheekbones', BATCH_SIZE)
male_vec = get_vector_from_label('Male', BATCH_SIZE)
Found 202599 images. label: Attractive images : POS move : NEG move :distance : 𝛥 distance 266 : 0.898 : 1.004 : 1.493 : 1.493 537 : 0.564 : 0.66 : 1.263 : -0.229 789 : 0.338 : 0.387 : 1.131 : -0.132 1050 : 0.236 : 0.255 : 1.049 : -0.082 1327 : 0.191 : 0.209 : 1.039 : -0.01 1584 : 0.167 : 0.168 : 1.006 : -0.033 1834 : 0.133 : 0.121 : 0.985 : -0.021 2088 : 0.113 : 0.117 : 0.996 : 0.011 2338 : 0.104 : 0.102 : 0.981 : -0.015 2603 : 0.09 : 0.087 : 0.966 : -0.015 2880 : 0.083 : 0.088 : 0.971 : 0.005 3135 : 0.074 : 0.079 : 0.968 : -0.003 3396 : 0.07 : 0.071 : 0.966 : -0.002 3644 : 0.062 : 0.074 : 0.958 : -0.008 3894 : 0.06 : 0.071 : 0.951 : -0.007 4170 : 0.055 : 0.057 : 0.966 : 0.015 4429 : 0.052 : 0.056 : 0.967 : 0.001 4668 : 0.045 : 0.06 : 0.965 : -0.001 4915 : 0.044 : 0.054 : 0.958 : -0.007 5164 : 0.044 : 0.049 : 0.963 : 0.006 5411 : 0.039 : 0.046 : 0.961 : -0.002 5699 : 0.038 : 0.038 : 0.966 : 0.005 Found the Attractive vector Found 202599 images. label: Mouth_Slightly_Open images : POS move : NEG move :distance : 𝛥 distance 230 : 1.119 : 1.083 : 1.692 : 1.692 469 : 0.581 : 0.64 : 1.389 : -0.303 691 : 0.399 : 0.382 : 1.261 : -0.129 937 : 0.281 : 0.235 : 1.167 : -0.093 1180 : 0.196 : 0.187 : 1.141 : -0.026 1418 : 0.155 : 0.174 : 1.111 : -0.031 1652 : 0.142 : 0.124 : 1.1 : -0.01 1890 : 0.128 : 0.103 : 1.081 : -0.019 2131 : 0.114 : 0.096 : 1.074 : -0.007 2367 : 0.093 : 0.087 : 1.067 : -0.007 2615 : 0.093 : 0.083 : 1.045 : -0.022 2873 : 0.081 : 0.075 : 1.04 : -0.006 3122 : 0.07 : 0.068 : 1.036 : -0.004 3355 : 0.06 : 0.062 : 1.035 : -0.001 3623 : 0.063 : 0.051 : 1.031 : -0.005 3879 : 0.06 : 0.056 : 1.027 : -0.004 4120 : 0.054 : 0.051 : 1.026 : -0.001 4356 : 0.051 : 0.047 : 1.016 : -0.01 4584 : 0.051 : 0.049 : 1.017 : 0.0 4807 : 0.043 : 0.043 : 1.009 : -0.008 5057 : 0.039 : 0.039 : 1.008 : -0.001 Found the Mouth_Slightly_Open vector Found 202599 images. label: Smiling images : POS move : NEG move :distance : 𝛥 distance 232 : 1.056 : 1.023 : 1.562 : 1.562 481 : 0.626 : 0.548 : 1.477 : -0.085 728 : 0.4 : 0.352 : 1.407 : -0.07 984 : 0.255 : 0.254 : 1.36 : -0.047 1231 : 0.206 : 0.178 : 1.314 : -0.046 1453 : 0.155 : 0.159 : 1.287 : -0.027 1669 : 0.133 : 0.136 : 1.277 : -0.01 1906 : 0.12 : 0.116 : 1.243 : -0.034 2151 : 0.097 : 0.101 : 1.235 : -0.008 2398 : 0.093 : 0.085 : 1.23 : -0.005 2625 : 0.089 : 0.091 : 1.23 : 0.0 2885 : 0.081 : 0.071 : 1.228 : -0.002 3127 : 0.069 : 0.073 : 1.227 : -0.0 3367 : 0.062 : 0.062 : 1.229 : 0.002 3626 : 0.06 : 0.064 : 1.224 : -0.005 3866 : 0.057 : 0.059 : 1.222 : -0.002 4070 : 0.051 : 0.057 : 1.216 : -0.007 4310 : 0.048 : 0.049 : 1.205 : -0.011 4559 : 0.048 : 0.049 : 1.202 : -0.003 4800 : 0.047 : 0.046 : 1.208 : 0.006 5036 : 0.043 : 0.042 : 1.206 : -0.002 5285 : 0.046 : 0.041 : 1.207 : 0.001 5533 : 0.042 : 0.038 : 1.207 : 0.0 5758 : 0.033 : 0.04 : 1.203 : -0.004 Found the Smiling vector Found 202599 images. label: Wearing_Lipstick images : POS move : NEG move :distance : 𝛥 distance 243 : 1.091 : 1.017 : 1.656 : 1.656 464 : 0.597 : 0.573 : 1.412 : -0.245 708 : 0.386 : 0.355 : 1.341 : -0.071 959 : 0.271 : 0.251 : 1.321 : -0.02 1212 : 0.199 : 0.188 : 1.294 : -0.027 1441 : 0.162 : 0.175 : 1.249 : -0.045 1670 : 0.132 : 0.133 : 1.237 : -0.012 1913 : 0.129 : 0.122 : 1.215 : -0.022 2148 : 0.107 : 0.099 : 1.215 : -0.0 2369 : 0.096 : 0.098 : 1.197 : -0.018 2617 : 0.089 : 0.08 : 1.193 : -0.004 2840 : 0.071 : 0.073 : 1.196 : 0.003 3085 : 0.072 : 0.069 : 1.191 : -0.006 3316 : 0.067 : 0.061 : 1.185 : -0.005 3556 : 0.063 : 0.062 : 1.19 : 0.004 3793 : 0.055 : 0.056 : 1.188 : -0.002 4037 : 0.063 : 0.048 : 1.184 : -0.004 4280 : 0.053 : 0.048 : 1.178 : -0.006 4499 : 0.049 : 0.047 : 1.179 : 0.001 4704 : 0.046 : 0.045 : 1.185 : 0.006 4940 : 0.041 : 0.044 : 1.182 : -0.003 5160 : 0.042 : 0.041 : 1.185 : 0.003 5408 : 0.043 : 0.039 : 1.188 : 0.003 5635 : 0.04 : 0.04 : 1.188 : 0.001 5866 : 0.041 : 0.036 : 1.188 : -0.001 Found the Wearing_Lipstick vector Found 202599 images. label: High_Cheekbones images : POS move : NEG move :distance : 𝛥 distance 227 : 1.166 : 1.003 : 1.723 : 1.723 453 : 0.724 : 0.61 : 1.31 : -0.414 672 : 0.357 : 0.379 : 1.194 : -0.115 906 : 0.261 : 0.244 : 1.162 : -0.032 1135 : 0.199 : 0.19 : 1.148 : -0.014 1360 : 0.189 : 0.166 : 1.14 : -0.008 1601 : 0.142 : 0.14 : 1.11 : -0.03 1817 : 0.124 : 0.128 : 1.078 : -0.032 2038 : 0.114 : 0.097 : 1.065 : -0.012 2289 : 0.105 : 0.08 : 1.049 : -0.017 2542 : 0.095 : 0.078 : 1.037 : -0.012 2776 : 0.08 : 0.071 : 1.032 : -0.004 3002 : 0.069 : 0.066 : 1.031 : -0.002 3228 : 0.072 : 0.072 : 1.027 : -0.004 3467 : 0.073 : 0.063 : 1.029 : 0.002 3698 : 0.055 : 0.057 : 1.03 : 0.001 3918 : 0.054 : 0.054 : 1.032 : 0.002 4149 : 0.056 : 0.046 : 1.033 : 0.001 4368 : 0.052 : 0.048 : 1.034 : 0.002 4577 : 0.043 : 0.043 : 1.025 : -0.009 4806 : 0.045 : 0.041 : 1.027 : 0.002 5032 : 0.043 : 0.046 : 1.018 : -0.009 5249 : 0.041 : 0.036 : 1.019 : 0.0 Found the High_Cheekbones vector Found 202599 images. label: Male images : POS move : NEG move :distance : 𝛥 distance 221 : 1.152 : 1.004 : 1.736 : 1.736 424 : 0.646 : 0.563 : 1.465 : -0.271 646 : 0.434 : 0.309 : 1.358 : -0.107 850 : 0.268 : 0.226 : 1.333 : -0.025 1069 : 0.233 : 0.182 : 1.289 : -0.044 1254 : 0.169 : 0.155 : 1.282 : -0.007 1462 : 0.162 : 0.128 : 1.27 : -0.012 1676 : 0.137 : 0.11 : 1.282 : 0.012 1875 : 0.111 : 0.099 : 1.288 : 0.006 2098 : 0.098 : 0.09 : 1.28 : -0.008 2313 : 0.089 : 0.079 : 1.27 : -0.01 2531 : 0.079 : 0.069 : 1.269 : -0.001 2765 : 0.082 : 0.062 : 1.267 : -0.002 2976 : 0.073 : 0.065 : 1.256 : -0.011 3172 : 0.067 : 0.054 : 1.252 : -0.004 3382 : 0.062 : 0.051 : 1.254 : 0.002 3585 : 0.063 : 0.052 : 1.251 : -0.002 3789 : 0.055 : 0.05 : 1.251 : 0.0 3998 : 0.053 : 0.043 : 1.251 : -0.0 4185 : 0.046 : 0.048 : 1.247 : -0.004 4388 : 0.049 : 0.041 : 1.255 : 0.008 4612 : 0.048 : 0.04 : 1.247 : -0.008 4825 : 0.041 : 0.033 : 1.245 : -0.002 Found the Male vector
eyeglasses_vec = get_vector_from_label('Eyeglasses', BATCH_SIZE)
Found 202599 images. label: Eyeglasses images : POS move : NEG move :distance : 𝛥 distance 36 : 2.66 : 0.673 : 2.737 : 2.737 66 : 1.524 : 0.469 : 2.245 : -0.492 104 : 1.063 : 0.258 : 2.04 : -0.205 129 : 0.621 : 0.189 : 1.921 : -0.119 163 : 0.571 : 0.143 : 1.79 : -0.131 196 : 0.452 : 0.111 : 1.713 : -0.078 222 : 0.337 : 0.103 : 1.699 : -0.014 251 : 0.334 : 0.084 : 1.683 : -0.016 276 : 0.267 : 0.076 : 1.656 : -0.027 302 : 0.249 : 0.068 : 1.629 : -0.027 340 : 0.267 : 0.064 : 1.6 : -0.03 366 : 0.192 : 0.054 : 1.568 : -0.031 398 : 0.195 : 0.053 : 1.584 : 0.015 435 : 0.219 : 0.048 : 1.581 : -0.003 459 : 0.167 : 0.044 : 1.591 : 0.01 496 : 0.176 : 0.04 : 1.582 : -0.009 530 : 0.156 : 0.039 : 1.587 : 0.004 563 : 0.152 : 0.036 : 1.569 : -0.018 597 : 0.147 : 0.036 : 1.533 : -0.036 626 : 0.114 : 0.037 : 1.529 : -0.004 650 : 0.101 : 0.033 : 1.514 : -0.016 675 : 0.103 : 0.03 : 1.531 : 0.017 703 : 0.109 : 0.028 : 1.553 : 0.022 734 : 0.113 : 0.028 : 1.533 : -0.019 763 : 0.101 : 0.026 : 1.529 : -0.004 790 : 0.097 : 0.024 : 1.528 : -0.001 826 : 0.106 : 0.024 : 1.528 : 0.0 865 : 0.108 : 0.023 : 1.524 : -0.004 898 : 0.092 : 0.021 : 1.518 : -0.006 935 : 0.091 : 0.02 : 1.525 : 0.007 969 : 0.09 : 0.022 : 1.531 : 0.006 1004 : 0.084 : 0.022 : 1.531 : -0.001 1026 : 0.059 : 0.02 : 1.526 : -0.005 Found the Eyeglasses vector
blonde_vec = get_vector_from_label('Blond_Hair', BATCH_SIZE)
Found 202599 images. label: Blond_Hair images : POS move : NEG move :distance : 𝛥 distance 73 : 1.967 : 0.683 : 2.162 : 2.162 161 : 1.097 : 0.444 : 1.754 : -0.408 231 : 0.556 : 0.295 : 1.689 : -0.065 317 : 0.47 : 0.199 : 1.619 : -0.07 386 : 0.346 : 0.145 : 1.612 : -0.007 458 : 0.262 : 0.124 : 1.596 : -0.015 529 : 0.253 : 0.1 : 1.547 : -0.049 600 : 0.206 : 0.088 : 1.53 : -0.018 675 : 0.19 : 0.079 : 1.495 : -0.034 737 : 0.157 : 0.071 : 1.509 : 0.014 818 : 0.172 : 0.06 : 1.496 : -0.014 882 : 0.123 : 0.06 : 1.499 : 0.004 957 : 0.133 : 0.053 : 1.513 : 0.013 1023 : 0.118 : 0.048 : 1.508 : -0.004 1096 : 0.11 : 0.045 : 1.496 : -0.013 1163 : 0.105 : 0.047 : 1.495 : -0.001 1243 : 0.106 : 0.044 : 1.5 : 0.005 1311 : 0.086 : 0.04 : 1.499 : -0.001 1390 : 0.093 : 0.039 : 1.49 : -0.009 1458 : 0.082 : 0.036 : 1.486 : -0.004 1540 : 0.079 : 0.035 : 1.485 : -0.001 1596 : 0.067 : 0.034 : 1.482 : -0.003 1673 : 0.068 : 0.029 : 1.474 : -0.008 1756 : 0.073 : 0.028 : 1.466 : -0.008 1834 : 0.064 : 0.026 : 1.457 : -0.009 1899 : 0.056 : 0.027 : 1.452 : -0.005 1961 : 0.06 : 0.028 : 1.456 : 0.004 2035 : 0.063 : 0.027 : 1.451 : -0.006 2113 : 0.053 : 0.024 : 1.448 : -0.003 Found the Blond_Hair vector
print('Attractive Vector')
add_vector_to_images(attractive_vec)
print('Mouth Open Vector')
add_vector_to_images(mouth_open_vec)
print('Smiling Vector')
add_vector_to_images(smiling_vec)
print('Lipstick Vector')
add_vector_to_images(lipstick_vec)
print('Young Vector')
add_vector_to_images(young_vec)
print('Male Vector')
add_vector_to_images(male_vec)
print('Eyeglasses Vector')
add_vector_to_images(eyeglasses_vec)
print('Blond Vector')
add_vector_to_images(blonde_vec)
Attractive Vector
Mouth Open Vector
Smiling Vector
Lipstick Vector
Young Vector
Male Vector
Eyeglasses Vector
Blond Vector
def morph_faces(start_image_file, end_image_file):
factors = np.arange(0,1,0.1)
att_specific = att[att['image_id'].isin([start_image_file, end_image_file])]
att_specific = att_specific.reset_index()
data_flow_label = imageLoader.build(att_specific, 2)
example_batch = next(data_flow_label)
example_images = example_batch[0]
example_labels = example_batch[1]
z_points = vae.encoder.predict(example_images)
fig = plt.figure(figsize=(18, 8))
counter = 1
img = example_images[0].squeeze()
sub = fig.add_subplot(1, len(factors)+2, counter)
sub.axis('off')
sub.imshow(img)
counter+=1
for factor in factors:
changed_z_point = z_points[0] * (1-factor) + z_points[1] * factor
changed_image = vae.decoder.predict(np.array([changed_z_point]))[0]
img = changed_image.squeeze()
sub = fig.add_subplot(1, len(factors)+2, counter)
sub.axis('off')
sub.imshow(img)
counter += 1
img = example_images[1].squeeze()
sub = fig.add_subplot(1, len(factors)+2, counter)
sub.axis('off')
sub.imshow(img)
plt.show()
start_image_file = '000238.jpg'
end_image_file = '000193.jpg' #glasses
morph_faces(start_image_file, end_image_file)
Found 2 images.
start_image_file = '000112.jpg'
end_image_file = '000258.jpg'
morph_faces(start_image_file, end_image_file)
Found 2 images.
start_image_file = '000230.jpg'
end_image_file = '000712.jpg'
morph_faces(start_image_file, end_image_file)
Found 2 images.