轻轻松松使用StyleGAN(七):用StyleGAN Encoder为女朋友制作美丽头像

在上一篇文章里,我们下载了StyleGAN Encoder的源代码和相关资源,可以实现对真实人脸特征码的提取,内容请参考:

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

那么,针对我们感兴趣的话题,如何用StyleGAN Encoder为女朋友制作美丽头像呢?这里的美丽头像,一定不能等同于美图秀秀和抖音里面的美颜、滤镜、瘦脸,这样才能显示出Python程序员的与众不同,那么应该怎么做呢?

(1)先找到女朋友喜爱的明星,提取明星照片的特征码,比如:

奥黛丽·赫本原图                                 对齐的头像原图                  用特征码生成的赫本头像

       

可以看出,用特征码生成的赫本头像,与头像原图相当接近,尤其是面部细节几乎一模一样,但是首饰的细节未能生成,包括:公主皇冠、耳坠等,也许今后哪一天能找到一个补丁,可以逼真地生成首饰和衣饰的细节吧。

林允儿原图                                         对齐的头像原图                    用特征码生成的林允儿头像                

       

用特征码生成的林允儿头像,因为没有首饰,所以看起来与原图十分相似。

(2)把女朋友的照片特征码也提取出来,方法同(1);

(3)把用明星的特征码修饰女朋友的照片特征码,从多张美颜照片中找到比较接近本人且更加生动、美丽的头像,然后找机会发给她吧!

女朋友本人原图                       徐静蕾+美颜                            杨幂+美颜

      

可以看到,用明星特征码修饰过的照片会让女朋友显得更有气质,而且生成的图片(1024x1024)纹理通常也比原始的头像截图更为细腻。

那么问题来了,如果女朋友是个眼镜妹呢?让我们再来看一看效果:

眼镜妹本人原图                       徐静蕾+美颜                            杨幂+美颜                                

        

那么,亲爱的程序员,你看过这些美丽的头像,有没有一点点动心呢?

你所需要的,只是StyleGAN Encoder(当然,要先安装cuda/cudnn/dlib/tensorflow-gpu/pillow等,感兴趣地可以翻看博主前面的文章),以及一块内存超过11GB的显卡而已(推荐:NVIDIA Geforce GTX 2080Ti以上)。

完整的操作命令及源代码如下(带中文注释):

(1)从原始照片中找到对齐的人脸头像:

python align_images.py raw_images/ aligned_images/

(2)从对齐的人脸头像提取特征码并生成StyleGAN头像:

python encode_images.py aligned_images/ generated_images/ latent_representations/ --iterations 300 --use_mssim_loss 300

(3)用明星特征码修饰女朋友的照片特征码,并生成混合后的StyleGAN头像,源代码(带中文注释)如下:

import os
import pickle
import numpy as np
import PIL.Image
import dnnlib
import dnnlib.tflib as tflib
import config
import glob

#----------------------------------------------------------------------------
# Helpers for loading and using pre-trained generators.

# pre-trained network.
Model = './models/karras2019stylegan-ffhq-1024x1024.pkl'
Style_No = 7

synthesis_kwargs = dict(output_transform=dict(func=tflib.convert_images_to_uint8, nchw_to_nhwc=True), minibatch_size=8)
_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]


# Changing Style
# 用目标图像的src_dlatents的一部分替换原图像的dst_dlatents的对应部分,
# 然后用Gs.components.synthesis.run()函数生成风格混合后的图像

def change_style_figure(png, Gs, w, h, style_ranges):
    print(png)
    os.makedirs(config.dlatents_dir, exist_ok=True)

    src = np.load(os.path.join(config.dlatents_dir, 'jinglei_01.npy'))
    dst = np.load(os.path.join(config.dlatents_dir, 'girl_01.npy'))

    src_dlatents = np.stack(src for i in range(Style_No))
    dst_dlatents = np.expand_dims(dst, axis=0)

    # 从dlatents生成图像
    src_images = Gs.components.synthesis.run(src_dlatents, randomize_noise=False, **synthesis_kwargs)
    dst_images = Gs.components.synthesis.run(dst_dlatents, randomize_noise=False, **synthesis_kwargs)

    # 画空白图
    canvas = PIL.Image.new('RGB', (w * (Style_No + 1), h * (len(dst_images) + 1)), 'white')

    # 在画布的第一行画源图像,第一格空白
    for col, src_image in enumerate(list(src_images)):
        canvas.paste(PIL.Image.fromarray(src_image, 'RGB'), ((col + 1) * w, 0))

    # 在画布逐行绘制图像
    for row, dst_image in enumerate(list(dst_images)):

        # 首列绘制目标图像
        canvas.paste(PIL.Image.fromarray(dst_image, 'RGB'), (0, (row + 1) * h))

        # 将目标图像复制N份,构成新数组
        row_dlatents = np.stack([dst_dlatents[row]] * Style_No)

        # 用src_dlatents的指定列替换row_dlatents的指定列,数据混合
        for i in range(Style_No):
            row_dlatents[i, style_ranges[i]] = src_dlatents[i, style_ranges[i]]

        # 调用用Gs.components.synthesis.run()函数生成风格混合后的图像
        row_images = Gs.components.synthesis.run(row_dlatents, randomize_noise=False, **synthesis_kwargs)

        # 在画布上逐列绘制风格混合后的图像
        for col, image in enumerate(list(row_images)):
            canvas.paste(PIL.Image.fromarray(image, 'RGB'), ((col + 1) * w, (row + 1) * h))

    canvas.save(png)


# Main program.

def main():
    tflib.init_tf()
    os.makedirs(config.generated_dir, exist_ok=True)

    change_style_figure(os.path.join(config.generated_dir, 'change-style-figure.png'), load_Gs(Model), w=1024, h=1024, \
                        style_ranges=[range(3,4)]+[range(4,5)]+[range(5,6)]+[range(6,7)]+[range(7,8)] \
                        +[range(8,9)]+[range(9,10)])

 #----------------------------------------------------------------------------

if __name__ == "__main__":
    main()

同时,config.py也要稍微添加一点东东:

# Paths.

dlatents_dir = 'latent_representations'
generated_dir = 'generated_images'
result_dir = 'results'
data_dir = 'datasets'
cache_dir = 'cache'
run_dir_ignore = ['results', 'datasets', 'cache']

# experimental - replace Dense layers with TreeConnect
use_treeconnect = False
treeconnect_threshold = 1024

下一篇:

轻轻松松使用StyleGAN(八):StyleGAN Encoder的align_images.py代码解析+中文注释 

(完)

发布了32 篇原创文章 · 获赞 75 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_41943311/article/details/103348865