人脸漫画合成
简单记录一下我的毕业设计。
任务
给定一张人脸图像,把它转化成日本动漫的风格。
数据集
人脸数据集:CelebAMask-HQ是一个大型的人脸图像数据集,它有30,000张高分辨率的人脸图像,下载地址:https://github.com/switchablenorms/CelebAMask-HQ
动漫数据集:Danbooru ,有14,000张裁剪好的动漫头像,下载地址: https://www.kaggle.com/lukexng/animefaces-512x512
网络结构
主要借鉴了 CycleGAN。网络有两个生成器,两个判别器,在生成器的输入加入了face-parsing,更改了判别器。符号意义如下:
domain A:人脸 domain B:动漫
Generators: G_A: A -> B;实现从人脸到动漫的迁移 G_B: B -> A 实现从动漫到人脸的迁移
Discriminators: D_A: G_A(A) vs. B; 判断是真实动漫还是生成的假动漫 D_B: G_B(B) vs. A判断是真实人脸还是生成的假人脸
A->B方向网络示意图如下:
B->A类似,不再赘述。
生成器
网络结构没有改动:卷积->上采样*2->resnet _block*9->下采样*2->卷积
输入从3通道变为6通道(photo+face-parsing or anime+face-parsing):face-parsing代表了人脸五官的结构,可以指导生成,降低不配对任务的难度
判别器
改进版PatchGAN的D,将30个patch改为35个,考虑到动漫和人脸在五官比例上是不对应的,比如动漫中的大眼睛、小鼻子,所以这个任务要允许一定变形,要求生成的人脸和人脸解析完全对应反而达不到动漫的效果 。因此,判别器的输入还是三通道,只用判断真假,判别器结构示意图如下:
损失函数
对抗损失:让生成的图片接近真实图片的分布
循环一致性损失:保持内容不变
总损失:
实验设置
数据集制作
为了在CycleGAN上运行我们自己的数据集,要实现一个dataset
类并修改train.py
,具体做法见代码。
选取了12,000张人脸,28,000张动漫,将人脸图片用BiSeNet进行处理,得到相应的face-parsing结果。然后按8:2的比例划分了训练集与测试集。
实验参数
大部分都是CycleGAN论文里的设置。
试验结果
由于设备和时间的限制,只跑了25个epoch,效果还行就没再训练了,多跑几个epoch应该会有更好的效果。
可以看到,由于face-parsing的输入,生成的图片和人脸在五官位置上还是比较对应的,风格也比较接近动漫,但细节部分还不够好,尤其是鼻子和嘴巴,猜想是因为日本动漫对鼻子和嘴巴的勾勒本来就比较钱,再加上训练次数不够,导致了此问题。未来可以考虑加入注意力机制以提升合成图片的质量。
侧脸、戴帽子等遮挡难度还是比较大,还有一些莫名失败的例子。
一些数据集中没有的,如胡子、眼镜、手指,生成的动漫勉强可以接受。
遇到的一些问题
1.多线程问题
最开始在自己的电脑上测试代码,报错:
CUDA out of memory. Tried to allocate 784.00 MiB (GPU 0; 4.00 GiB total capacity; 456.81 MiB already allocated; 2.47 GiB free; 548.00 MiB reserved in total by PyTorch)
可以看到内存是够用的却不分配,后发现是多线程的问题,num_threads=0解决。
2.D的损失突然接近0,生成图片只剩纹理图
之前以为是学习率太大了,调小后跑了几个epoch还是会出现这种情况。根本原因在于D的性能太好了,生成器学不到什么东西,改进D后这种状况消失了。
3.一些失败的尝试
这里的代码或多或少有点问题,不过还是记录一下。