云社区 博客 博客详情

张小白带你使用StyleGAN玩转人脸生成

张辉 发表于 2021-04-29 08:53:23 2021-04-29
0
0

【摘要】 老谭生成器使用说明书

各位童鞋,上次的蚂蚁牙黑好玩吗?(https://bbs.huaweicloud.com/blogs/246301  https://bbs.huaweicloud.com/blogs/246302

如果觉得还有点意思,那么你一定会对StyleGAN感兴趣。

StyleGAN的原理张小白也看不大懂。。反正就是根据预训练模型,生成一些大家从来没见过的照片,比如人脸、汽车、马,动漫,网红脸(整容脸),超模脸之类的。

具体的原理可以参见:论文阅读-人脸生成_StyleGAN:https://zhuanlan.zhihu.com/p/62119852

张小白从来就是个实战派,那么就跟随张小白的脚步,看看到底怎么生成这么好玩的东西吧。

Part 1:软件及工具准备

玩转这个最好是自己有个带gpu的windows。

可以按照张小白的博客安装好 cuda和cudnn。(https://bbs.huaweicloud.com/blogs/212446 )不过这里的版本是不一定需要跟StyleGAN的运行环境完全一致的。

你可以根据 https://blog.csdn.net/weixin_50888378/article/details/109022585 安装Windows的Anaconda环境。

感谢 @枫树 大侠告知,有了conda的加持,是可以同时在一台机器内安装多套GPU的cuda和cudnn环境的。要知道,cuda和cudnn的版本跟tensorflow的版本密切相关,一旦不一致就会有很多问题,因为有的神经网络需要TF2的版本,有的需要TF1的不同版本。不可能每次都重装cuda和cudnn。

此外,你可以根据 https://bbs.huaweicloud.com/forum/forum.php?mod=viewthread&tid=119491 一楼的方法安装好社区版不要钱的 PyCharm。

你还需要安装Microsoft Visual Studio 2019. 可以到 https://visualstudio.microsoft.com/zh-hans/downloads/ 下载安装,安装的时候请务必选择:使用C++的桌面开发,其他随意:

在这些基础环境安装好之后,就可以开GAN了。

Part 2:代码准备

这次的实验需要用到3个代码仓,一个是stylegan2,一个是stylegan2encoder,一个是generators-with-stylegan2

先clone下来:

https://github.com/NVlabs/stylegan2

https://github.com/rolux/stylegan2encoder

https://github.com/a312863063/generators-with-stylegan2.git

你可以直接git clone ,当然因为众所周知的原因,你也可以通过 gitee转克隆:(张小白教过你们的。。。)


git clone https://gitee.com/BolinLi-s/stylegan2.git 

git clone https://gitee.com/gdjmck/stylegan2encoder.git

git clone https://gitee.com/zhangliwu888/generators-with-stylegan2

Part 3:StyleGAN系统安装

使用PyCharm打开stylegan2目录:

看看README.md

这是小白退散。。。的规则:

需要安装Python 3.6, Tensorflow 1.14 (On Windows,注意仔细看),需要CUDA10.0cuDNN 7.5,

需要Nvidia GPU,

需要16G内存。

(如果你们都没有的话,就上ModelArts吧。。。)

(一)Python 3.6+CUDA 10.0+cuDNN环境安装

我们使用conda来创建这个环境吧:

conda create -n gaohuo python=3.6 

激活conda环境

conda activate gaohuo 

先安装CUDA10.0(请注意是在gaohuo环境里面)

conda install cudatoolkit=10.0

conda install cudnn

装的cudnn 版本号是6.0,readme提示是7.5,可能会有问题。先安装了再说。

(二)PIP依赖包安装

升级pip到最新版本

python -m pip install --upgrade pip

安装tensorflow-gpu版本

pip install tensorflow-gpu==1.14 -i http://pypi.douban.com/simple --trusted-host=pypi.douban.com

(需要注意,conda安装时,等于号是一个,pip安装时,等于号是两个)

包有点大(287M),耐心等待安装完毕。最近PIP的清华源不大好使,豆瓣源稍微好一点,但是也会断。。有时候安装得靠点运气。

。。。

装指定版本的keras(2.2.5)

pip install keras==2.2.5

安装PIL 8.2.0

安装dlib 19.22

pip install dlib

安装tqdm 4.60

pip install tqdm

安装requests 2.25.1

pip install requests

(三)准备预训练模型

我们需要准备一下预训练模型:

看README.md提供的链接:下面的car, cat,church,hourse就看你随意吧。

点击蓝色的链接就可以下载:

下载完毕后,将其拷贝到 stylegan2工程的 models目录下吧。(新建个models目录)

Part 4:使用StyleGan2的预训练模型生成随机图片

修改 pretrained_networks.py 文件,将含有

gdrive:networks/stylegan2-ffhq-config-f.pkl 的一行改为一下内容:

    'gdrive:networks/stylegan2-ffhq-config-f.pkl':                          '.\models\stylegan2-ffhq-config-f.pkl',


修改 dnnlib/tblib/custom_ops.py文件,将 compiler_bindir_search_path 一节的内容改为跟自己 前面安装的Visual Studio 相同的目录,

张小白本地的目录是这样的:

compiler_bindir_search_path = [
#    'C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.16.27023/bin/Hostx64/x64',
#    'C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.23.28105/bin/Hostx64/x64',
    'C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools\MSVC/14.28.29333/bin/Hostx64/x64',
    'C:/Program Files (x86)/Microsoft Visual Studio/2017/BuildTools/VC/Tools\MSVC/14.16.27023/bin/Hostx64/x64',
#    'C:/Program Files (x86)/Microsoft Visual Studio 14.0/vc/bin',
    'C:/Program Files (x86)/Microsoft Visual Studio 10.0/VC/bin',
]

先试一下用官方的模型生成的人像吧:

python run_generator.py generate-images --network=gdrive:networks/stylegan2-ffhq-config-f.pkl --seeds=6600-6625 --truncation-psi=0.5

。。

报错了。。。经过度娘查询,https://blog.csdn.net/DLW__/article/details/104229303 说明CUDA 10.0版本不行,需要装CUDA10.1版本。

conda install cudatoolkit=10.1

。。。

为了保险起见,将与cuda配套的cudnn也重新安装一下(可能这个步骤没必要做)

conda unsintall cudnn

conda install cudnn


再来重跑前面的脚本:

python run_generator.py generate-images --network=gdrive:networks/stylegan2-ffhq-config-f.pkl --seeds=6600-6625 --truncation-psi=0.5

...

貌似已经生成了图片,去result目录看一看:

果然有,使用资源管理器可以看得更清楚:

好了,我们完成了StyleGAN的第一步,生成随机的人脸图像。

有兴趣的人也可以下载其他的模型,生成比如 马、猫、教堂、汽车的图片:

反正下载不同的模型可以生成不同的图片。这些图片是否在世界上存在呢?这可能是个谜。。。

Part 5:使用stylegan2encoder生成真实人像图片的特征码

切换stylegan2encoder工程:

使用 conda activate guohao进入tensorflow 1.14 +cuda 10.1+cudnn环境

建立raw_images目录,存放原始人像图片

建立aligned_images目录,存放头像对齐后的图片

在网上找一张硬汉哈里森福特的照片:


将其另存为fute.jpg ,保存在raw_images目录下。

按照前面同样的方式,修改dnnlib/tflib/custom_ops.py文件:

和pretrained_networks.py文件:

将stypegan2的models目录下的预训练模型拷贝到这里(创建同样的目录)

然后执行:

python align_images.py raw_images/ aligned_images/

。。。

执行完毕后,aligned_images目录下,会生成一个图片 fute_01.jpg

打开 一看,是将图片的头像居中了,而且分辨率是1024X1024:

有了1024X1024的图片,我们就可以使用encode_images.py脚本生成特征码了。

python encode_images.py aligned_images/ generated_images/ latent_representations/

。。。

这里面要跑1000次。请耐心等待跑完。

generated_images目录下生成了上图的图片: fute_01.png(照片中的头发好像发生了一些变化)

而 latent_representations 目录下也生成了特征码文件:fute_01.npy

将aligned_images目录下的人脸图片投射到dlatents空间(这步有点问题。。)

修改projector.py

将 

        vgg16_pkl                       = 'https://drive.google.com/uc?id=1N2-m9qszOeVC9Tq77WxsLnuWwOedQiD2',

改为:

        vgg16_pkl                       = '.\models\\vgg16_zhang_perceptual.pkl',


vgg16_zhang_perceptual.pkl 可从 https://pan.baidu.com/s/1vP6NM9-w4s3Cy6l4T7QpbQ(提取码: 5qkp)下载,下载后将其拷入models目录。

修改project_images.py

    parser.add_argument('--vgg16-pkl', default='https://drive.google.com/uc?id=1N2-m9qszOeVC9Tq77WxsLnuWwOedQiD2', help='VGG16 network pickle filename')

改为:

    parser.add_argument('--vgg16-pkl', default='./models/vgg16_zhang_perceptual.pkl', help='VGG16 network pickle filename')

然后执行以下脚本:

python project_images.py aligned_images/ generated_images/

将 aligned_images目录下的人脸图片投射到dlatents空间,找到最佳的dlatents,保存dlatents文件和重建的人脸图片到generated_images目录。

。。。

出了个错: CUDA_ERROR_ILLEGAL_ADDRESS.

这个问题张小白搜了一下,貌似说是跟显卡驱动有关,又可能跟显存不足有关。

好像暂时搞不定。

Part 6:使用generators-with-stylegan2生成随机人脸图片

打开generators-with-stylegan2工程:

根据networks目录下的 “模型下载后放在这里.txt”的文件中的地址,下载各个模型:

结果如下:

同样的方式配置 dnnlib/tflib/custom_ops.py

进入同样的gaohuo conda环境,运行main.py

缺省会生成20张 黄种人的照片:

照片生成在 result目录下:

你也可以将main.py中的模型文件改为其他的名字:

重新运行main.py,就会生成不同的图片:

萌娃脸:

网红脸:

超模脸:

明星脸:

好像也蛮好玩的。。

Part 7:使用stylegan2生成真实人脸的重建图片

切换到stylegan2工程:

新建 datasets/mypictures 目录

将stylegan2encode工程下的 aligned_images目录(就是福特人脸居中的目录)拷贝过来:

仔细看了一下fute_01.png文件的大小:

发现这个文件有点大了。想想前面可能是因为显存不足造成的python代码无法执行完毕。最好还是对这个1024X1024的24bit的文件做个瘦身。

网上搜了一下,有个叫做 imageJ的应用程序好像比较适合做这个:( https://zhuanlan.zhihu.com/p/54955448

于是按照链接的方法下载并安装了imageJ。

运行imageJ:

打开 fute_01.png

将其转为8bit color,

再另存为fute_01.jpg。

将其拷贝到 ./aligned_images 目录(原来的png文件挪走)

此时文件只有127K了。非常舒适。


执行dataset_tool.py脚本,对“./aligned_images”目录下的图片,进行预处理,把处理结果存放到“./datasets/mypictures”目录下:

python dataset_tool.py create_from_images ./datasets/mypictures ./aligned_images

生成的文件如下:

运行run_projector.py(硬编码的缺省迭代次数为:1000),得到StyleGAN2模型下的真实人脸的重建图像,图像放在“./results”目录下面

python run_projector.py project-real-images --network=gdrive:networks/stylegan2-ffhq-config-f.pkl --dataset=mypictures --data-dir=./datasets

。。。

。。。

。。。唉,拼到了587/1000.还是没有躲过 CUDA_EROR_ILLEGAL_ADDRESS的境遇。

看来张小白的乞丐显卡真的不行。

下次考虑将这些代码放在ModelArts运行试试。

不过,虽然没有完全结束,我们还是可以看到一些中间结果:

Part 8:使用stylegan2encode生成不同场景下的真实人像的重建图片

切换stylegan2encode工程:

准备一个新的python脚本:config.py

dlatents_dir = 'latent_representations'
generated_dir = 'generated_images'
result_dir = 'results'

准备另一个新的python脚本:move_and_show.py

import os
import pickle
import PIL.Image
import numpy as np
import dnnlib
import dnnlib.tflib as tflib
import config
from encoder.generator_model import Generator
import matplotlib.pyplot as plt
import glob

# 预训练好的网络模型,来自NVIDIA
Model = './models/stylegan2-ffhq-config-f.pkl'
_Gs_cache = dict()


# 加载StyleGAN已训练好的网络模型
def load_Gs(model):
    if model not in _Gs_cache:
        model_file = glob.glob(Model)
        if len(model_file) == 1:
            model_file = open(model_file[0], "rb")
        else:
            raise Exception('Failed to find the model')

        _G, _D, Gs = pickle.load(model_file)
        # _G = Instantaneous snapshot of the generator. Mainly useful for resuming a previous training run.
        # _D = Instantaneous snapshot of the discriminator. Mainly useful for resuming a previous training run.
        # Gs = Long-term average of the generator. Yields higher-quality results than the instantaneous snapshot.

        # Print network details.
        # Gs.print_layers()

        _Gs_cache[model] = Gs
    return _Gs_cache[model]


# 使用generator生成图片
def generate_image(generator, latent_vector):
    latent_vector = latent_vector.reshape((1, 18, 512))
    generator.set_dlatents(latent_vector)
    img_array = generator.generate_images()[0]
    img = PIL.Image.fromarray(img_array, 'RGB')
    return img.resize((256, 256))


# 将真实人脸图片对应的latent与改变人脸特性/表情的向量相混合,调用generator生成人脸的变化图片
def move_and_show(generator, flag, latent_vector, direction, coeffs):
    fig, ax = plt.subplots(1, len(coeffs), figsize=(15, 10), dpi=80)
    # 调用coeffs数组,生成一系列的人脸变化图片
    for i, coeff in enumerate(coeffs):
        new_latent_vector = latent_vector.copy()
        # 人脸latent与改变人脸特性/表情的向量相混合,只运算前8层(一共18层)
        new_latent_vector[:8] = (latent_vector + coeff * direction)[:8]
        ax.imshow(generate_image(generator, new_latent_vector))
        ax.set_title('Coeff: %0.1f' % coeff)
    [x.axis('off') for x in ax]
    # 显示
    plt.show()

    # 根据看到的人脸变化的效果,输入一个你认为合适的浮点数
    favor_coeff = float(input('Please input your favourate coeff, such as -1.5 or 1.5: '))
    new_latent_vector = latent_vector.copy()
    # 用输入的浮点数控制生成新的人脸变化
    new_latent_vector[:8] = (latent_vector + favor_coeff * direction)[:8]
    # 增加一个维度,以符合generator对向量的要求
    new_latent_vector = new_latent_vector.reshape((1, 18, 512))
    # 将向量赋值给generator
    generator.set_dlatents(new_latent_vector)
    # 调用generator生成图片
    new_person_image = generator.generate_images()[0]
    # 画图,1024x1024
    canvas = PIL.Image.new('RGB', (1024, 1024), 'white')
    canvas.paste(PIL.Image.fromarray(new_person_image, 'RGB'), ((0, 0)))
    # 根据不同的标志,存入不同的文件名
    if flag == 0:
        filename = 'new_age.png'
    if flag == 1:
        filename = 'new_angle.png'
    if flag == 2:
        filename = 'new_gender.png'
    if flag == 3:
        filename = 'new_eyes.png'
    if flag == 4:
        filename = 'new_glasses.png'
    if flag == 5:
        filename = 'new_smile.png'
    # 将生成的图像保存到文件
    canvas.save(os.path.join(config.generated_dir, filename))


def main():
    # 初始化
    tflib.init_tf()
    # 调用预训练模型
    Gs_network = load_Gs(Model)
    generator = Generator(Gs_network, batch_size=1, randomize_noise=False)

    # 读取对应真实人脸的latent,用于图像变化,qing_01.npy可以替换为你自己的文件名
    os.makedirs(config.dlatents_dir, exist_ok=True)
    person = np.load(os.path.join(config.dlatents_dir, 'fute_01.npy'))

    # 读取已训练好的用于改变人脸特性/表情的向量
    # 包括:改变年龄、改变水平角度、改变性别、改变眼睛大小、是否佩戴眼镜、改变笑容等
    age_direction = np.load('ffhq_dataset/latent_directions/age.npy')
    angle_direction = np.load('ffhq_dataset/latent_directions/angle_horizontal.npy')
    gender_direction = np.load('ffhq_dataset/latent_directions/gender.npy')
    eyes_direction = np.load('ffhq_dataset/latent_directions/eyes_open.npy')
    glasses_direction = np.load('ffhq_dataset/latent_directions/glasses.npy')
    smile_direction = np.load('ffhq_dataset/latent_directions/smile.npy')

    # 混合人脸和变化向量,生成变化后的图片
    move_and_show(generator, 0, person, age_direction, [-6, -4, -3, -2, 0, 2, 3, 4, 6])
    move_and_show(generator, 1, person, angle_direction, [-6, -4, -3, -2, 0, 2, 3, 4, 6])
    move_and_show(generator, 2, person, gender_direction, [-6, -4, -3, -2, 0, 2, 3, 4, 6])
    move_and_show(generator, 3, person, eyes_direction, [-3, -2, -1, -0.5, 0, 0.5, 1, 2, 3])
    move_and_show(generator, 4, person, glasses_direction, [-6, -4, -3, -2, 0, 2, 3, 4, 6])
    move_and_show(generator, 5, person, smile_direction, [-3, -2, -1, -0.5, 0, 0.5, 1, 2, 3])


if __name__ == "__main__":
    main()

请注意np.load这句应该改为前面生成的特征码文件 fute_01.npy

安装matplot工具:

pip install matplotlib

将generators-with-stylegan2 工程下的 latent_directions目录复制到 stylegan2encode工程的ffhq_dataset 目录下

python move_and_show.py

可以看到 生成了一串图片:

感觉从老年到孩童的都生成了。虽然老年那张看起来有点别扭。。。

×掉上面的图片,再重新输入 favourate coeff的不同参数:

比如 1.0

会给你做个调整:

-1.0:

0:

张小白在尝试stylegan2的过程中,参考了以下资料中的介绍,并引用了相关的代码,为此对原作者们表示感谢。这些作者们对stylegan2网络都做了深入的分析,有兴趣的童鞋们可以去看他们的博客。

希望大家都能玩转StyleGAN网络!

参考资料清单:

1. 轻轻松松使用StyleGAN 系列

https://blog.csdn.net/weixin_41943311/article/details/100539707 

2.轻轻松松使用StyleGAN2 系列

https://blog.csdn.net/weixin_41943311/article/details/103611827 

3.【阿修】GAN学习笔记(目前是StyleGAN的使用)

https://lucky2018.github.io/ax-learning-gan/ 

4.用StyleGan给自己编码 系列

https://blog.csdn.net/zs858570636/article/details/105237557 

5.自定义数据集上训练StyleGAN | 基于Python+OpenCV+colab实现

https://cloud.tencent.com/developer/article/1815843 

6.nvcc error : 'cudafe++' died with status 0xC0000005 (ACCESS_VIOLATION)

https://blog.csdn.net/DLW__/article/details/104229303 

7.为什么conda 可以安装cuda这种很底层的驱动?

https://www.zhihu.com/question/345172080 

8.科研人必备图像处理软件—ImageJ(安装篇)

https://zhuanlan.zhihu.com/p/54955448 

(全文完,谢谢阅读)

BTW:

下面张小白可能会考虑在ModelArts上跑通这些内容。毕竟在本机乞丐显卡的加持下,有几个运行还是报错的。另外,模型训练也是基本上没法跑的。

登录后可下载附件,请登录或者注册

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区),文章链接,文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:huaweicloud.bbs@huawei.com进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
评论文章 //点赞 收藏 0
点赞
分享文章到微博
分享文章到朋友圈

上一篇:张小白AI博文知识点串烧Ver0.1-20210422

下一篇:张小白手把手教你如何将Tensorflow框架的LeNet模型迁移到昇腾环境

评论 (0)


登录后可评论,请 登录注册

评论