1.研究背景

随着互联网的发展与移动设备的普及,越来越多的人在社交媒体上分享个人图像。人像摄影流行的同时促进了人脸图像编辑技术的快速发展。传统的人脸图像编辑技术包括添加面部装饰(如眼镜、胡子)以及修饰容颜。基于生成对抗网络的人脸图像编辑方法能够改变人脸的固有属性(如年龄、性别)。人脸图像的年龄属性编辑技术在娱乐社交、影视媒体和智能安防等领域有着良好的应用前景和价值,能够广泛应用于人脸特效制作、帮助寻找失踪儿童、跨年龄段的人脸识别数据合成等任务。

2.图片演示

3.视频演示

改进StyleGANv2的容貌年龄预测系统(源码&教程)_哔哩哔哩_bilibili

4.StyleGAN2介绍

StyleGAN2 的出现当然是因为StyleGAN存在瑕疵,少量生成的图片有明显的水珠,这个水珠也存在于feature map上,如下图:

导致水珠的原因是 Adain 操作,Adain对每个feature map进行归一化,因此有可能会破坏掉feature之间的信息。emmmm,懵懵懂懂,最重要的是实验证明 当去除Adain的归一化操作后,水珠就消失了,所以Adain就背锅吧。
上面两张图说明了从 styleGAN 到 styleGAN2 ,在网络结构上的变换,去除normalization之后水珠消失了,但是styleGAN的一个亮点是 style mixing,仅仅只改网络结构,虽然能去除水珠,但是无法对style mixing 有 scale-specific级别的控制。

5.StyleGAN2 的改进点

AdaIN

StyleGAN第一个版本提出了通过AdaIN模块来实现生成,这个模块非常好也非常妙。

权重解调

虽然我们修改了网络结构,去除了水滴问题,但是styleGAN的目的是对特征实现可控的精细的融合。

StyleGAN2说,style modulation可能会放大某些特征的影像,所以style mixing的话,我们必须明确的消除这种影像,否则后续层的特征无法有效的控制图像。如果他们想要牺牲scale-specific的控制能力,他们可以简单的移除normalization,就可以去除掉水滴伪影,这还可以使得FID有着微弱的提高。现在他们提出了一个更好的替代品,移除伪影的同时,保留完全的可控性。这个就是weight demodulation。

我们继续看这个图:

里面包含三个style block,每一个block包含modulation(Mod),convolution and normalization。

modulation可以影响着卷积层的输入特征图。所以,其实Mod和卷积是可以继续宁融合的。比方说,input先被Mod放大了3倍,然后在进行卷积,这个等价于input直接被放大了3倍的卷积核进行卷积。Modulation和卷积都是在通道维度进行操作。所以有如下公式:

接下来的norm部分也做了修改:

这里替换了对特征图做归一化,而是去卷积的参数做了一个归一化,先前有研究提出,这样会有助于GAN的训练。
至此,我们发现,Mod和norm部分的操作,其实都可以融合到卷积核上。

class GeneratorBlock(nn.Module):def __init__(self, latent_dim, input_channels, filters, upsample = True, upsample_rgb = True, rgba = False):super().__init__()self.upsample = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=False) if upsample else Noneself.to_style1 = nn.Linear(latent_dim, input_channels)self.to_noise1 = nn.Linear(1, filters)self.conv1 = Conv2DMod(input_channels, filters, 3)self.to_style2 = nn.Linear(latent_dim, filters)self.to_noise2 = nn.Linear(1, filters)self.conv2 = Conv2DMod(filters, filters, 3)self.activation = leaky_relu()self.to_rgb = RGBBlock(latent_dim, filters, upsample_rgb, rgba)def forward(self, x, prev_rgb, istyle, inoise):if exists(self.upsample):x = self.upsample(x)inoise = inoise[:, :x.shape[2], :x.shape[3], :]noise1 = self.to_noise1(inoise).permute((0, 3, 2, 1))noise2 = self.to_noise2(inoise).permute((0, 3, 2, 1))style1 = self.to_style1(istyle)x = self.conv1(x, style1)x = self.activation(x + noise1)style2 = self.to_style2(istyle)x = self.conv2(x, style2)x = self.activation(x + noise2)rgb = self.to_rgb(x, prev_rgb, istyle)return x, rgb

可以发现,这个噪音也会经过Linear层的简单变换,然后里面加入了残差。为什么要输出rgb图像呢?这个会放在下次,或者下下次的内容。styleGAN1是需要用progressive growing的策略的,而StyleGAN2使用新的架构,解决了这种繁琐的训练方式。

6.代码实现

