短剧换脸出海的技术复杂性 中我们提到了场景画面中经常同时出现多个人物,如何识别不同人脸,替换为各自的目标人脸 或者是 实现各个人脸的口型对齐,是我们面临的较大挑战。 我们来看个简化的例子,在下图的场景中,我们需要把女主角的人脸替换为选定的目标人脸,我们该如何操作?它可能是一个复杂的处理流程,但通常来说要替换一个对象,首先需要能够先识别需要替换的对象,要替换人脸,自然需要首先能够识别需要替换的人脸。

“识别需要替换的人脸” 就是我们今天要介绍的“人脸识别(face recognition)”技术。

人脸识别 在实际生活中有着丰富的应用场景,如手机的 Face ID 解锁,门禁、支付等各类安全系统的人脸验证等。特别是在监控追踪领域有着广阔的应用前景和应用价值,美剧《疑犯追踪》正在逐步成为现实。

美剧《疑犯追踪》剧照

那么究竟什么是“人脸识别”?人脸识别 就是 识别人脸 啊…hahaha 😜,从字面概念上确实没有太多可解释的,不过相信通过下文的介绍,大家可以对人脸识别相关的技术有更深入的了解。

1. 人脸识别的 Pipeline

1.1 Detect 检测

在一张图片中,通常人脸(如果有的话)只出现在部分区域。“检测”就是指需要准确识别出人脸所在的区域。可以形象理解为需要用个方框把图片中的人脸框出来,如下图所示。 检测步骤是实现人脸识别的第一步,也是最关键的步骤。如果都不能检测出人脸在哪儿,何谈后续的识别。 目前常用的人脸检测方案可以分为两类:

  1. 传统检测方法:深度学习前时代,如 opencv haar-cascade, dlib HOG 等
  2. 现代检测方法:基于深度学习,如 s3fd, SSD, MTCNN, RetinaFace 等

1.1.1 传统检测方法 - 以 HOG 为例

传统检测方法的主要优势在于检测速度快,耗费资源少,从而能够在“低端”设备(如传统的数码相机)上运行。本文中我们会介绍传统检测方法中的 dlib HOG 方法。

HOG, Histogram of Oriented Gradients, 方向梯度直方图 是在 2005 年提出的。由于 HOG 方法并不基于图片颜色数据来检测人脸,所以使用 HOG 方法时,首先需要把图片转换为黑白。

然后,我们将遍历图片中的每一个像素。 对于每个像素,我们检查它周围的其他像素:

比较当前像素与直接围绕它的像素的深度值,画一个箭头(向量)来代表图像变暗的方向:

对图片中的每个像素重复这个过程,最终每个像素都会用一个箭头(向量)表示,这些箭头(向量)称为 梯度(gradients),它们表示了图像中从明亮到黑暗的流动过程。

在实际实现时,保存每个像素的梯度太过于细节化了,有可能捕捉不到图像的整体信息,因此,通常将图像分割成 8x8 或 16x16 的小块,计算每个小块的的主方向梯度,保留指向性最强的那个。最后的结果就是图像的 HOG 表示。

为了在图像的 HOG 表示中,找到人脸,我们需要做的只是与许多脸部照片的平均 HOG 表示进行比较,找出最相似的区域,即为人脸区域,从而成功检测到人脸。

HOG 方法由于其对局部形状信息的有效描述,以及对光照变化的不敏感,在人脸检测领域得到了广泛的应用。但它对姿态变化和遮挡的处理能力有限,因此在应用时,通常会结合面部特征点估计方法等。当前通常也会和现代的深度学习检测方法结合,以提高检测效率和准确率。

1.1.2 现代检测方法

现代基于深度学习的检测方法,核心实现都是基于 CNN 卷积神经网络。卷积神经网络能够学习到图像中的已知结构,比如人脸。 |400

