1、确定目标(分割mask ---> 动漫人脸)

2、确定技能路线(语义分割 + 语义合成)

3、实现(数据集标注 + 模型调优 + 界面编写)

PS:原作者并没有开源数据集和代码, 不过给了所有参考资料的源码和数据集链接!
复现该当没有问题

瓜分mask生成动漫人脸爆肝数周从零搭建

目标

该项目的目标是建立一个深度学习模型,从分割mask天生动漫人脸肖像。

segmentation mask to anime face portrait

在这个项目中,首先手动标注一小批图像
然后利用数据增强和 U-Net 模型来乘以分割mask的数量来构建数据集。
末了,演习一个 GauGAN 模型,用于从分割mask中合成动漫人脸。

1. 语义分割

语义分割是为图像中的每个像素分配标签(也称为类 id)的过程。
它的结果是一个分割mask,它是一个大小为高度 宽度的数组,每个像素都包含一个类 ID。

class id: 0 = background, 5 = hair

1.1 Dataset

在进入图像天生任务之前,我们须要一个分割mask数据集,用于演习天生模型将mask转换为图像。

不幸的是,我在互联网上找不到任何动漫人脸分割数据集。
只管如此,Danbooru2019-Portraits 上有一个动漫肖像(512 x 512px)数据集。
以是我决定从 Danbooru 肖像中标注的分割mask。

数据集链接:https://www.gwern.net/Crops#danbooru2019-portraits

1.2 Annotation

要标注图像,我们必须确定类。
最初的想法是列出 15 个类:

background, body, ear, face, eyeball, pupil, eyelash, nose, mouth, hair, hair_accessory, eyebrow, glasses, clothes, hand

后来为了大略起见,将其缩减为 7 个类,终极的类列表如下:

background, skin, face, eye, mouth, hair, clothes

有许多不同的注释工具,这里利用的是 labelme。

https://github.com/wkentaro/labelme

labelme GUI

在这项乏味的事情上费力事情数周后,设法标注了 200 张图像

examples of annotated masks

left: original image, middle: segmentation mask, right: visualization of the annotation

1.3 Data Augmentation

当然,200 张带注释的图像不敷以让我们演习我们的网络。
我们须要利用数据增强技能来增加数据集的大小。

通过随机旋转、镜像和扭曲图像,我从这 200 个样本中天生了 3000 多个数据。
换句话说,现在我有 3200 个数据。

examples of augmented masks

然而,这些数据在内容和风格方面高度重复,由于它们仅从 200 个样本中扩充而来。
为了演习网络将分割掩码转换为高质量和多样化的动漫面孔,我们须要的不仅仅是 200 + 3000 个数据点。
因此,我将首先利用这些数据来演习一个 U-Net 模型来学习从动漫人脸到分割掩码的翻译。
然后我会将全体 Danbooru 肖像数据集输入到经由演习的 U-Net 模型中,以天生更多不同人脸的分割掩码。

anime face portraits to segmentation mask

1.4 U-Net

U-Net 最初是为了分割医学图像进行诊断而引入的。
它通过利用跳跃连接来办理传统 FCN(全卷积网络)中发生的信息丢失问题,在精确分割方面做得非常好。

U-Net 的架构与 Autoencoder 相似,但从下采样端到上采样端有额外的连接层。

source: https://arxiv.org/abs/1505.04597

不才采样部分,我利用预演习的 MobileNetV2 从输入图像中提取特色。
在上采样部分,我利用了由 Conv2DTranspose、Batchnorm 和 ReLU 层组成的块。

U-Net v1, v2 architecture

在我的 U-Net 版本 1 中,输入和输出大小为 128 x 128px。
经由演习的模型确实学习了从动漫人脸到分割mask的非常好的映射。
但由于我想在我后来的合成模型中拥有 512 x 512px 的输入和输出,我将 U-Net 输出的大小调度为 512 x 512px 并进行插值。
然而,结果看起来是像素化的,它未能捕捉到涌如今小区域(例如嘴巴)中的某些种别。