def get_lr(t, ts, initial_lr, final_lr):alpha = pow(final_lr/initial_lr, 1/ts)**(t*ts)return initial_lr * alphadef project(imgs: List[PIL.Image.Image],masks: List[PIL.Image.Image] = None,generator = None,pSp = None,ckpt: arg_type(str, help="path to the model checkpoint") = None,model_type: arg_type(str, help="inner model type. `ffhq-config-f` for default genrator and `ffhq-inversion` for pSp") = None,size: arg_type(int, help="original output image resolution") = 1024,style_dim: arg_type(int, help="dimensions of style z") = 512,n_mlp: arg_type(int, help="the number of multi-layer perception layers for style z") = 8,channel_multiplier: arg_type(int, help="channel product, affect model size and the quality of generated pictures") = 2,start_lr: arg_type(float, help="learning rate at the begin of training") = 0.1,final_lr: arg_type(float, help="learning rate at the end of training") = 0.025,latent_level: arg_type(List[int], help="indices of latent code for training") = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17],step: arg_type(int, help="optimize iterations") = 100,mse_weight: arg_type(float, help="weight of the mse loss") = 1,no_encoder: arg_type('project:no_encoder', action="store_true", help="disable to use pixel2style2pixel model to pre-encode the images") = False,
):n_mean_latent = 4096transform = transforms.Compose([transforms.Resize(256),transforms.CenterCrop(256),transforms.Transpose(),transforms.Normalize([127.5, 127.5, 127.5], [127.5, 127.5, 127.5]),])_imgs = []_masks = []if masks is None:masks = [Image.new(mode='L', size=img.size, color=255) for img in imgs]for img, mask in zip(imgs, masks):assert isinstance(img, PIL.Image.Image) and isinstance(mask, PIL.Image.Image)img = paddle.to_tensor(transform(img))mask = (paddle.to_tensor(transform(mask.convert('RGB')))[:1] + 1) / 2_imgs.append(img)_masks.append(mask)imgs = paddle.stack(_imgs, 0)masks = paddle.stack(_masks, 0)percept = lpips.LPIPS(net='vgg')percept.train() # on PaddlePaddle, lpips's default eval mode means no gradients.if generator is not None:no_encoder = Trueif pSp is None:no_encoder = Falseif no_encoder:generator = generator if generator is not None else get_generator(weight_path=None if ckpt is None else ckpt,model_type='ffhq-config-f' if model_type is None else model_type,size=size,style_dim=style_dim,n_mlp=n_mlp,channel_multiplier=channel_multiplier)# generator.eval() # on PaddlePaddle, model.eval() means no gradients.with paddle.no_grad():noise_sample = paddle.randn((n_mean_latent, style_dim))latent_out = generator.style(noise_sample)latent_mean = latent_out.mean(0)latent_in = latent_mean.detach().clone().unsqueeze(0).tile((imgs.shape[0], 1))latent_in = latent_in.unsqueeze(1).tile((1, generator.n_latent, 1)).detach()else:pSp = pSp if pSp is not None else get_pSp(weight_path=None if ckpt is None else ckpt,model_type='ffhq-inversion' if model_type is None else model_type,size=size,style_dim=style_dim,n_mlp=n_mlp,channel_multiplier=channel_multiplier)# pSp.eval() # on PaddlePaddle, model.eval() means no gradients.generator = pSp.decoderwith paddle.no_grad():_, latent_in = pSp(imgs, randomize_noise=False, return_latents=True)latent_in = latent_in.detach().clone()var_levels = list(latent_level)const_levels = [i for i in range(generator.n_latent) if i not in var_levels]assert len(var_levels) > 0if len(const_levels) > 0:latent_fix = latent_in.index_select(paddle.to_tensor(const_levels), 1).detach().clone()latent_in = latent_in.index_select(paddle.to_tensor(var_levels), 1).detach().clone()latent_in.stop_gradient = Falseoptimizer = optim.Adam(parameters=[latent_in], learning_rate=start_lr)frames = []pbar = tqdm(range(step))latent_n = latent_infor i in pbar:t = i / steplr = get_lr(t, step, start_lr, final_lr)optimizer.set_lr(lr)if len(const_levels) > 0:latent_dict = {}for idx, idx2 in enumerate(var_levels):latent_dict[idx2] = latent_in[:,idx:idx+1]for idx, idx2 in enumerate(const_levels):latent_dict[idx2] = (latent_fix[:,idx:idx+1]).detach()latent_list = []for idx in range(generator.n_latent):latent_list.append(latent_dict[idx])latent_n = paddle.concat(latent_list, 1)img_gen, _ = generator([latent_n], input_is_latent=True, randomize_noise=False)frames.append(make_image(img_gen))batch, channel, height, width = img_gen.shapeif height > 256:factor = height // 256img_gen = img_gen.reshape((batch, channel, height // factor, factor, width // factor, factor))img_gen = img_gen.mean([3, 5])p_loss = percept(img_gen*masks, (imgs*masks).detach()).sum()mse_loss = F.mse_loss(img_gen*masks, (imgs*masks).detach())loss = p_loss + mse_weight * mse_lossoptimizer.clear_grad()loss.backward()optimizer.step()pbar.set_description((f"perceptual: {p_loss.numpy()[0]:.4f}; "f"mse: {mse_loss.numpy()[0]:.4f}; lr: {lr:.4f}"))img_gen, _ = generator([latent_n], input_is_latent=True, randomize_noise=False)frames.append(make_image(img_gen))imgs_seq = [[] for _ in range(img_gen.shape[0])]for i in range(img_gen.shape[0]):for frame in frames:imgs_seq[i].append(frame[i])return imgs_seq, latent_nif __name__ == "__main__":import argparseimport osfrom utils import save_videofrom crop import align_faceparser = argparse.ArgumentParser(description="Image projector to the generator latent spaces")parser, arg_names = func_args(parser, project)parser.add_argument("--no_crop", action="store_true", help="disable to crop input images first")parser.add_argument("--save_mp4", action="store_true", help="saving training progress images as mp4 videos")parser.add_argument("files", metavar="FILES", nargs="+", help="path to image files to be projected")parser.add_argument("--output", type=str, default="./output", help="output directory")args = parser.parse_args()imgs = []masks = []for imgfile in args.files:if args.no_crop:img = Image.open(imgfile)imgs.append(img)maskfile = '.'.join(imgfile.split('.')[:-1]) + '.mask.' + imgfile.split('.')[-1]if os.path.exists(maskfile):mask = Image.open(maskfile)else:mask = Image.new(mode='L', size=img.size, color=255)masks.append(mask)else:img, mask = align_face(imgfile)imgs.append(img)masks.append(mask)imgs_seq, latent_code = project(imgs, masks, **{arg_name: getattr(args, arg_name) for arg_name in arg_names})os.makedirs(args.output, exist_ok=True)for i, input_name in enumerate(args.files):code_name = os.path.join(args.output, os.path.splitext(os.path.basename(input_name))[0] + ".pd")latent_file = {"latent_code": latent_code[i],}paddle.save(latent_file, code_name)img_name = os.path.join(args.output, os.path.splitext(os.path.basename(input_name))[0] + "-project.png")pil_img = Image.fromarray(imgs_seq[i][-1])pil_img.save(img_name)if args.save_mp4:fps = 30duration = 5save_video(imgs_seq[i],os.path.join(args.output, os.path.splitext(os.path.basename(input_name))[0] + "-project.mp4"),fps, duration)

