本文正在参与「金石计划」

一、前言

在上一篇博客:/post/721068…, 分享了怎么用AutoEncoder生成人脸,在本篇博客,依然围绕人脸来评论。

怎么从一张人脸自然地改换到另一张人脸,或许从年轻渐突变老,运用AutoEncoder能够很容易完成这样的功能。

二、完成原理

AutoEncoder的意图是对输入进行编码,期望这个编码能够很好的还原原有数据。当AutoEncoder练习完成后,咱们能够对恣意的图画进行编码,这样就能够用一个低维的向量表示图片。

那这个低维向量有什么作用呢?假设咱们运用AutoEncoder把图画编码成1024维的向量,通过修正该向量,就能够到达修正图画的作用,可是咱们现在的问题是怎么修正向量。

关于用人脸数据练习的AutoEncoder,如果咱们胡乱修正编码向量,会导致Decoder解码的内容不像人脸。在今日的比方中,需求完成人脸的突变作用。咱们能够把人脸的突变转换成向量的突变,运用插值算法能够很简单的完成向量突变。比方人脸A的向量为z1,人脸B的向量为z2,此时在z1和z2之间插值4个向量,然后把这几个向量用Decoder解码,得到的作用便是人脸突变作用。

比方下面的图片,左上角和右下角的图画是用实在图画的向量解码出来的,而中心的图画则是通过插值算法生成的向量得到的图。即使性别不同也能够很自然的改换。

AutoEncoder实现人脸渐变

三、插值算法

插值算法有许多,这儿选择最简单的线性插值。便是让向量z1每一个都等距离改换,直到改换成向量z2。插值的代码非常简单,详细如下:

def interpolate(x1, x2, num):
    """
    x1:开始向量
    x2:结束向量
    num:最后需求得到的向量个数
    """
    result = torch.zeros((num, *x1.shape))
    step = (x2 - x1) / (num - 1)
    for i in range(num):
        result[i] = x1 + step * i
    return result

这儿能够简单测验一下,代码如下:

x1 = torch.Tensor([1, 0])
x2 = torch.Tensor([0, 1])
out = interpolate(x1, x2, 5)
print(out)

输出结果如下:

tensor([[1.0000, 0.0000],
        [0.7500, 0.2500],
        [0.5000, 0.5000],
        [0.2500, 0.7500],
        [0.0000, 1.0000]])

能够看到,向量x1渐突变成了向量x2。

四、代码完成

接下来就来完成人脸突变的作用。这儿需求用到之前练习的AutoEncoder模型,详细参考博客/post/721068…。 加载练习好的模型,合作插值算法完成人脸突变。

import torch
from torch.utils.data import DataLoader
from torchvision.utils import make_grid
import matplotlib.pyplot as plt
# 加载数据集
dataloader = DataLoader(
    FaceDataset(data_dir='/home/zack/Files/datasets/img_align_celeba', image_size=64),
    batch_size=2
)
model = FaceAutoEncoder()
model.load_state_dict(torch.load('../outputs/face_auto_encoder.pth'))
model.eval()
with torch.no_grad():
    for idx, data in enumerate(dataloader):
        # 对人脸编码
        encoded1 = model.encoder(data[0].reshape((1, 3, 64, 64)))
        encoded2 = model.encoder(data[1].reshape((1, 3, 64, 64)))
        # 对人脸编码进行插值
        encoded = interpolate(encoded1[0], encoded2[0], 64)
        # 解码成人脸
        outputs = model.decoder(encoded).reshape((64, 3, 64, 64))
        outputs = make_grid(outputs, normalize=True)
        plt.imshow(outputs.numpy().transpose((1, 2, 0)))
        plt.show()

其间FaceAutoEncoder和FaceDataset是上一篇博客完成的两个类。下面是几组生成作用:

AutoEncoder实现人脸渐变

在测验中发现,运用练习数据中的图片能够得到比较好的作用,而运用额外图片作用则差一点。

本文正在参与 人工智能创作者扶持计划