在版本 2 中,我只是将输入和输出大小变动为 512 x 512px(我一开始并没有这样做,由于我不肯望输出喧华并在图像中令人困惑的区域中添补随机点,例如 衣服)。
正如我所料,v2 的输出很喧华。
不过,它们看起来比 v1 更好。

U-Net v3 architecture

在版本 3 中,我考试测验通过用 UpSampling2D 层更换 Conv2DTranspose 层来减轻噪音和棋盘伪影。
现在的结果比 v2 的要好得多。
噪音更少,棋盘伪影更少。

checkerboard artifacts of v2

U-Net segmentation results

末了,我将全体 Danbooru 数据集输入 U-Net v3 以构建我的分割掩码数据集。

2.图像语义合成

现在,我们有了分割蒙版数据集,是时候深入研究紧张任务——图像语义合成,正如之前所说,这不过是从分割mask到真实图像的转换的一个花哨的名称。

Semantic Image Synthesis: segmentation mask to anime face portrait

2.1 GauGAN

source: https://github.com/NVlabs/SPADE

GauGAN 由 Nvidia 开拓,用于从分割mask合成逼真的图像。
在他们的展示网站上,他们展示了 GauGAN 如何出色地通过几笔画来天生逼真的风景图像。

demo链接:https://www.nvidia.com/en-us/research/ai-playground/

GauGAN architecture

上图展示了 GauGAN 模型的架构。
绿色块完备代表发电机。
鉴别器是一个 PatchGAN。

2.2 SPADE

source: https://nvlabs.github.io/SPADE/

GauGAN 的核心是 SPADE(Spatially-Adaptive Denormalization)模块,它是从 Batch Norm 修正而来的归一化层。
它旨在战胜 pix2pixHD 中的寻衅:在具有统一类 ID 的大区域丢失语义信息。

这是通过将 Conv 层引入Batch Norm来办理的,这样它具有不同的参数集(β,γ),这些参数以分割mask为条件,并且会随着不同的区域而变革。
这意味着 SPADE 许可天生器在统一标签区域中学习更多细节。

因此,在我们的问题中,天生的图像可能如下所示:

2.3 Pretrained Encoder

encoder 实际上是可选的,由于可以直接从高斯分布中采样 z(潜在向量)而无需任何输入(就像 vanilla GAN)。
这里利用了encoder ,由于我想用参考图像对天生的图像进行样式设置。

VAE architecture

由于与encoder一起演习 GauGAN 是不稳定的,须要更多的韶光和资源,以是我提前利用 VAE 演习了我的编码器,然后在 GauGAN 模型的演习过程中利用预演习的encoder对 z 进行采样。

2.4 Results

以下是从不同的分割mask和参考图像天生的图像的结果。

semantic image synthesis results

2.5 Latent Attribute Vectors

除了利用参考图像来掌握输出图像的风格外,我们还可以直接操纵潜在向量 z 来做到这一点。
为此,我们首先须要找出潜在空间中的属性向量。

动漫角色面部最主要的属性之一是头发颜色。
但是,由于数据集没有带有头发颜色的标签,我必须自己利用 i2v 来标记它们,i2v 是一个用于估计插图标签的库。
然后,我们可以通过利用 t-SNE 将样本图像的潜在向量投影到 2D 空间来可视化潜在空间以及估计的标签。

t-SNE of 4000 samples (estimated hair colors are indicated by image border colors)

末了,通过打算不同标签的潜在向量之间的间隔和方向,我们可以得到属性向量。
下面的动画演示了利用提取的属性向量在头发颜色之间进行的转换。

,时长00:11

3. GUI

利用 python tkinter 库创建了一个 GUI,用于编辑天生的图像和分割mask。
以下是演示视频:

,时长04:21

4. 总结

这个项目还有改进的空间,尤其是语义分割模型(U-Net)和语义图像合成模型(GauGAN)。
以下是未来要做的事情的清单:

探求更好的模型架构以从原始图像中得到更准确的分割掩码改进 GauGAN 模型以肃清头发区域涌现的噪声演习天生模型以天生随机分割mask