7.系统整合

8.完整源码&环境部署视频教程&自定义UI界面

9.参考文献


[1]徐莹.基于分层结构和稀疏表示的人脸老化模拟研究[J].中南大学.2012.DOI:10.7666/d.y2196806.
[2]Shuang Liu,Dan Li,Tianchi Cao,等.GAN-Based Face Attribute Editing[J].IEEE Access.2020.834854-34867.DOI:10.1109/ACCESS.2020.2974043.
[3]Lanitis, A.,Taylor, C.J.,Cootes, T.F…Toward automatic simulation of aging effects on face images[J].Pattern Analysis & Machine Intelligence, IEEE Transactions on.2002,24(4).442-455.
[4]Volker Blanz,Thomas Vetter.A Morphable Model For The Synthesis Of 3D Faces[J].Computer graphics.1999,33(0).
[5]Alfred Müller.Integral Probability Metrics and Their Generating Classes of Functions[J].Advances in applied probability.1997,29(2).429-443.DOI:10.1017/S000186780002807X.
[6]Bor-Chun Chen,Chu-Song Chen,Winston H. Hsu.Cross-Age Reference Coding for Age-Invariant Face Recognition and Retrieval[C].2014
[7]Jia Deng,Wei Dong,Socher, R.,等.ImageNet: A large-scale hierarchical image database[C].

