轻轻松松使用StyleGAN(五):提取真实人脸特征码的一些探索

时间:2024-05-23 10:25:54

我们在上一篇文章中提到:能不能给出一个目标图像,使用神经网络自动提取出它的特征码呢?

如果可以,那么我们就可以方便地对这些图像进行编辑,创造出各种各样“酷炫”的风格人像。

这个工作可以分为两步:

(1)先利用StyleGAN生成的特征码和生成的人脸图像训练一个网络,把人脸图像作为输入,把特征码作为输出,理论上可以得到一个StyleGAN的逆向网络模型,如果训练成功的话,这个模型可以自动将人脸图像转换为特征码;

(2)利用真实人脸图像对上面得到的模型进行进一步训练和“微调”,使之能够用于真实人脸的特征码提取。

我们已经完成了第一步的工作,内容请参考:

https://blog.****.net/weixin_41943311/article/details/102370766

但是,在进行第二步工作时,遇到了很大的困扰,如何做进一步的训练和“微调”呢?我做了一些尝试,基本上都失败了,现在把结果写在下面(但是,在最后,我们找到了新的用于解决这个问题的开源项目!):

(0)我们有StyleGAN和经过训练后的人脸生成模型 karras2019stylegan-ffhq-1024x1024.pkl ;我们也构造了StyleGAN的逆向网络lotus,并且lotus经过训练优化后的accuracy = 0.9501;用lotus生成的人脸图片的dlatents,再次使用StyleGAN,其生成的人脸图片与原始图片具有高度的相似性;

(1)能否按照“真实人脸-->lotus-->dlatents-->StyleGAN-->生成图片”的顺序构造一个可训练的神经网络(其中:StyleGAN使用经过训练后的人脸生成模型 karras2019stylegan-ffhq-1024x1024.pkl 且保持不变,把生成图片和真实人脸转换为向量作为X_train、Y_train并比较它们的差异(mean_squared_erro)),然后训练这个网络,得到一个适用于真实人脸图片的新lotus模型呢?

事实证明这样是行不通的,keras和tensorflow不支持在训练模型中再包含一个其他的神经网络,无论是把这个神经网络放在keras.Model()里,还是把这个神经网络放到自定义的loss函数里,在model.compile()时都会报错;

(2)换一个思路,我从网上下载了一些真实人脸的图片,试图在已达到accuracy = 0.9501的基础上进一步训练lotus,但训练时得到的accuracy始终低于2%,说明真实人脸图片与StyleGAN生成的人脸图片有着十分巨大的差别,无法利用已训练好的lotus进一步优化模型;

(3)能否利用“相似-逼近”的方法找到真实人脸的dlatents?即:先将真实人脸图片通过lotus生成dlatents_0,dlatents_0可以用 Gs.components.synthesis.run() 方法生成图片picture_0;picture_0通过lotus生成dlatents_1,dlatents_1可以与dlatents_0交换或混合部分数据(可以考虑用算术加权平均法或相乘再开方法来混合),然后用 Gs.components.synthesis.run() 方法生成picture_1;picture_1通过lotus生成dlatents_2,第dlatents_2可以继续与dlatents_0交换或混合部分数据,然后用 Gs.components.synthesis.run() 方法生成picture_2;......;由于每次交换或混合时,都是与dlatents_0进行运算,是否能让最终生成的picture_n接近真实人脸?

事实上,这个猜想是错的,最终生成的图片picture_n只是无限接近图片picture_0而已;

(4)能否利用“差值预测”的方式修正dlatents来得到真实人脸的dlatents?如下图所示:

轻轻松松使用StyleGAN(五):提取真实人脸特征码的一些探索

假设:dlatents = w * picture + b

则:delta(dlatents) = w * delta(picture),所以:w = delta(dlatents)/delta(picture)

当有一组dlatents和picture数据时,w = delta(dlatents)/delta(picture)求和并取平均值;为提高预测的可信度,可以打乱求差值的两个节点的顺序,dlatents之间直接用向量求差值,picture之间可以用mean_squared_erro来求差值

同时由于,dlatents_0 - X = w * (picture_0 - 真实人脸)

则:X = dlatents_0 - w * (picture_0 - 真实人脸)

我按这个思路设计了程序,可惜,得到的结果X对应的图片仍然是非常接近picture_0。

简单看了一下数据, (picture_0 - 真实人脸)的差值显著高于(picture_n - picture_m),说明真实人脸图片的数据分布特点与StyleGAN生成的人脸数据有着很大的差别。

既然上面四个方法都行不通(也许是具体的工作细节有问题,请高手指正~),那只能换一个思路了!

那就是:

  • 随机初始化一个latent code 并且使用梯度下降的方法去优化它

在 github.com 上有这样的开源项目,我们需要花一点时间来研究一下这个方案,即:stylegan-encoder,它能够实现的效果如下图所示:

轻轻松松使用StyleGAN(五):提取真实人脸特征码的一些探索

(完)