
鉴于最近利用人工智能的应用程序激增,用于模型训练的大型数据集变得越来越重要。当我们考虑使用录制的视频作为培训材料时,重要的是要考虑诸如《通用数据保护条例》(GDPR)之类的法规,这些法规要求在镜头中看到的所有个人的同意或内容的匿名化。
然而,获得许多人的许可并不总是实用的,并且手动模糊每一帧中的人脸都是劳动密集型的。不幸的是,博客中讨论的许多自动化方法或 GitHub 上可用的方法都缺乏准确性和/或性能。
在处理初创公司使用有限资源处理大量高清质量帧的常见场景时,这尤其成问题。在这种情况下,可靠和有效的方法至关重要。
在本文中,我们将仔细研究我最近使用的一个简单的 Python 方法,为什么我使用它,以及为什么你也应该使用它。
为什么匿名很重要
随着高质量视频数据和强大的人工智能模型的日益普及,人们越来越担心个人信息可以从看似无害的镜头中提取出来。包含可识别人脸的视频数据可能会以多种方式被滥用。一个突出的例子是法庭上使用的深度伪造。
还有另一个重要因素:在有偏见或不公平标记的数据上训练的人工智能模型可以使现有的偏见永久化。匿名人脸有助于确保这些偏差不会由于种族、性别、年龄等因素而通过训练数据引入。这在执法或招聘等应用中尤其重要,在这些应用中,有偏见的模型可能会产生严重的现实后果。
“我来这里学习如何从视频中删除敏感信息”
...亚达亚达亚达,让我们切入正题。
了解图像和模式识别
我们希望读取视频数据,找到每帧的所有人脸并用修改后的内容替换它们。此内容可能涉及高斯模糊等技术,甚至是合成图像,从而有助于生成多样化的训练数据。

生成高质量的图像数据可能很棘手
无论使用何种工具,该过程始终相同:
- 从视频流或文件中读取图像数据
- 对图像数据执行人脸检测
- 提取所有人脸的感兴趣区域 (ROI)
- 匿名化每个投资回报率
- 返回更新的数据
- 重复该过程直到文件结束
为了更好地了解我们需要做什么,我们应该首先看看我们看到了什么以及我们的计算机看到了什么。
我们看到了什么
当我们看图像时,我们的大脑会识别模式并将模式与我们知道的物体进行比较。这就是我们如何知道我们看到的是一个人(或任何其他物体,就此而言)。您可能知道,这种认识有时可能很困难。例如。当一个物体被部分覆盖,或者你从一个你不习惯的角度看它时。

反射使事情变得棘手
请记住:模式识别取决于训练。也就是说,我们见过一个物体多少次?我们见过多少次物体的变化(不同的视角、照明等)?
如果你一生中只见过一只狗和一只狐狸,当你看到不同的狗和狐狸时,你就不会很好地识别它们。你也不会很擅长区分狗和狐狸。犬类专家可能见过数千只狗,因此可以在眨眼间识别任何狗,同时还知道它的品种和大致年龄。
我们的计算机看到了什么
对于计算机(至少是更常见的计算机),图像本质上是一个 2D 矩阵,由表示像素颜色强度的值组成。如果您对更详细的解释感兴趣,请查看这篇阐述概念的精彩文章。
此外,重要的是要记住计算机缺乏上下文理解。与人类不同,我们不能轻易地传达诸如“我正在寻找狗”(是的,又是狗)之类的概念,这意味着我们不能简单地让计算机意识到我们正在寻找图像中的“有毛皮和尾巴的四足生物”。

图像作为像素值矩阵
这就是人工智能——更准确地说,神经网络——发挥作用的地方。如今,我们可以训练一个模型来解释像素值的2D矩阵,类似于我们的大脑。我们向计算机提供一个矩阵,并说“这是一只狗”。在我们多次使用不同的图像执行此操作后,我们可以提供我们没有用于训练的值,并询问“这是一只狗吗”?计算机通过神经网络发送这些值,神经网络生成一个输出,指示这些值代表狗的可能性。

