上一节我们通过VAE网络完成了人脸生成效果。VAE网络一个特性是会把人脸编码成一个含有200个分量的向量,反过来说在特定分布范围内的含有200个分量的向量就对应一张人脸。由于向量之间可以进行运算,这就意味着我们把两张不同人脸A,B分布转换成两个不同向量z_A,z_B,然后我们使用向量运算例如z_AB = z_A *(1 - alpha) + z_B *alpha,就能将两个向量以一定比例合成一个新向量,该新向量就会对应一个人脸,而且这个人脸就会同时具有人脸A和B的特点,如果我们增大参数alpha,那么生成向量对应的人脸特征就会更像人脸B,如果我们减少alpha的值,生成向量对应的人脸就更像人脸A.
接下来我们看看如何实现人脸的转变特效,首先我们先出数据图片中选出具有特定特征的人脸图片,例如”戴墨镜“,然后使用编码器得出”戴墨镜“人脸图片的特征向量,然后我们再选取不带墨镜的人脸图片,计算其特征向量,然后使用向量运算将两个向量结合起来,这样我们就能把后面不带墨镜的人脸转换成带墨镜的模样。
我们看看相应代码实现:
def morph_faces(start_image_file, end_image_file):
alpha = np.arange(0, 1, 0.1)
atttribute_specific = att[att['image_id'].isin([start_image_file, end_image_file])]
att_specific = atttribute_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_vectors = vae.encoder.predict(example_images)#获得人脸图像的关键向量
fig = plt.figure(figsize = (18, 8))
counter = 1
img = example_images[0].squeeze()
sub = fig.add_subplot(1, len(alpha) + 2, counter)
sub.axis('off')
sub.imshow(img)
counter += 1
for factor in alpha: #通过变化参数让一个向量滑向另一个向量
changed_z_vector = z_vectors[0] * (1 - factor) + z_vectors[1] * factor
changed_image = vae.decoder.predict(np.array([changed_z_vector]))[0] #根据新向量绘制人脸图像
img = changed_image.squeeze()