深度伪造技术是当今AI领域最引人入胜且令人担忧的应用之一。虽然深度伪造可以用于合法目的,但它也可能被用于散布虚假信息。有了轻易将某人的面孔替换到任何视频中的能力,真的能相信眼睛所看到的吗?一个看似真实的视频,显示政治家或演员做了或说了令人震惊的事情,可能根本不是真的。
在本系列文章中,将展示深度伪造是如何工作的,并展示如何从头开始实现它们。然后,将看看DeepFaceLab,这是一个常用的、由Tensorflow驱动的一站式工具,用于创建令人信服的深度伪造。
在之前的文章中,讨论了很多理论,但现在是时候进入实际代码,让这个项目工作了!在本文中,将指导完成将源(src)和目标(dst)视频转换为实际图像,准备输入到自动编码器中所需的步骤。如果不熟悉这些术语,建议快速阅读之前的文章以获得一些上下文。
数据集由四个带有创意共享署名许可的视频组成,因此可以重用或修改它们。这个数据集包含两个源个体的视频和两个目标个体的视频。可以在这里找到数据集。将要解释的笔记本在这里。在Kaggle笔记本上进行了这个阶段的预处理,但如果有一个强大的GPU,可以很容易地在本地运行项目。让深入代码!
让从导入所需的库和创建将要使用的目录开始:
import cv2
import pandas as pd
import os
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
!pip install mtcnn
from mtcnn import MTCNN
!cd /kaggle/working/
!mkdir frames_1
!mkdir frames_2
!mkdir frames_3
!mkdir frames_4
!mkdir results_1
!mkdir results_2
正如在第一篇文章中可能记得的,提到需要将视频转换为图像,这样就可以提取个体帧中的面部,最后用它们来训练模型。在这一步中,将使用OpenCV,这是一个在这类任务中广泛使用的计算机视觉库,来提取组成视频的图像。让开始实践:
定义视频所在的位置以及输出将被保存的位置(如果需要,请修改它们):
input_1 = '/kaggle/input/presidentsdataset/presidents/trump1.mp4'
input_2 = '/kaggle/input/presidentsdataset/presidents/trump2.mp4'
input_3 = '/kaggle/input/presidentsdataset/presidents/biden1.mp4'
input_4 = '/kaggle/input/presidentsdataset/presidents/biden2.mp4'
output_1 = '/kaggle/working/frames_1/'
output_2 = '/kaggle/working/frames_2/'
output_3 = '/kaggle/working/frames_3/'
output_4 = '/kaggle/working/frames_4/'
定义将用于提取帧的函数:
def extract_frames(input_path, output_path):
videocapture = cv2.VideoCapture(input_path)
success, image = videocapture.read()
count = 0
while success:
cv2.imwrite(output_path + "frame%d.jpg" % count, image)
success, image = videocapture.read()
count += 1
return count
提取帧:
total_frames_1 = extract_frames(input_1, output_1)
total_frames_2 = extract_frames(input_2, output_2)
total_frames_3 = extract_frames(input_3, output_3)
total_frames_4 = extract_frames(input_4, output_4)
确定每个视频提取了多少帧:
print('Total frames extracted in video 1:', total_frames_1)
print('Total frames extracted in video 2:', total_frames_2)
print('Total frames extracted in video 3:', total_frames_3)
print('Total frames extracted in video 4:', total_frames_4)
最后的输出意味着为源个体有1701和1875帧,第二个个体有1109和1530帧。这是一个很好的图像数量,可以训练模型。如果想绘制src个体的一帧,只需运行:
%matplotlib inline
plt.figure()
image = cv2.imread('/kaggle/working/frames_1/frame1.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image = image.astype('float32')
image /= 255.0
plt.imshow(image)
plt.show()
它将显示这个:
绘制目标个体的一帧:
%matplotlib inline
plt.figure()
image = cv2.imread('/kaggle/working/frames_3/frame1.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
plt.imshow(image)
plt.show()
现在已经获得了所有的帧,是时候从中提取面部了。为此,首先检测面部的位置,然后裁剪它以保存为新文件。将使用MTCNN检测器,这是一个专门为面部检测开发的Python库。
使用他们的一个示例,这是它的面部检测看起来的样子:
将使用他们的脚本作为基础代码,从帧中提取面部,但正如看到的,检测器并不考虑整个面部。下颌、部分前额和颧骨没有包括在内,所以将采取MTCNN检测,并添加一些额外的填充,以在裁剪之前得到整个面部在一个正方形中,然后生成一个新的图像。运行以下行:
def extract_faces(source_1, source_2, destination, detector):
counter = 0
for dirname, _, filenames in os.walk(source_1):
for filename in filenames:
try:
image = cv2.imread(os.path.join(dirname, filename))
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
detections = detector.detect_faces(image)
x, y, width, height = detections[0]['box']
x1, y1, x2, y2 = x-10, y+10, x-10+width+20, y+10+height
face = image[y1:y2, x1:x2]
face = cv2.resize(face, (120, 120), interpolation=cv2.INTER_LINEAR)
plt.imsave(os.path.join(destination, str(counter)+'.jpg'), face)
print('Saved:', os.path.join(destination, str(counter)+'.jpg'))
except:
pass
counter += 1
for dirname, _, filenames in os.walk(source_2):
for filename in filenames:
try:
image = cv2.imread(os.path.join(dirname, filename))
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
detections = detector.detect_faces(image)
x, y, width, height = detections[0]['box']
x1, y1, x2, y2 = x-10, y+10, x-10+width+20, y+10+height
face = image[y1:y2, x1:x2]
face = cv2.resize(face, (120, 120), interpolation=cv2.INTER_LINEAR)
plt.imsave(os.path.join(destination, str(counter)+'.jpg'), face)
print('Saved:', os.path.join(destination, str(counter)+'.jpg'))
except:
pass
counter += 1
detector = MTCNN()
extract_faces('/kaggle/working/frames_1/', '/kaggle/working/frames_2/', '/kaggle/working/results_1/', detector)
extract_faces('/kaggle/working/frames_3/', '/kaggle/working/frames_4/', '/kaggle/working/results_2/', detector)
Python Saved: /kaggle/working/results_1/0.jpg Saved: /kaggle/working/results_1/1.jpg Saved: /kaggle/working/results_1/2.jpg Saved: /kaggle/working/results_1/3.jpg Saved: /kaggle/working/results_1/4.jpg ...
最终结果应该是在results_1和results_2中保存了几张面部图像,每个文件夹包含相应个体的面部。可能已经注意到将所有面部调整为120x120的尺寸。这是为了避免在构建模型和定义输入形状时发生任何冲突。
要绘制一张面部并给一个它被提取后的样子的想法,运行以下命令:
%matplotlib inline
plt.figure()
image = cv2.imread('/kaggle/working/results_1/700.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
plt.imshow(image)
plt.show()
它将绘制这个:
注意图像显示了个体面部的更广泛范围。这将对以后交换面部非常有帮助,但它也将帮助达到模型训练中更低的错误。如果像一样在Kaggle笔记本中遵循这些步骤,发出以下命令,然后更容易地下载文件:
!zip -r /kaggle/working/trump_faces.zip /kaggle/working/results_1/
!zip -r /kaggle/working/biden_faces.zip /kaggle/working/results_2/