YOLO 宠物分类
我知道 我知道。关于狗、狐狸和各种东西有很多理论和喋喋不休,但我们很快就会谈到这一点。跟我走。
人脸检测方法
对于检测人脸的计算机视觉任务,有很多方法。为了获得概述并理解我们为什么使用或不使用某些技术,我们将在进入现代方法之前介绍一些较旧的方法。
免责声明:我在这里只是触及表面。如果您想更深入地了解兔子洞,请查看这篇文章: 什么是人脸检测?终极指南 2023 + 型号比较
哈尔瀑布 (2001)
在 2000 年代初期,引入了像广为人知的 Haar Cascade 这样的级联分类器。Haar Cascades是一种用于对象检测的机器学习技术,通常应用于人脸检测等计算机视觉任务。它们通过使用一系列简单的特征来识别图像中的模式。这些功能被组织成级联的阶段,其中每个阶段通过过滤掉非对象区域来逐渐缩小对对象的搜索范围。不幸的是,不同场景(即旋转的面)的检测结果远不及现代技术的准确性。
HOG + 线性支持向量机 (2005)
2005年,提出了另一种物体识别方法:定向梯度直方图(HOG)图像描述符和线性支持向量机(SVM)。试图用更简单的术语分解复杂的过程:HOG用于对象检测并捕获区域中的图像特征。SVM 是一种监督学习模型,经过训练可以根据这些模式区分不同的事物,帮助它在获得新图片时识别特定对象。两者一起可以用作强大的对象检测器。然而,这种方法已经有近二十年的历史了,尽管准确性可以相提并论,但基于深度学习的现代方法缺乏性能。
基于深度学习的人脸检测器:YOLO和YuNet
随着计算机视觉领域的发展,研究人员寻求更准确和通用的物体检测方法,特别是在面部检测的背景下。这导致了基于深度学习的技术的出现,这些技术利用神经网络的力量来彻底改变对象识别。这些进步的两个突出例子是YOLO(2016)和YuNet(2021)。
YOLO(你只看一次)框架因其在物体检测中同时实现非常高的精度和非凡的速度而受到广泛关注。YOLO 不是将图像分解为多个区域进行分析,而是一次性处理整个图像,直接预测边界框和类概率(因此您只看一次)。这种实时检测功能使 YOLO 成为各种应用的游戏规则改变者,包括速度和准确性至关重要的人脸检测。根据我的经验,需要强大的GPU才能获得良好的性能。
2021 年,YuNet 作为图像人脸检测器推出,旨在以高帧率实现高精度,而无需强大的硬件。这就是我过去使用YuNet的原因,并将在本文中重点介绍它。
随着 2022 年 SFace 的推出,提出了另一个探测器,根据 YuNet 的作者的说法,它的速度再次提高了 4 倍左右。
分步指南
首先,我想提一下,本指南中使用的工具包可以替换为任何其他能够执行AI模型,加载图像和替换图像区域的软件。如果你更喜欢JavaScript技术堆栈,我使用ml5.js(用于人脸检测)和p5.js(模糊)实现了类似的软件,但当然存在性能限制。
我使用的是Python 3.9和OpenCV 4.7.0。
- 加载视频帧
import timefrom imutils.video import FileVideoStreamqueue_size = 64fvs = FileVideoStream('video.mp4', None, queue_size).start()# wait for queue to fillwhile not fvs.more(): time.sleep(0.1)frame = fvs.read()frame_height, frame_width, _ = frame.shapeyunet_model = cv2.FaceDetectorYN_create( model='models/face_detection_yunet_2022mar.onnx', config='', input_size=[frame_width, frame_height], score_threshold=0.7, nms_threshold=0.8, top_k=40)
我们使用FileVideoStream(FVS)将输入视频加载到单独的线程上。在此过程中,使用队列来加载帧。然后暂停主线程,直到队列包含项目。这允许 FVS 线程执行。完成后,读取第一帧以确定视频尺寸。
YuNet 被实例化为我们的分类器,其中包含 2022 版本的模型,因为它适合我正在使用的 OpenCV 版本,但您可以将 2023 版本与 OpenCV 4.8.0 一起使用。
- 遍历帧并检测人脸
while fvs.running(): frame = fvs.read() if frame is None: continue _, faces = yunet_model.detect(frame) faces = faces if faces is not None else [] faces = np.asarray(faces, dtype=np.int16) for face in faces: x1, y1, w, h = face[:4] # bounding box coordinates x2 = x1 + w y2 = y1 + h # for implementations of anonymize_roi() see next section frame = anonymize_roi(frame, x1, y1, x2, y2)
我们启动一个循环,读取帧并将每个帧传递给 YuNet 实例。YuNet 为每个检测到的人脸返回一个边界框数组,我们使用 numpy 将其转换为整数,这样我们就不必在以后弄乱浮点值。然后,我们迭代检测到的人脸并确定ROI坐标,然后再应用任何类型的匿名化。
如果 YuNet 结果不够,您可以使用 YOLO 或任何其他模型重复此步骤。为此,只需在循环之前创建所选模型的实例,像刚才一样传递帧进行检测,并将 anonymize_roi() 应用于模型实例返回的边界框。
- 显示或保存更新的帧
现在当前帧已更新,我们可以将其保存到文件中,显示它或两者兼而有之。
while fvs.running(): frame = fvs.read() if frame is None: continue _, faces = yunet_model.detect(frame) faces = faces if faces is not None else [] faces = np.asarray(faces, dtype=np.int16) for face in faces: x1, y1, w, h = face[:4] # bounding box coordinates x2 = x1 + w y2 = y1 + h # for implementations of anonymize_roi() see next section frame = anonymize_roi(frame, x1, y1, x2, y2) # save frame to video file here cv2.imshow('demo-face-blur', frame) if cv2.waitKey(1) == ord('q'): returncv2.destroyAllWindows()
在这个基本示例中,我们使用 OpenCV 显示一个窗口,其中我们的框架作为内容。如果在窗口聚焦的情况下按 Q,则执行将以返回结束。由于这只是为了展示这个想法,因此优雅的退出取决于您。
编辑技术
现在,让我们深入了解一些交换感兴趣区域(=人脸)中信息的常见方法。请记住,丢失的原始图像信息越多,逆转该过程的难度就越大。这类似于使用标记来覆盖纸上的敏感细节。
掩蔽
由于ROI中没有保留任何原始信息,因此此策略非常安全。不幸的是,它不太适合训练数据,因为模型可能会使用掩码及其锋利的边缘作为特征,并开始“寻找”这些特征。如果这与您的情况无关,这是一种非常快速和简单的方法。
def anonymize_roi(frame, x1, y1, x2, y2): roi = frame[y1:y2, x1:x2] if not roi.size: return frame return cv2.rectangle(frame, (x1, y1), (x2, y2), (255, 255, 255), -1)

