1 项目背景
最近看了一篇文章是关于用ai为冰冰上妆的博文,文章使用的是SCGAN架构,但直接使用SCGN提取妆容效果并不是很好,文章的解决办法是先把图片裁剪出人脸然后对五官进行分割最后再使用SCGN网络进行上妆,最后效果也非常不错。于是我就产生了一个想法——用PaddleGAN的PSGAN模型来实现对冰冰的妆容迁移,至于PSGAN有什么优势呢让我们看一下对于PSGAN的原理分析。
2 PSGAN原理
PSGAN模型的任务是妆容迁移, 即将任意参照图像上的妆容迁移到不带妆容的源图像上。很多人像美化应用都需要这种技术。近来的一些妆容迁移方法大都基于生成对抗网络(GAN)。它们通常采用 CycleGAN 的框架,并在两个数据集上进行训练,即无妆容图像和有妆容图像。但是,现有的方法存在一个局限性:只在正面人脸图像上表现良好,没有为处理源图像和参照图像之间的姿态和表情差异专门设计模块。PSGAN是一种全新的姿态稳健可感知空间的生成对抗网络。PSGAN 主要分为三部分:妆容提炼网络(MDNet)、注意式妆容变形(AMM)模块和卸妆-再化妆网络(DRNet)。这三种新提出的模块能让 PSGAN 具备上述的完美妆容迁移模型所应具备的能力。
3 采用PaddleGAN进行训练
飞桨生成对抗网络开发套件–PaddleGAN,为开发者提供经典及前沿的生成对抗网络高性能实现,并支撑开发者快速构建、训练及部署生成对抗网络,以供学术、娱乐及产业应用。
3.1 安装PaddleGAN
# 要安装paddlegan到根目录,所以先要切换目录
%cd /home/aistudio/
# 使用git克隆addleGAN仓库到当前目录
!git clone https://gitee.com/paddlepaddle/PaddleGAN.git
# 下载好后切换目录到PaddleGAN的
%cd /home/aistudio/PaddleGAN
/home/aistudio
3.2 安装第三方库
下载第三方库的时候,pip下载的很多是国外的源,所以我们可以换成国内的源下载速度会变快,这里我提供三个源。
- 清华:https://pypi.tuna.tsinghua.edu.cn/simple
- 阿里云:http://mirrors.aliyun.com/pypi/simple/
- 中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/
# 切换路径
%cd /home/aistudio/PaddleGAN/
# 安装所需的第三方库
!pip install -r requirements.txt
!pip install boost -i https://mirrors.aliyun.com/pypi/simple/
!pip install CMake -i https://mirrors.aliyun.com/pypi/simple/
!pip install dlib -i https://mirrors.aliyun.com/pypi/simple/
# 有下方提示代表安装成功
# Successfully built dlib
# Installing collected packages: dlib
# Successfully installed dlib-19.22.0
3.3 裁剪人脸
注意:其实在psgan中已经对图像处理了,只是我在训练的时候结果人脸并不是在中间,所以可以先运行下面的裁剪人脸和改变图像大小代码。(也可以不运行)
这里直接使用 dlib, 裁剪出人脸的区域
# 裁剪人脸
import cv2
import dlib
# 裁剪前后的路径
cut_before_img="/home/aistudio/work/ps_source.png"
cut_after_img="/home/aistudio/work/ps_source_face.png"
img = cv2.imread(cut_before_img)
height, width = img.shape[:2]
face_detector = dlib.get_frontal_face_detector()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_detector(gray, 1)
def get_boundingbox(face, width, height, scale=1.6, minsize=None):
"""
Expects a dlib face to generate a quadratic bounding box.
:param face: dlib face class
:param width: frame width
:param height: frame height
:param scale: bounding box size multiplier to get a bigger face region
:param minsize: set minimum bounding box size
:return: x, y, bounding_box_size in opencv form
"""
x1 = face.left()
y1 = face.top()
x2 = face.right()
y2 = face.bottom()
size_bb = int(max(x2 - x1, y2 - y1) * scale)
if minsize:
if size_bb < minsize:
size_bb = minsize
center_x, center_y = (x1 + x2) // 2, (y1 + y2) // 2
# Check for out of bounds, x-y top left corner
x1 = max(int(center_x - size_bb // 2), 0)
y1 = max(int(center_y - size_bb // 2), 0)
# Check for too big bb size for given x, y
size_bb = min(width - x1, size_bb)
size_bb = min(height - y1, size_bb)
return x1, y1, size_bb
if len(faces):
face = faces[0]
x,y,size = get_boundingbox(face, width, height)
cropped_face = img[y-50:y+size,x:x+size]
cv2.imwrite(cut_after_img, cropped_face)
True
# 改变图像大小
import cv2
im1 = cv2.imread(cut_after_img)
im2 = cv2.resize(im1,(im1.shape[1],im1.shape[1]),) # 为图片重新指定尺寸
cv2.imwrite(cut_after_img,im2)
True
# 裁剪对比显示
import cv2
from matplotlib import pyplot as plt
%matplotlib inline
# 裁剪前路径
before = cv2.imread(cut_before_img)
after = cv2.imread(cut_after_img)
plt.figure(figsize=(10, 10))
plt.subplot(1, 2, 1)
plt.title('cut-before')
plt.imshow(before[:, :, ::-1])
plt.subplot(1, 2, 2)
plt.title('cut-after')
plt.imshow(after[:, :, ::-1])
plt.show()
3.4 妆容迁移
运行如下命令,就可以完成妆容迁移,程序运行成功后,会在当前文件夹生成妆容迁移后的图片文件。本项目中提供了原始图片和参考供展示使用,具体命令如下所示:
python tools/psgan_infer.py \
--config-file configs/makeup.yaml \
--model_path /your/model/path \
--source_path docs/imgs/ps_source.png \
--reference_dir docs/imgs/ref \
--evaluate-only
参数说明:
-
config-file: PSGAN网络到参数配置文件,格式为yaml
-
model_path: 训练完成保存下来网络权重文件的路径(可以不设置,也可点击下载权重)
-
source_path: 未化妆的原始图片文件全路径,包含图片文件名字
-
reference_dir: 化妆的参考图片文件路径,不包含图片文件名字
-
结果自动保存至/home/aistudio/PaddleGAN/output/transfered_ref_ps_ref.png
# 妆容迁移代码
%cd /home/aistudio/PaddleGAN
!python tools/psgan_infer.py \
--config-file configs/makeup.yaml \
--source_path ~/work/ps_source_face.png \
--reference_dir ~/work/ref \
--evaluate-only
# 有下方提示代表运行成功
# Transfered image output/transfered_ref_ps_ref.png has been saved!
# done!!!
3.5 结果显示
import cv2
from matplotlib import pyplot as plt
%matplotlib inline
ps_source = cv2.imread('/home/aistudio/work/ps_source_face.png')
ps_ref = cv2.imread('/home/aistudio/work/ref/ps_ref.png') # 这是化妆图片的路径
transfered_ref_ps_ref = cv2.imread('/home/aistudio/PaddleGAN/output/transfered_ref_ps_ref.png')
plt.figure(figsize=(10, 10))
plt.subplot(1, 3, 1)
plt.title('Origanl')
plt.imshow(ps_source[:, :, ::-1])
plt.xticks([])
plt.yticks([])
plt.subplot(1, 3, 2)
plt.title('MarkUp')
plt.imshow(ps_ref[:, :, ::-1])
plt.xticks([])
plt.yticks([])
plt.subplot(1, 3, 3)
plt.title('After')
plt.imshow(transfered_ref_ps_ref[:, :, ::-1])
plt.xticks([])
plt.yticks([])
# 保存
save_path='/home/aistudio/work/output.png'
plt.savefig(save_path)
plt.show()
4 总结
看着最后的训练效果感觉还不错。都看到这里了你还不自己试一下,说不定有想不到的效果yo