在前面的文章里,我们可以利用StyleGAN创建令人惊讶的黄种人脸和专属于自己的老婆动漫头像,内容请参考:
https://blog.csdn.net/weixin_41943311/article/details/100539707
并且,我们知道,可以对特征码进行混合与编辑,改变这些人脸和动漫头像的风格,内容请参考:
https://blog.csdn.net/weixin_41943311/article/details/100694599
那么,能不能给出一个目标图像,使用神经网络自动提取出它的特征码呢?
如果可以,那么我们就可以方便地对这些图像进行编辑,创造出各种各样“酷炫”的风格人像。
这个工作可以分为两步:
(1)先利用StyleGAN生成的特征码和生成的人脸图像训练一个网络,把人脸图像作为输入,把特征码作为输出,理论上可以得到一个StyleGAN的逆向网络模型,如果训练成功的话,这个模型可以自动将人脸图像转换为特征码;
(2)利用真实人脸图像对上面得到的模型进行进一步训练和“微调”,使之能够用于真实人脸的特征码提取。
这篇文章先说明第一步的工作。
我们构造了一个如下图所示的神经网络,并计划对它进行训练。这个网络的输入为256x256的图片,输出为18x512的dlatents(StyleGAN的中间数据层,即:w)
构建这个模型的代码如下,我们这里把这个模型叫做lotus_body():
# 定义StyleGAN的逆向网络模型lotus
# 下面的功能函数均使用keras原生函数构造
def lotus_body(x):
# input: (none, 256, 256, 3), output: (none, 8, 8,2048)
# 必须设定include_top=False, weights=None, 才能将输入设为256x256x3
# resnet输出C5,C5的shape是(none, 8, 8, 2048)
resnet = keras.applications.resnet50.ResNet50(include_top=False, weights=None, input_tensor=x, input_shape=(256,256,3))
y = resnet.output
print('ResNet50 C5 shape : ', y.shape)
# output: (none, 8, 8, 144)
# 输出feature maps = filters = 144, 2D卷积输出的高和宽8 - 1 + 1 = 8
y = keras.layers.convolutional.Conv2D(144, (1, 1), padding='same', activation='relu')(y)
# output: (none, 96, 96)
y = keras.layers.Reshape((96, 96))(y)
for i in range(3):
# output: (none, 96, 96)
# 输出feature maps = filters = 96, 1D卷积输出的长度96 - 1 + 1 = 96
y = keras.layers.local.LocallyConnected1D(96, 1)(y)
# output: (none, 96, 96),(2,1)代表将输入的第二个维度重拍到输出的第一个维度,而将输入的第一个维度重排到第二个维度
y = keras.layers.Permute((2, 1))(y)
# output:(none, 96, 96)
y = keras.layers.local.LocallyConnected1D(96, 1)(y)
# output: (none, 18, 512)
y = keras.layers.Reshape((18, 512))(y)
print('lotus body output shape : ', y.shape)
return y
为了训练这个模型,我们用StyleGAN生成了1200个dlatents以及它们所对应的人脸图片,并记录到文件中,训练时我们从文件中加载数据,并训练lotus模型。
由于lotus模型输出的不是目标的分类,而是18x512的张量,因此我们使用mean_squared_error作为损失函数loss,优化器(optimizer)使用的是adam,epochs = 503,batch_size = 6,最后训练得到的accuracy = 0.8933。
我们用StyleGAN生成了1280个dlatents以及它们所对应的人脸图片,使用mean_squared_error作为损失函数loss,优化器(optimizer)使用的是adam,epochs = 599,batch_size = 8,最后训练得到的accuracy = 0.9201。
完整的lotus网络模型训练及生成测试样片的源代码如下(带中文注释):