模糊/像素化
模糊是一种广泛使用的技术,像素化也是如此。应用高斯模糊是一种常见的方法,但在信号处理中有一些方法可以反转它。特别是,如果攻击者可以访问有关模糊/像素化过程和所用参数的详细信息。如果有足够的时间和资源,攻击者可能能够充分逆转该过程,以便能够再次识别人脸。
话虽如此,它仍然是一种常用方法,因为它易于实现且性能良好。逆转该过程需要付出巨大的努力,在许多情况下不太可能发生这种性质的攻击。
重要的是要考虑到内核大小决定了模糊程度,因此决定了面部特征的模糊程度。当面部靠近相机时,较小的内核大小将不起作用,因此需要进行调整。
def anonymize_roi(frame, x1, y1, x2, y2): roi = frame[y1:y2, x1:x2] if not roi.size: return frame anonymized_roi = cv2.blur(roi, ksize=(20, 20)) frame[y1:y2, x1:x2] = anonymized_roi return frame

生成合成数据
这是掩盖投资回报率的另一种方法,但使用人工面部信息。你很可能听说过Deepfake的,它们的架构非常相似。这里使用生成对抗网络(GAN),它由两个神经网络组成:一个生成人脸的生成器和一个学习区分假脸和真脸的鉴别器。这些网络协同工作并生成一张新面孔,如下图所示。