改进StyleGANv2的容貌年龄预测系统相关推荐

  1. 实例讲解spark在京东智能供应链预测系统的应用

    问题导读: 1. 京东的供应链是什么样的呢? 2. 预测技术在京东的供应链起着什么样的作用呢? 3. 京东整个预测系统的架构是什么样的呢? 4. 预测系统不同层面的技术选型分别为什么? 5. 预测系统 ...

  2. 基于数据挖掘的疾病数据可视化分析与预测系统

    温馨提示:文末有 CSDN 平台官方提供的学长 Wechat / QQ 名片 :) 1. 项目简介 随着医院信息系统(HIS)在全国各大医院的推广和应用,会有大量和病人相关的临床数据每天在医院中记录, ...

  3. 大数据专栏一-全自动化在线式当当销售情况分析预测系统

    (ps:临时想起来补一句,,本项目仅用于学习交流,不用于任何商业用途.还有如果有大数据班的学弟学妹看到这一定记得作业得按时交作业延期交了成绩会和下一个档次的作业一个分数)项目报告和代码以及录屏都保存在 ...

  4. 山东大学暑期项目实训——云主机服务比价与预测系统

    山东大学暑期项目实训--云主机服务比价与预测系统(十二) 使用tensorflow做预测 一.简单的预测函数值 1.使用训练数据做预测 创建模型: model = keras.Sequential([ ...

  5. 基于改进First_order的表情驱动图片系统(源码&教程)

    1.研究背景 早期的Facerig软件可以即时抓取摄像头视频中的人脸关键点,将表情.头部姿态等信息转化到三维虚拟化身上,比如一只猫.一个虚拟卡通人物上.然后在使用即时视频通讯软件时,选择facerig ...

  6. 【玩转华为云】手把手教你利用ModelArts实现人脸年龄预测

    本篇推文共计2000个字,阅读时间约3分钟. 华为云-华为公司倾力打造的云战略品牌,2011年成立,致力于为全球客户提供领先的公有云服务,包含弹性云服务器.云数据库.云安全等云计算服务,软件开发服务, ...

  7. 基于python的银行信用卡客户等级预测系统

    目录 一.设计要求 二.技术综述 三.需求分析 四.系统实现 数据来源 一.设计要求 1.客户数据预处理.对数据集进行缺失值处理,包含删除缺失值.填充数据等,同时对数据进行归一化处理. 2.确定影响客 ...

  8. 基于关联规则(Variational Autoencoders)疾病预测系统实战:(pyspark FPGrowth实现频繁项集挖掘、最后给出预测模型topK准确率和召回率)

    基于关联规则(Variational Autoencoders)疾病预测系统实战:(pyspark FPGrowth实现频繁项集挖掘.最后给出预测模型topK准确率和召回率) 目录

  9. 基于变分自动编码器(Variational Autoencoders)疾病预测系统实战:(Keras实现并可视化训练和验证误差、最后给出topK准确率和召回率)

    基于变分自动编码器(Variational Autoencoders)疾病预测系统实战:(Keras实现并可视化训练和验证误差.最后给出topK准确率和召回率) 本文中使用的VAE算法以病人病史为输入 ...

最新文章

  1. 在Ubuntu 16.04.4 LTS上调研开源QUIC项目ngtcp2
  2. mysql query plan_MySQL Execution Plan--IN查询计划(2)
  3. 11g下如何查询trace文件名
  4. mysql触发器不起作用 navicat的bug?
  5. vim复制粘贴_打造一款高逼格的Vim神器
  6. python中函数分为哪四类_Python函数参数分类原理详解
  7. mysql5.6免安装配置(菜鸟版)
  8. 简单几何(圆与多边形公共面积) UVALive 7072 Signal Interference (14广州D)
  9. iOS截取视频预览图,截图方向错误的解决
  10. [LeetCode] NO. 242 Valid Anagram
  11. es6的模块化export和import
  12. 华为云微认证答题_华为云微认证
  13. MTK6763平台手机 在国外无法成功注册VOLTE。求解
  14. java爬取国家统计局之统计用区划和城乡划分代码(省市区三级)
  15. jQuery实现表单提交验证
  16. linux下python网络编程框架-twisted安装手记,Linux下Python网络编程框架-Twisted安装手记 | 学步园...
  17. Java培训机构可靠吗?
  18. python给批量图片添加文字_Python之利用PIL批量给图片添加文字
  19. 计算机应用基础考试制作表格,计算机应用基础考试---Excel电子表格公式与函数...
  20. Linux下C语言开发

热门文章

  1. Epson针式打印机切纸/存折灯常亮一页打印造成多页的解决方案
  2. 小米airdots双耳串联问题解决
  3. 基于 Element-ui 的富文本组件quillEditor
  4. 用spring管理和实例化对象的四种方式
  5. 在Ubuntu18.04上搭建私有网盘 —— ownCloud
  6. html提交按钮标签代码是什么,怎么使用?(示例)
  7. OpenCV系列之图像的几何变换 | 十四
  8. Linux 知:gdb
  9. Javascript 斐波那契数列
  10. 2021-09-03剑指Offer51.数组中的逆序对