s3fd 人脸检测模型结构如下图所示。实现细节待后续论文阅读补充[#TODO]。 |400

1.2 Align 对齐

在真实世界的应用场景中,人脸图像可能会因为头部的不同姿态(如偏转、倾斜或俯仰)而出现变化。人脸对齐通过旋转、缩放和裁剪等操作,将这些人脸图像调整到一个标准的姿态,从而减少姿态差异对识别性能的影响。Google 在 FaceNet中的研究的表明,通过 Align 操作可以将人脸识别的准确率从98.87% 提升到 99.63%,提升近 1%。下图展示的 旋转操作。

1.3 Normalize 标准化

标准化是指通过 68 个面部特征点(dlib库包含直接可用的 API 来识别这些特征点),标识出下巴和下颌线、眉毛、鼻子、眼睛和嘴唇。

 face landmark | center | 300

基于这些特征点,提取准确的面部区域。这将大大提高人脸识别模型的准确性,因为我们将通过这种方式摒弃其他非脸部的噪音数据。

Transclude of face-recognition-normalize.excalidraw

补充说明:基于面部特征点也可以对人脸进行对齐校正,比如侧脸校正。

1.4 Represent 表示

在上文的 1.1.1 传统检测方法 - 以 HOG 为例 中,我们展示了人脸的 HOG 表示。在当前主流的基于深度学习的方法中,我们如何表示和存储人脸数据呢?又该轮到我们熟悉的 Embedding 出场了。

下图展示了人脸识别分类模型 VGG-Face 的模型结构。由于模型的目标是多分类(2622 类),因此倒数第二层输出是 2622 维,最后一层是 softmax(经过Softmax函数后,所有输出概率的总和为1)。

这里值得注意的是倒数第三层,它的输出是一个 4096 维的 embedding 向量,它即为一个人脸图像的 embedding 向量表示。如下图所示:

目前所有基于深度学习的人脸识别系统,最终都会将人脸转换为 embedding 向量来表示。这样对人脸的识别验证问题就可以转换为 embedding 向量的相似度计算问题。

1.5 Verify 验证

在上一节提到了在得到了人脸的 embedding 向量表示后,我们就可以将人脸的识别验证问题,可以转换为 embedding 向量的相似度计算问题。对于小规模数据量的 embedding 向量相似度计算问题,可以通过计算 Cosine 余弦,Euclidean Distance 欧式距离 等方式求解;但对于较大规模量级的 embedding 向量相似度计算问题,我们通常基于 Facebook Faiss 或 专用的向量数据库(milvusPinecone)等实现。

通过以上公式,我们可以计算得到向量相似度的值,但回到我们的人脸识别验证问题,根据计算得到的值,我们如何判断两个人脸是否是同一个人的或者有多大程度是同一个人的呢?这需要我们确定向量相似度的阈值,只有当大于(或小于)阈值时,我们才认为是同一个人的人脸。阈值的确定 image.png

2. 人脸识别应用实践

我们回到关于 短剧换脸出海 的需求上, 在上文中我们主要介绍了换脸过程中人脸识别相关的技术,换脸目前通过 facefusion等开源方案也可以得到相对还可接受的效果。 但在短剧换脸出海时,还需要解决在多人场景中语音驱动口型对齐的问题。比如如果要对下面的短剧片段中,如果我们要将穿白色裙子的女一号的语音改为英语,由于女一号经常与其他角色同时出现在画面中,因此我们在每一帧画面中我们首先要能精准识别到女一号的人脸,在此基础上才能继续应用语音驱动口型技术。

正如在 短剧换脸出海的技术复杂性 中提到的,上述短剧片段要实现语音驱动口型对齐复杂性过高,我们来看个简化版的例子。 下面的视频片段是两个人正在对谈,并且都是一直正脸出现在视频画面中,这样我们实现分别针对左边人物和右边人物的语音驱动口型对齐时,相比与上述短剧场景要简单很多。

在单人场景中,使用 sd-wav2lip-uhq等开源方案实现视频中人物的语音驱动口型对齐,可以达到较好的效果,具体效果见项目中的示例。那是不是基于 sd-wav2lip-uhq 改造下以支持多人场景呢? 在 sd-wav2lip-uhq 的处理流程中,由于是单人场景,它只需要识别出每帧图像中的人脸区域,然后在该区域应用语音驱动口型对齐技术,并不需要识别出具体是谁的人脸。 在多人场景中,我们需要指定要对哪个人脸应用语音驱动口型对齐,不然像 sd-wav2lip-uhq 方案默认会对找到的第一个人脸应用语音驱动口型对齐 。 所以,改造 sd-wav2lip-uhq 方案以支持多人场景主要工作就是需要找出每帧图像中的所有人脸,并且准确识别要应用语音驱动口型对齐的指定人脸。

具体实现见 sd-wav2lip-uhq-multiple-face。实现效果如下面两个视频所示。

3. 人脸识别开源工具

实现人脸识别的开源工具较多,如 Deepfaceinsightfaceface-recognition,VGG_Face,Google Facenet,OpenFace, Dlib 等。

Deepface是个功能强大的轻量级 Python 库,除了人脸识别功能,还可以进行(实时)人脸属性分析。具体使用示例见:face-recognition-demo-with-deepface.ipynb

参考资料: