• 想知道你未来宝宝长什么样吗?


    摘要:本案例可根据一张父亲和母亲的正脸照片,生成孩子的照片,并且可以调节参数,看看不同性别和年龄孩子的长相。

    本文分享自华为云社区《BabyGAN:根据父母照片生成孩子照片》,作者: 山海之光。

    本案例可根据一张父亲和母亲的正脸照片,生成孩子的照片,并且可以调节参数,看看不同性别和年龄孩子的长相。

    为保证照片的生成效果,上传父母的照片时尽量上传能露出五官且浅色底的照片。

    本案例仅用于学习交流,请勿用于其他用途。

    另外,由于技术不完善的原因,生成的孩子照片可能会有扭曲或失真,你可以更换不同的父母照片,重新生成孩子照片,直到达到满意的生成效果为止。

    下面开始按步骤运行本案例。

    1. 安装所需的模块

    本步骤耗时约4分钟

    !pip install imutils moviepy dlib

    2. 下载代码和模型文件

    1. import os
    2. import moxing as mox
    3. root_dir = '/home/ma-user/work/ma_share/'
    4. code_dir = os.path.join(root_dir, 'BabyGAN')
    5. if not os.path.exists(os.path.join(root_dir, 'BabyGAN.zip')):
    6. mox.file.copy('obs://arthur-1/BabyGAN/BabyGAN.zip', os.path.join(root_dir, 'BabyGAN.zip'))
    7. os.system('cd %s; unzip BabyGAN.zip' % root_dir)
    8. os.chdir(code_dir)

    3. 加载相关模块及模型

    1. import cv2
    2. import math
    3. import pickle
    4. import imageio
    5. import warnings
    6. import PIL.Image
    7. import numpy as np
    8. from glob import glob
    9. from PIL import Image
    10. import tensorflow as tf
    11. from random import randrange
    12. import moviepy.editor as mpy
    13. import matplotlib.pyplot as plt
    14. from IPython.display import clear_output
    15. from moviepy.video.io.ffmpeg_writer import FFMPEG_VideoWriter
    16. import config
    17. import dnnlib
    18. import dnnlib.tflib as tflib
    19. from encoder.generator_model import Generator
    20. %matplotlib inline
    21. warnings.filterwarnings("ignore")

    加载模型文件,本代码块只可执行一次,如果发生报错,请restart kernel,重新运行所有代码

    1. tflib.init_tf()
    2. URL_FFHQ = "./karras2019stylegan-ffhq-1024x1024.pkl"
    3. with dnnlib.util.open_url(URL_FFHQ, cache_dir=config.cache_dir) as f:
    4. generator_network, discriminator_network, Gs_network = pickle.load(f)
    5. generator = Generator(Gs_network, batch_size=1, randomize_noise=False)
    6. model_scale = int(2 * (math.log(1024, 2) - 1))
    7. age_direction = np.load('./ffhq_dataset/latent_directions/age.npy')
    8. horizontal_direction = np.load('./ffhq_dataset/latent_directions/angle_horizontal.npy')
    9. vertical_direction = np.load('./ffhq_dataset/latent_directions/angle_vertical.npy')
    10. eyes_open_direction = np.load('./ffhq_dataset/latent_directions/eyes_open.npy')
    11. gender_direction = np.load('./ffhq_dataset/latent_directions/gender.npy')
    12. smile_direction = np.load('./ffhq_dataset/latent_directions/smile.npy')
    13. def get_watermarked(pil_image: Image) -> Image:
    14. try:
    15. image = cv2.cvtColor(np.array(pil_image), cv2.COLOR_RGB2BGR)
    16. (h, w) = image.shape[:2]
    17. image = np.dstack([image, np.ones((h, w), dtype="uint8") * 255])
    18. pct = 0.08
    19. full_watermark = cv2.imread('./media/logo.png', cv2.IMREAD_UNCHANGED)
    20. (fwH, fwW) = full_watermark.shape[:2]
    21. wH = int(pct * h * 2)
    22. wW = int((wH * fwW) / fwH * 0.1)
    23. watermark = cv2.resize(full_watermark, (wH, wW), interpolation=cv2.INTER_AREA)
    24. overlay = np.zeros((h, w, 4), dtype="uint8")
    25. (wH, wW) = watermark.shape[:2]
    26. overlay[h - wH - 10: h - 10, 10: 10 + wW] = watermark
    27. output = image.copy()
    28. cv2.addWeighted(overlay, 0.5, output, 1.0, 0, output)
    29. rgb_image = cv2.cvtColor(output, cv2.COLOR_BGR2RGB)
    30. return Image.fromarray(rgb_image)
    31. except:
    32. return pil_image
    33. def generate_final_images(latent_vector, direction, coeffs, i):
    34. new_latent_vector = latent_vector.copy()
    35. new_latent_vector[:8] = (latent_vector + coeffs * direction)[:8]
    36. new_latent_vector = new_latent_vector.reshape((1, 18, 512))
    37. generator.set_dlatents(new_latent_vector)
    38. img_array = generator.generate_images()[0]
    39. img = PIL.Image.fromarray(img_array, 'RGB')
    40. if size[0] >= 512: img = get_watermarked(img)
    41. img_path = "./for_animation/" + str(i) + ".png"
    42. img.thumbnail(animation_size, PIL.Image.ANTIALIAS)
    43. img.save(img_path)
    44. face_img.append(imageio.imread(img_path))
    45. clear_output()
    46. return img
    47. def generate_final_image(latent_vector, direction, coeffs):
    48. new_latent_vector = latent_vector.copy()
    49. new_latent_vector[:8] = (latent_vector + coeffs * direction)[:8]
    50. new_latent_vector = new_latent_vector.reshape((1, 18, 512))
    51. generator.set_dlatents(new_latent_vector)
    52. img_array = generator.generate_images()[0]
    53. img = PIL.Image.fromarray(img_array, 'RGB')
    54. if size[0] >= 512: img = get_watermarked(img)
    55. img.thumbnail(size, PIL.Image.ANTIALIAS)
    56. img.save("face.png")
    57. if download_image == True: files.download("face.png")
    58. return img
    59. def plot_three_images(imgB, fs=10):
    60. f, axarr = plt.subplots(1, 3, figsize=(fs, fs))
    61. axarr[0].imshow(Image.open('./aligned_images/father_01.png'))
    62. axarr[0].title.set_text("Father's photo")
    63. axarr[1].imshow(imgB)
    64. axarr[1].title.set_text("Child's photo")
    65. axarr[2].imshow(Image.open('./aligned_images/mother_01.png'))
    66. axarr[2].title.set_text("Mother's photo")
    67. plt.setp(plt.gcf().get_axes(), xticks=[], yticks=[])
    68. plt.show()

    4. 准备好父亲和母亲的照片

    本案例已各准备好一张默认的父母亲照片,可在左侧边栏的文件资源管理窗口中,进入到 ma_share/BabyGAN 目录,再进入到 father_image 或 mother_image 目录即可看到已提供的父母亲照片,如下图所示:

    如果你需更换父母亲的照片,请查看本文第11节“更换父亲和母亲的照片”

    1. if len(glob(os.path.join('./father_image', '*.jpg'))) != 1 or (not os.path.exists('./father_image/father.jpg')):
    2. raise Exception('请在 ma_share/BabyGAN/father_image 目录下准备一张父亲的照片,且命名为father.jpg')
    3. if len(glob(os.path.join('./mother_image', '*.jpg'))) != 1 or (not os.path.exists('./mother_image/mother.jpg')):
    4. raise Exception('请在 ma_share/BabyGAN/father_image 目录下准备一张母亲的照片,且命名为mother.jpg')

    5. 获取父亲的脸部区域,并进行人脸对齐

    !python align_images.py ./father_image ./aligned_images

    查看父亲的人脸

    1. if os.path.isfile('./aligned_images/father_01.png'):
    2. pil_father = Image.open('./aligned_images/father_01.png')
    3. (fat_width, fat_height) = pil_father.size
    4. resize_fat = max(fat_width, fat_height) / 256
    5. display(pil_father.resize((int(fat_width / resize_fat), int(fat_height / resize_fat))))
    6. else:
    7. raise ValueError('No face was found or there is more than one in the photo.')

    6. 获取母亲的脸部区域,并进行人脸对齐

    !python align_images.py ./mother_image ./aligned_images

    查看母亲的人脸

    1. if os.path.isfile('./aligned_images/mother_01.png'):
    2. pil_mother = Image.open('./aligned_images/mother_01.png')
    3. (mot_width, mot_height) = pil_mother.size
    4. resize_mot = max(mot_width, mot_height) / 256
    5. display(pil_mother.resize((int(mot_width / resize_mot), int(mot_height / resize_mot))))
    6. else:
    7. raise ValueError('No face was found or there is more than one in the photo.')

    7. 提取人脸特征

    本步骤耗时约3分钟

    1. !python encode_images.py \
    2. --early_stopping False \
    3. --lr=0.25 \
    4. --batch_size=2 \
    5. --iterations=100 \
    6. --output_video=False \
    7. ./aligned_images \
    8. ./generated_images \
    9. ./latent_representations
    10. if len(glob(os.path.join('./generated_images', '*.png'))) == 2:
    11. first_face = np.load('./latent_representations/father_01.npy')
    12. second_face = np.load('./latent_representations/mother_01.npy')
    13. print("Generation of latent representation is complete! Now comes the fun part.")
    14. else:
    15. raise ValueError('Something wrong. It may be impossible to read the face in the photos. Upload other photos and try again.')

    8. 生成一家三口照片

    请修改下面代码中的 gender_influence 和 person_age参数,

    gender_influence:性别影响因子,取值范围[0.01, 0.99],取值越接近0,父亲的容貌影响越大,反之母亲影响越大;

    person_age:年龄影响因子,取值范围[10, 50],设置该值后,将生成对应年龄的小孩的容貌。

    每次修改该参数值后,重新运行下面的代码块,即可生成孩子的新照片

    1. genes_influence = 0.8 # 性别影响因子,取值范围[0.01, 0.99],取值越接近0,父亲的容貌影响越大,反之母亲影响越大
    2. person_age = 10 # 年龄影响因子,取值范围[10, 50],设置该值后,将生成对应年龄的小孩的容貌
    3. style = "Default"
    4. if style == "Father's photo":
    5. lr = ((np.arange(1, model_scale + 1) / model_scale) ** genes_influence).reshape((model_scale, 1))
    6. rl = 1 - lr
    7. hybrid_face = (lr * first_face) + (rl * second_face)
    8. elif style == "Mother's photo":
    9. lr = ((np.arange(1, model_scale + 1) / model_scale) ** (1 - genes_influence)).reshape((model_scale, 1))
    10. rl = 1 - lr
    11. hybrid_face = (rl * first_face) + (lr * second_face)
    12. else:
    13. hybrid_face = ((1 - genes_influence) * first_face) + (genes_influence * second_face)
    14. intensity = -((person_age / 5) - 6)
    15. resolution = "512"
    16. size = int(resolution), int(resolution)
    17. download_image = False
    18. face = generate_final_image(hybrid_face, age_direction, intensity)
    19. plot_three_images(face, fs=15)

    9. 查看孩子各年龄段的容貌

    请修改下面代码中的 gender_influence 参数,该参数是性别影响因子,取值范围[0.01, 0.99],取值越接近0,父亲的容貌影响越大,反之母亲影响越大。

    每次修改该参数值后,要重新运行下面的代码块

    1. gender_influence = 0.8 # 性别影响因子,取值范围[0.01, 0.99],取值越接近0,父亲的容貌影响越大,反之母亲影响越大
    2. !rm -rf ./for_animation
    3. !mkdir ./for_animation
    4. face_img = []
    5. hybrid_face = ((1 - gender_influence) * first_face) + (gender_influence * second_face)
    6. animation_resolution = "512"
    7. animation_size = int(animation_resolution), int(animation_resolution)
    8. frames_number = 50
    9. download_image = False
    10. for i in range(0, frames_number, 1):
    11. intensity = (8 * (i / (frames_number - 1))) - 4
    12. generate_final_images(hybrid_face, age_direction, intensity, i)
    13. clear_output()
    14. print(str(i) + " of {} photo generated".format(str(frames_number)))
    15. for j in reversed(face_img):
    16. face_img.append(j)
    17. automatic_download = False
    18. if gender_influence <= 0.3:
    19. animation_name = "boy.mp4"
    20. elif gender_influence >= 0.7:
    21. animation_name = "girl.mp4"
    22. else:
    23. animation_name = "animation.mp4"
    24. imageio.mimsave('./for_animation/' + animation_name, face_img)
    25. clear_output()
    26. display(mpy.ipython_display('./for_animation/' + animation_name, height=400, autoplay=1, loop=1))

    10. 查看孩子不同性别的容貌

    请修改下面代码中的 person_age 参数,该参数是年龄影响因子,取值范围[10, 50],设置该值后,将生成对应年龄的小孩的容貌。

    每次修改该参数值后,要重新运行下面的代码块

    1. person_age = 10 # 小孩的年龄,取值范围[10, 50],设置该值后,将生成对应年龄的小孩的容貌
    2. !rm -rf ./for_animation
    3. !mkdir ./for_animation
    4. face_img = []
    5. intensity = -((person_age / 5) - 6)
    6. animation_resolution = "512"
    7. animation_size = int(animation_resolution), int(animation_resolution)
    8. frames_number = 50 # 容貌变化的图像数,取值范围[10, 50]
    9. download_image = False
    10. for i in range(1, frames_number):
    11. gender_influence = i / frames_number
    12. hybrid_face = ((1 - gender_influence) * first_face) + (gender_influence * second_face)
    13. face = generate_final_images(hybrid_face, age_direction, intensity, i)
    14. clear_output()
    15. print(str(i) + " of {} photo generated".format(str(frames_number)))
    16. for j in reversed(face_img):
    17. face_img.append(j)
    18. animation_name = str(person_age) + "_years.mp4"
    19. imageio.mimsave('./for_animation/' + animation_name, face_img)
    20. clear_output()
    21. display(mpy.ipython_display('./for_animation/' + animation_name, height=400, autoplay=1, loop=1))

    11. 更换父亲和母亲的照片

    接下来,你可以上传自己感兴趣的父母亲照片到father_image 和 mother_image目录下,重新运行代码,即可生成新的孩子照片。

    你需要按照如下规则和步骤进行:

    1、参考下图的操作,进入到 ma_share/BabyGAN 目录;

    2、准备一张父亲的照片,上传到 father_image 目录下,命名必须为father.jpg;(如果你不知道上传文件到 JupyterLab 的方法,请查看此文档

    3、准备一张母亲的照片,上传到 mother_image 目录下,命名必须为mother.jpg;

    4、father_image 和 mother_image目录都只允许存在一张照片;

    5、重新运行步骤4~10的代码。

    点击关注,第一时间了解华为云新鲜技术~

  • 相关阅读:
    【PAT(甲级)】1046 Shortest Distance(距离分析)
    黑盒测试与白盒测试
    若依框架使用mars3d的环境配置,地球构建
    zabbix自定义模板,邮件报警,代理服务器,自动发现与自动添加及snmp
    全网echarts案例资源大总结和echarts的高效使用技巧(细节版)
    RabbitMQ的六种工作模式
    探店通系统源码,短视频矩阵源码独立部署,look here
    web前端期末大作业——基于Bootstrap响应式汽车经销商4S店官网21页
    成功案例 | 安超云助力兰州大学第二医院搭建新型IT基础设施平台 提升医疗信息资源利用率
    oradebug current_sql
  • 原文地址:https://blog.csdn.net/devcloud/article/details/119818603