提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
Ganimation :通过动作单元(Action Units )操纵人脸表情
ECCV2018
以面部动作单元(AU)和单独图片为输入的条件GAN
通过类似cycleGAN的思想实现无监督学习
数据集准备(git里vipermu的数据集au是错的,需要自己生成au)
CelebA
–image_dir 图像目录
通过Openface处理人脸图像得到包含对应表情landmarks的文件
–attr_path 图像对应表情向量
项目目录
# 目录
-ganimation-master
-----config.py #参数设置
-----data_loader.py #数据集加载
-----logger.py #记录参数
-----main.py #主函数
-----model.py #模型
-----solver.py #操作
-----utils.py #相关用法
-----experiments #训练过程中保存log、models的地址
-----data #存放数据集
-----animations #存放animation操作需要的参考图像、参考表情向量
#animation的输入图像以及操作输出图像
使用方法(切换至适配的虚拟环境)
1.训练(train)
python main.py --mode train
2.表情编辑(animation)
python main.py --mode animation
model.py 模型定义
初始化权重与定义残差模块
class BaseNetwork(nn.Module): #初始化权重
def __init__(self):
super(BaseNetwork, self).__init__()
def init_weights(self):
self.apply(self._weights_init_fn)
def _weights_init_fn(self, m):
classname = m.__class__.__name__
if classname.find('Conv') != -1:
m.weight.data.normal_(0.0, 0.02)
if hasattr(m.bias, 'data'):
m.bias.data.fill_(0)
elif classname.find('BatchNorm2d') != -1:
m.weight.data.normal_(1.0, 0.02)
m.bias.data.fill_(0)
class ResidualBlock(BaseNetwork):
"""Residual Block with instance normalization.定义两层卷积结构的残差模块"""
def __init__(self, dim_in, dim_out):
super(ResidualBlock, self).__init__()
self.main = nn.Sequential(
nn.Conv2d(dim_in, dim_out, kernel_size=3,
stride=1, padding=1, bias=False),
nn.InstanceNorm2d(dim_out, affine=True, track_running_stats=True),
nn.ReLU(inplace=True),
nn.Conv2d(dim_out, dim_out, kernel_size=3,
stride=1, padding=1, bias=False),
nn.InstanceNorm2d(dim_out, affine=True, track_running_stats=True))
self.init_weights()
def forward(self, x):
return x + self.main(x)
Generator生成器模型
提取特征的部分:先经过一个77的大卷积核并将通道数变为64,然后两次下采样,经过6个连续的残差模块提取特征后再两次上采样恢复分辨率。
head部分有两个:color map部分、attention模块:两个head都是有77的反卷积恢复到图像原本分辨率,再经过激活函数得到回归结果
class Generator(BaseNetwork):
"""Generator network."""
def __init__(self, conv_dim=64, c_dim=5, repeat_num=6):
super(Generator, self).__init__()
layers = []
layers.append(nn.Conv2d(3+c_dim, conv_dim, kernel_size=7, #大卷积核展宽通道到64
stride=1, padding=3, bias=False))
layers.append(nn.InstanceNorm2d(
conv_dim, affine=True, track_running_stats=True))
layers.append(nn.ReLU(inplace=True))
self.debug1 = nn.Sequential(*layers)
# Down-sampling layers.
curr_dim = conv_dim
for i in range(2): #两次下采样
layers.append(nn.Conv2d(