使用深度隐私生成的合成人脸2
不幸的是,性能约为 1 fps(可能是我的错)。如果您有技巧可以更快地运行它,请在下面发表评论。
我听说过某些公司将其作为服务提供的窃窃私语,但据我所知,它往往会在口袋里烧一个洞,并在速度方面拖后腿。
注意事项、限制和优化
无论您选择哪种编校方法,微调对于获得良好的训练结果都至关重要。如果你模糊太多,你不妨只使用蒙版,因为所有的面部特征都会丢失,边缘变得太清晰。但是只有一点点模糊,面孔仍然可以辨认。这与尝试减少ROI大小类似。
虽然使用地标检测进行 ROI 优化确实会产生令人满意的结果,但我通过测试发现投入的努力可能不合理,因为 ROI 仍然需要覆盖大部分面部。
不同的投资回报率形状和大小
合并更多类似面部的形状(如椭圆)可能会改善训练结果。但是,使用 OpenCV 模糊椭圆需要我们为每个 ROI 复制和屏蔽每一帧,这会显著降低性能。如果您碰巧知道实现这一目标的任何更快方法,请给我发消息。
与任何自动化系统一样,我们的软件有时可能会(并且会)出现故障。人脸检测不是 100% 准确的,这意味着某些人脸不会被检测到,因此根本不会被替换。失真的图像以及侧身看相机的人脸和部分遮挡人脸(例如手指)都会对准确性构成威胁。因此,建议仔细调整所有模型参数,并通过手动管理来跟进处理。
将分类器与跟踪器组合在一起
在最近的一个客户项目中,我使用了全规模网络(OSNet)跟踪器来增强结果。跟踪器可以稳定输出,尤其是当对象偶尔被遮挡时。这是GitHub上一个漂亮的例子:使用YOLOv7和StrongSORT与OSNet的实时多相机多对象跟踪器
多线程
Python 中的多线程可以帮助完成 I/O 密集型任务。常见的 Python 实现使用所谓的全局解释器锁 (GIL) 来确保线程安全。一次只执行一个解释器实例。当不使用解释器时(例如在等待 I/O 时),GIL 被释放。我通过分离 a) 帧的渲染和 b) 将帧保存到单独的类和单独的线程,成功地提高了性能。
使用分而治之算法进行多处理
在某些情况下,可以使用多个进程实现并行性。这是我在上述商业项目中实现的另一个想法。
当我们的任务不涉及实时视频流时,我们可以利用一种称为分而治之算法的技术。它涉及将我们的输入视频分解为多个部分,并同时在这些片段上执行相同的操作。
根据我的经验,这可以提高资源利用率和更快的执行时间。如果您对细节感到好奇:使用并行计算在 Python 中更快地处理视频
道德考虑
由于我们生活在一个快节奏、财务驱动的世界中,人们很容易忽视或低估技术使用可能带来的意想不到的后果。然而,重要的是要认识到,负责任地使用包括视频监控和人工智能在内的技术具有重要的道德分量。

记住本叔叔的话【优酷视频上传男4聊天,见演职员表】
每个个人、组织和开发人员都有责任考虑其行为对隐私、安全和社会价值的潜在影响。
结论
正如我们所看到的,保护隐私可能是一项复杂的任务,涉及许多考虑因素。鉴于潜在的风险以及该领域日益增长的监管,我认为这是值得花费的时间。如今,几乎任何人都可以实施和使用最先进的人脸匿名方法,从而为更复杂的任务腾出人力资源。
使用自动化技术和人工智能伴随着勤奋理解和降低风险的责任,确保保持匿名性并将重新识别的风险降至最低。
这涉及优先考虑用户同意、数据保护和避免有偏见的结果。通过坚持这些原则,我们可以利用技术的好处,同时最大限度地减少负面影响,促进更负责任和公平的技术格局。
在我的第一篇文章中,您的反馈非常重要。无论您有问题、建议还是任何想法要补充,我都渴望向您学习。请随时在下面分享您的评论或直接与我联系。期待与您建立联系!
评论留言