转自AI Studio,原文链接:SSAT妆容迁移 - 飞桨AI Studio

又是展示的一天,妆容迁移之SSAT PADDLE版本,你值得拥有

1. 效果展示

又是展示的一天呢,枯燥且乏味的show time。哈哈哈哈哈哈哈哈哈哈

请原谅我笑得这么大声

就是第一列的女生用的第二列的妆容,就是第四列的结果,第三列是看第二列妆容按照第一列的脸型扭曲的效果咋样,可以忽略 

   

如果你想试一下死亡芭比粉的口红,是不是就不需要亲自买一只就可以看到效果了?请把项目有用打在公屏上。

如果看官是有女朋友的男生想看自己女朋友涂紫色口红的样子,你可以fork

如果看官本身是女生,想看闺蜜涂紫色口红的样子,你可以fork

咱说一个数,200fork一个项目,冲冲冲!!!!!!!!!!!!!

这个时候肯定有人好奇,怎么不用男生当试验呢?我肯定试过了,但是怎么可能放出来嘛,是吧,哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈。

这个时候肯定有人会问,小帅哥,这个是这么做出来的呢?对吧,我知道的,我很懂的哦,请允许我喝口水娓娓道来。

好了好了,严肃起来,严肃起来

2. 论文名称:SSAT: A Symmetric Semantic-Aware Transformer Network for Makeup Transfer and Removal

论文PDF我也放在项目里面了

原论文官方项目地址:https://github.com/Snowfallingplum/SSAT

作者的视频论文讲解:https://www.bilibili.com/video/BV1k34y1t7jk?spm_id_from=333.788.top_right_bar_window_history.content.click

知乎的论文讲解: https://zhuanlan.zhihu.com/p/494364754

那个数据集呢,没有哦,因为我是直接把官方提供的预训练模型参数直接给转成paddle的参数文件格式了,哈哈哈,我不会训练哦。

3.妆容迁移的任务描述:

把人物B的妆容迁移到人物A身上,也就是输入的是两张人物人脸照片得到一张新的人脸照片C。C照片需要保持A的人脸内容特征,但是需要保持B的妆容。

4.本项目注意点

就是这个人脸呢。要占整张图片的很大一部分,不然效果就不太好,尽量减少让模型减少受背景干扰的机会。不要像上方这个图片一样,这就是一个错误典型!!!!!!

另外模型输入的是4个部分信息。这个时候有人好奇了,为啥是四个部分信息呢?不是只要输入模型两张人脸就好了吗,一张target(提供人脸内容信息),一张reference(妆容信息)。这个时候这就体现这篇论文创新之处了,它为了给模型一个人脸各个部分的先验信息,所以对于target和reference对应的人脸解析信息也作为输入给模型了。那么这个时候有人会说:大佬大佬,那么我们可没有能够得到人脸先验信息的轮子呀,咋办?

我会允许这种事情的发生?不可能,绝对不可能,于是我这个人脸解析项目特意弥补了这方面的空白。大家只要用就行了。

另外再注意一下,人脸解析项目自动把图片reshape成512*512大小的,然后模型输出的人脸解析的图片也是512*\512大小的,然后本项目这里reference和target我也自动resize成512*\512大小的,也就是请你如果想用本项目实验的话请输入的图片都是正方形,防止人脸因为resize变形。

5.模型解读

我也懒得把现有的资料搬运一遍,如果真的想去学习这个模型,那么我所有资料信息上方已经提供了。大家该看自己看,这边我提供一份我原创的模型框架图,方便对照着代码理解看。这里展示的图片是png格式,项目里面也提供pdf版本的。 

6.代码使用讲解

In [19]

import cv2
import numpy as np
def load_parse(parse):
    parse = cv2.imread(parse, cv2.IMREAD_GRAYSCALE)
    # print(parse)
    # parse = self.rotate(parse, angle)
    h, w = parse.shape
    result = np.zeros([h, w, 18])
    for i in range(18):
        result[:, :, i][np.where(parse == i)] = 1
    result = np.array(result)
    return result

# load_parse("1.png").shape

In [20]

'''
makeup_face_img就是reference ,16行代码图片读取路径改一下
makeup_parse就是reference的人脸解析信息,19行代码图片读取路径改一下
makeup_none_img就是target,21行代码图片读取路径改一下
makeup_none_parse就是target的人脸解析信息,25行代码图片读取路径改一下
'''

import numpy as np
from PIL import Image
from paddle.vision.transforms import functional as F


import paddle


makeup_face_img = cv2.cvtColor(cv2.imread("12.jpg", flags=cv2.IMREAD_COLOR),
                            cv2.COLOR_BGR2RGB)
makeup_face_img = F.resize(makeup_face_img, [512,512])
makeup_parse = load_parse("12.png")

makeup_none_img = cv2.cvtColor(cv2.imread("refer.jpg", flags=cv2.IMREAD_COLOR),
                            cv2.COLOR_BGR2RGB)

makeup_none_img = F.resize(makeup_none_img, [512,512])
makeup_none_parse = load_parse("refer.png")

makeup_face_img = (paddle.to_tensor(makeup_face_img).astype("float32")/127.5-1).unsqueeze(0).transpose([0,3,1,2])
makeup_parse = paddle.to_tensor(makeup_parse).unsqueeze(0).transpose([0,3,1,2]).astype("float32")
makeup_none_img = (paddle.to_tensor(makeup_none_img).astype("float32")/127.5-1).unsqueeze(0).transpose([0,3,1,2])
makeup_none_parse = paddle.to_tensor(makeup_none_parse).unsqueeze(0).transpose([0,3,1,2]).astype("float32")
data = {"non_makeup":makeup_none_img,"makeup":makeup_face_img,"non_makeup_parse":makeup_none_parse,"makeup_parse":makeup_parse}

In [21]

from  paddle_model import MakeupGAN as pmm
pm = pmm()
pm.set_state_dict(paddle.load("paddleweight.pdparams"))
test_pair_img = pm.test_pair(data)

In [ ]

print(test_pair_img)

In [23]

test_pair_img = (test_pair_img+1)*127.5
test_pair_img = test_pair_img.numpy()
test_pair_img = test_pair_img.transpose(0, 2, 3, 1)[0]
test_pair_img = test_pair_img.astype(np.uint8)
cv2.imwrite('ep1och.png',cv2.cvtColor(test_pair_img,cv2.COLOR_RGB2BGR)) # ep1och.png就是输出结果
True

7. 一些小问题

官方作者团队给出的代码是有瑕疵的,我也提了issue并且得到作者的肯定。这个问题是我把权重从pytorch迁移到paddle后仔细阅读了一下源码发现的,但是呢,我把这个问题申明放在项目最后,就表示这是不影响使用的。

Logo

学大模型,用大模型上飞桨星河社区!每天8点V100G算力免费领!免费领取ERNIE 4.0 100w Token >>>

更多推荐