购物网站开题报告,wordpress 音乐播放器 歌词,大数据在营销中的应用,做网站有什么市场风险PyTorch深度学习实战#xff08;30#xff09;——Deepfakes 0. 前言1. Deepfakes 原理2. 数据集分析3. 使用 PyTorch 实现 Deepfakes3.1 random_warp.py3.2 Deepfakes.py 小结系列链接 0. 前言
Deepfakes 是一种利用深度学习技术生成伪造视频和图像的技术。它通过将一个人的… PyTorch深度学习实战30——Deepfakes 0. 前言1. Deepfakes 原理2. 数据集分析3. 使用 PyTorch 实现 Deepfakes3.1 random_warp.py3.2 Deepfakes.py 小结系列链接 0. 前言
Deepfakes 是一种利用深度学习技术生成伪造视频和图像的技术。它通过将一个人的脸部特征或动作应用于另一个人的图像或视频中以产生逼真的虚假内容。Deepfakes 技术在短时间内取得了显著的进展并引起了广泛的关注和担忧为了能够更好的采取相应的检测和防御措施我们首先需要了解其基本原理。
1. Deepfakes 原理
我们已经学习了两种不同的图像到图像的转换任务包括使用 UNet 执行语义分割和使用自编码器执行图像重建。 Deepfakes 是与以上任务具有相似理论基础的图像到图像转换的技术。 Deepfakes 是一种利用深度学习技术合成的虚假图像和视频的技术Deepfakes 名称由 “deep learning” 和 “fake” 组成通常用于制作虚假的音频和视频。例如可以利用 Deepfakes 技术将一个人的脸替换到另一个人的身体上。 假设我们想要创建一个应用程序获取给定的面部图像并以期望方式改变面部表情在这种情况下Deepfakes 是一种可行的技术本节中我们将介绍 Deepfakes 的基本原理并使用小样本对抗学习技术生成具有感兴趣面部表情的逼真图像。 在 Deepfakes 任务中我们使用数百张人物 A 的照片和数百张人物 B 的照片。目任务的目标是通过将 A 人物的面部表情应用到 B 人物脸上或者将 B 人物的面部表情应用到 A 人物脸上来重建人物 B 和 A 的脸部特征。Deepfakes 图像生成过程的工作原理如下 在上图中我们通过编码器 (Encoder) 传递人物 A 和人物 B 的图像得到与人物 A (Latent Face A) 和人物 B (Latent Face B) 对应的潜向量将潜向量传递给它们相应的解码器 (Decoder A 和 Decoder B) 以获取相应的原始图像 (Reconstructed Face A 和 Reconstructed Face B)编码器和解码器与自编码器非常相似。但在此任务中我们只需要一个编码器但需要两个解码器(每个解码器对应一个不同的人物)。 我们期望从编码器获得的潜向量表示图像中包含的面部表情信息而解码器获取与人物相对应的图像。一旦编码器和两个解码器都经过训练后在执行deepfakes图像生成时我们按以下方式切换架构中的连接 当 A 人物的潜在向量通过 B 人物的解码器时重建的 B 人物脸部将具有 A 人物的特征反之亦然当 B 人物的潜在向量通过 A 人物的解码器时重建的 A 人物脸部将具有 B 人物的表情。 另一个有助于生成逼真图像的技巧是对人脸图像进行扭曲以这样的方式将其馈送到网络中将扭曲后的人脸作为输入预期的输出是原始图像。
2. 数据集分析
Pins Face Recognition 数据集包含通过 Pinterest 拍摄的图像该数据集包括 100 多个不同人物的 10,000 多张图像每个人物平均包含 100 张图片。 Pins Face Recognition 数据集的目标是推动人脸识别技术的发展并为研究人员提供一个用于测试和比较不同算法性能的标准基准。该数据集中的图像包括不同的人物和背景并且在姿势、光照和表情等方面具有一定的变化。可以通过 Kaggle 网站下载 Pins Face Recognition 数据集并选择两个不同人物的照片作为训练数据集。
3. 使用 PyTorch 实现 Deepfakes
了解了 Deepfakes 的工作原理后我们使用 PyTorch 实现使用自编码器生成将一个人物的表情转换到另一个人物面部的虚假图像。
3.1 random_warp.py
首先编写用于实现图像扭曲的实用脚本 random_warp.py
import numpy as np
import cv2random_transform_args {rotation_range: 10,zoom_range: 0.05,shift_range: 0.05,random_flip: 0.4,
}def get_training_data(images, batch_size):indices np.random.randint(len(images), sizebatch_size)for i, index in enumerate(indices):image images[index]image random_transform(image, **random_transform_args)warped_img, target_img random_warp(image)if i 0:warped_images np.empty((batch_size,) warped_img.shape, warped_img.dtype)target_images np.empty((batch_size,) target_img.shape, warped_img.dtype)warped_images[i] warped_imgtarget_images[i] target_imgreturn warped_images, target_imagesdef random_transform(image, rotation_range, zoom_range, shift_range, random_flip):h, w image.shape[0:2]rotation np.random.uniform(-rotation_range, rotation_range)scale np.random.uniform(1 - zoom_range, 1 zoom_range)tx np.random.uniform(-shift_range, shift_range) * wty np.random.uniform(-shift_range, shift_range) * hmat cv2.getRotationMatrix2D((w // 2, h // 2), rotation, scale)mat[:, 2] (tx, ty)result cv2.warpAffine(image, mat, (w, h), borderModecv2.BORDER_REPLICATE)if np.random.random() random_flip:result result[:, ::-1]return result# get pair of random warped images from aligened face image
def random_warp(image):assert image.shape (256, 256, 3)range_ np.linspace(128 - 80, 128 80, 5)mapx np.broadcast_to(range_, (5, 5))mapy mapx.Tmapx mapx np.random.normal(size(5, 5), scale5)mapy mapy np.random.normal(size(5, 5), scale5)interp_mapx cv2.resize(mapx, (80, 80))[8:72, 8:72].astype(float32)interp_mapy cv2.resize(mapy, (80, 80))[8:72, 8:72].astype(float32)warped_image cv2.remap(image, interp_mapx, interp_mapy, cv2.INTER_LINEAR)src_points np.stack([mapx.ravel(), mapy.ravel()], axis-1)dst_points np.mgrid[0:65:16, 0:65:16].T.reshape(-1, 2)mat umeyama(src_points, dst_points, True)[0:2]target_image cv2.warpAffine(image, mat, (64, 64))return warped_image, target_imagedef umeyama(src, dst, estimate_scale):num src.shape[0]dim src.shape[1]# Compute mean of src and dst.src_mean src.mean(axis0)dst_mean dst.mean(axis0)# Subtract mean from src and dst.src_demean src - src_meandst_demean dst - dst_meanA np.dot(dst_demean.T, src_demean) / numd np.ones((dim,), dtypenp.double)if np.linalg.det(A) 0:d[dim - 1] -1T np.eye(dim 1, dtypenp.double)U, S, V np.linalg.svd(A)rank np.linalg.matrix_rank(A)if rank 0:return np.nan * Telif rank dim - 1:if np.linalg.det(U) * np.linalg.det(V) 0:T[:dim, :dim] np.dot(U, V)else:s d[dim - 1]d[dim - 1] -1T[:dim, :dim] np.dot(U, np.dot(np.diag(d), V))d[dim - 1] selse:T[:dim, :dim] np.dot(U, np.dot(np.diag(d), V.T))if estimate_scale:scale 1.0 / src_demean.var(axis0).sum() * np.dot(S, d)else:scale 1.0T[:dim, dim] dst_mean - scale * np.dot(T[:dim, :dim], src_mean.T)T[:dim, :dim] * scalereturn T3.2 Deepfakes.py
(1) 导入所需库
from random_warp import get_training_data
import cv2
from glob import glob
import numpy as np
from torch.utils.data import DataLoader, Dataset
import random
import torch
import os
from torch import nn
from torch import optim
from matplotlib import pyplot as plt
device cuda if torch.cuda.is_available() else cpu(2) 从图像中提取人脸裁剪图像。
定义人脸级联分类器人脸级联分类器是一种人脸检测方法可以在图像中的面部周围绘制一个边界框
face_cascade cv2.CascadeClassifier(haarcascade_frontalface_default.xml)OpenCV 提供了 4 个级联分类器用于人脸检测可以从 OpenCV 官方下载这些级联分类器文件
haarcascade_frontalface_alt.xml (FA1)haarcascade_frontalface_alt2.xml (FA2)haarcascade_frontalface_alt_tree.xml (FAT)haarcascade_frontalface_default.xml (FD)
可以使用不同的数据集评估这些级联分类器的性能总的来说这些分类器具有相似的准确率。
定义用于从图像中裁剪人脸的函数 crop_face()
def crop_face(img):gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)faces face_cascade.detectMultiScale(gray, 1.3, 5)if(len(faces)0):for (x,y,w,h) in faces:img2 img[y:(yh),x:(xw),:]img2 cv2.resize(img2,(256,256))return img2, Trueelse:return img, False在以上函数中我们通过人脸级联分类器传递灰度图像 gray 并裁剪包含人脸的矩形图像。接下来返回一个重新调整大小的图像 img2。此外为了考虑在图像中没有检测到人脸的情况我们使用一个标志位记录图像中是否检测到人脸。
裁剪 personA 和 personB 的图像并将它们放在不同的文件夹中
if not os.path.exists(cropped_faces_personA):os.mkdir(cropped_faces_personA)
if not os.path.exists(cropped_faces_personB):os.mkdir(cropped_faces_personB)
def crop_images(folder):images glob(folder/*.jpg)for i in range(len(images)):img cv2.imread(images[i], 1)img2, face_detected crop_face(img)if(face_detectedFalse):continueelse:cv2.imwrite(cropped_faces_folder/str(i).jpg,img2)#cv2.cvtColor(img2, cv2.COLOR_RGB2BGR))
crop_images(personA)
crop_images(personB)(3) 创建数据加载器并检查数据
class ImageDataset(Dataset):def __init__(self, items_A, items_B):self.items_A np.concatenate([cv2.cvtColor(cv2.imread(f,1), cv2.COLOR_BGR2RGB)[None] for f in items_A])/255.self.items_B np.concatenate([cv2.cvtColor(cv2.imread(f,1), cv2.COLOR_BGR2RGB)[None] for f in items_B])/255.self.items_A self.items_B.mean(axis(0, 1, 2)) - self.items_A.mean(axis(0, 1, 2))def __len__(self):return min(len(self.items_A), len(self.items_B))def __getitem__(self, ix):a, b random.choice(self.items_A), random.choice(self.items_B)return a, bdef collate_fn(self, batch):imsA, imsB list(zip(*batch))imsA, targetA get_training_data(imsA, len(imsA))imsB, targetB get_training_data(imsB, len(imsB))imsA, imsB, targetA, targetB [torch.Tensor(i).permute(0,3,1,2).to(device) for i in [imsA, imsB, targetA, targetB]]return imsA, imsB, targetA, targetBa ImageDataset(glob(cropped_faces_personA/*.jpg), glob(cropped_faces_personB/*.jpg))
x DataLoader(a, batch_size32, collate_fna.collate_fn)数据加载器返回四个张量imsA、imsB、targetA 和 targetB。第一个张量 imsA 是第三个张量 targetA 的扭曲(变形)版本第二个 imsB 是第四个张量 targetB 的扭曲(变形)版本。 我们使用两个图像文件夹每个人脸图像使用一个文件夹 (a ImageDataset(glob(cropped_faces_personA/*.jpg), glob(cropped_faces_personB/*.jpg)))并且在 __iteritems__ 方法中分别在两个文件夹中随机获取一张人脸图像。 在 collate_fn 方法中的关键函数是 get_training_data用于通过扭曲(变形)人脸图像执行图像增强将扭曲后的人脸图像作为自编码器的输入并尝试预测正常人脸图像。使用扭曲图像不仅增加了训练数据的数量而且还可以作为神经网络的正则化器强制神经网络根据扭曲的人脸图像学习关键的面部特征。
查看示例图像样本
idx 1
imgs next(iter(x))[0]
for i in imgs:plt.subplot(2,4,idx)plt.imshow(i.permute(1,2,0).detach().cpu())idx 1if idx 8:break
plt.show()可以看到输入图像是扭曲人脸图像而输出图像为正常人脸图像且输入与输出图像一一对应。
(4) 构建模型并查看模型架构。
定义卷积 (_ConvLayer) 和反卷积 (_UpScale) 函数以及 Reshape 类
def _ConvLayer(input_features, output_features):return nn.Sequential(nn.Conv2d(input_features, output_features, kernel_size5, stride2, padding2),nn.LeakyReLU(0.1, inplaceTrue))def _UpScale(input_features, output_features):return nn.Sequential(nn.ConvTranspose2d(input_features, output_features, kernel_size2, stride2, padding0),nn.LeakyReLU(0.1, inplaceTrue))class Reshape(nn.Module):def forward(self, input):output input.view(-1, 1024, 4, 4) # channel * 4 * 4return output定义 Autoencoder 模型类它包含一个编码器和两个解码器 (decoder_A 和 decoder_B)
class Autoencoder(nn.Module):def __init__(self):super(Autoencoder, self).__init__()self.encoder nn.Sequential(_ConvLayer(3, 128),_ConvLayer(128, 256),_ConvLayer(256, 512),_ConvLayer(512, 1024),nn.Flatten(),nn.Linear(1024 * 4 * 4, 1024),nn.Linear(1024, 1024 * 4 * 4),Reshape(),_UpScale(1024, 512),)self.decoder_A nn.Sequential(_UpScale(512, 256),_UpScale(256, 128),_UpScale(128, 64),nn.Conv2d(64, 3, kernel_size3, padding1),nn.Sigmoid(),)self.decoder_B nn.Sequential(_UpScale(512, 256),_UpScale(256, 128),_UpScale(128, 64),nn.Conv2d(64, 3, kernel_size3, padding1),nn.Sigmoid(),)def forward(self, x, selectA):if select A:out self.encoder(x)out self.decoder_A(out)else:out self.encoder(x)out self.decoder_B(out)return out(5) 定义 train_batch 函数
def train_batch(model, data, criterion, optimizers):optA, optB optimizersoptA.zero_grad()optB.zero_grad()imgA, imgB, targetA, targetB data_imgA, _imgB model(imgA, A), model(imgB, B)lossA criterion(_imgA, targetA)lossB criterion(_imgB, targetB)lossA.backward()lossB.backward()optA.step()optB.step()return lossA.item(), lossB.item()model(imgA, B) 使用来自 A 类的输入图像返回 B 类的图像根据 imgA 预测 _imgA (其中 imgA 是 targetA 的扭曲版本)并使用 nn.L1Loss 将 _imgA 与 targetA 进行比较在训练期间预测新图像并定性地查看模型训练情况。
(6) 创建训练模型所需的所有组件
model Autoencoder().to(device)dataset ImageDataset(glob(cropped_faces_personA/*.jpg), glob(cropped_faces_personB/*.jpg))
dataloader DataLoader(dataset, 32, collate_fndataset.collate_fn)optimizers optim.Adam([{params: model.encoder.parameters()},{params: model.decoder_A.parameters()}],lr5e-5, betas(0.5, 0.999)), \optim.Adam([{params: model.encoder.parameters()},{params: model.decoder_B.parameters()}], lr5e-5, betas(0.5, 0.999))criterion nn.L1Loss()(7) 训练模型
n_epochs 50000
train_loss_A []
train_loss_B []
if not os.path.exists(checkpoint):os.mkdir(checkpoint)
for ex in range(n_epochs):N len(dataloader)trn_loss_A []trn_loss_B []for bx,data in enumerate(dataloader):lossA, lossB train_batch(model, data, criterion, optimizers)pos (ex (bx1)/N)trn_loss_A.append(lossA)trn_loss_B.append(lossB)train_loss_A.append(np.average(trn_loss_A))train_loss_B.append(np.average(trn_loss_B))if (ex1)%1000 0:state {state: model.state_dict(),epoch: ex}torch.save(state, ./checkpoint/autoencoder.pth)if (ex1)%1000 0:bs 5a,b,A,B data_a model(a[:bs], A)_b model(a[:bs], B)x torch.cat([A[:bs],_a,_b])idx 1for im in x:plt.subplot(3, 5, idx)plt.imshow(im.permute(1,2,0).detach().cpu())idx 1plt.show()_a model(b[:bs], A)_b model(b[:bs], B)x torch.cat([B[:bs],_a,_b])idx 1for im in x:plt.subplot(3, 5, idx)plt.imshow(im.permute(1,2,0).detach().cpu())idx 1plt.show()生成的重建图像如下所示 损失值的变化如下
epochs np.arange(n_epochs)1
plt.plot(epochs, train_loss_A, bo, labelTraining loss A)
plt.plot(epochs, train_loss_B, r-, labelTraining loss B)
plt.title(Training and Test loss over increasing epochs)
plt.xlabel(Epochs)
plt.ylabel(Loss)
plt.legend()
plt.grid(off)
plt.show()如上图所示可以通过调整自编码器使用两个解码器将表情从一张人脸交换到另一张人脸上。此外随着训练的增加重建的图像将变得更加逼真。
小结
Deepfakes 可以用于创造出艺术作品和娱乐内容能够将一个人的表演或特征应用到不同的情境中为电影、视频和游戏等领域带来创新和丰富多样的体验。也可以为电影制片人和视觉特效团队提供了更加高效和经济的方式来实现人物替换和数字化特效。相对于传统的化妆和后期制作技术Deepfakes 可以更快速地生成逼真的效果。因此Deepfakes 具备广泛创造性和应用潜力但也应当研究相应的技术来避免隐私、欺骗和滥用等问题。
系列链接
PyTorch深度学习实战1——神经网络与模型训练过程详解 PyTorch深度学习实战2——PyTorch基础 PyTorch深度学习实战3——使用PyTorch构建神经网络 PyTorch深度学习实战4——常用激活函数和损失函数详解 PyTorch深度学习实战5——计算机视觉基础 PyTorch深度学习实战6——神经网络性能优化技术 PyTorch深度学习实战7——批大小对神经网络训练的影响 PyTorch深度学习实战8——批归一化 PyTorch深度学习实战9——学习率优化 PyTorch深度学习实战10——过拟合及其解决方法 PyTorch深度学习实战11——卷积神经网络 PyTorch深度学习实战12——数据增强 PyTorch深度学习实战13——可视化神经网络中间层输出 PyTorch深度学习实战14——类激活图 PyTorch深度学习实战15——迁移学习 PyTorch深度学习实战16——面部关键点检测 PyTorch深度学习实战17——多任务学习 PyTorch深度学习实战18——目标检测基础 PyTorch深度学习实战19——从零开始实现R-CNN目标检测 PyTorch深度学习实战20——从零开始实现Fast R-CNN目标检测 PyTorch深度学习实战21——从零开始实现Faster R-CNN目标检测 PyTorch深度学习实战22——从零开始实现YOLO目标检测 PyTorch深度学习实战23——使用U-Net架构进行图像分割 PyTorch深度学习实战24——从零开始实现Mask R-CNN实例分割 PyTorch深度学习实战25——自编码器(Autoencoder) PyTorch深度学习实战26——卷积自编码器(Convolutional Autoencoder) PyTorch深度学习实战27——变分自编码器(Variational Autoencoder, VAE) PyTorch深度学习实战28——对抗攻击(Adversarial Attack) PyTorch深度学习实战29——神经风格迁移