赞
踩
人脸识别是一门比较成熟的技术。
它的身影随处可见,刷脸支付,信息审核,监控搜索,人脸打码等。
更多的时候,它是方便了我们的生活,足不出户,就可以实现各种 APP 的实名认证,信息审核。
一些公司,也都有对内部员工开放的刷脸支付系统,不用带手机,不用带工卡,带着一张或美丽或帅气的脸庞,就可以在公司内部「买买买,刷刷刷」。
除了这些常规操作,还可以对视频里的特定人物进行打码。
对于视频,人工后期的逐帧处理,打码任务无疑是个「体力活」。
但如果结合脸识别技术,那这个任务就会简单很多。
本文从原理出发,讲解人脸识别技术的视频打码应用。
过滤视频的敏感人物,就这么简单!
人脸识别技术包涵了多种算法,整个流程大致如下:
使用检测技术,检测出人脸位置。
使用 landmark 技术,检测出人脸关键点。
根据人脸位置和人脸关键点,裁剪出人脸区域,并根据关键点将人脸图片进行矫正,得到「标准脸」。
计算「标准脸」的人脸特征向量。
与「人脸库」的人脸特征向量比对,计算向量的距离,找到最接近的人,输出人脸识别结果。
1、人脸检测
输入:原始的可能含有人脸的图像。
输出:人脸位置的 bounding box。
这一步一般我们称之为“人脸检测”(Face Detection),人脸检测算法,可以使用的库有很多,例如 OpenCV、dlib、face_recognition、RetianFace、CenterFace 等等。
太多了,数不过来。
当然,自己用 yolo 、ssd 这类经典的检测算法,自己实现一个也是可以的。
2、人脸裁剪及矫正
输入:原始图像 + 人脸位置 bounding box。
输出:“校准”过的只含有人脸的图像。
这一步需要使用 landmark 算法,检测人脸中的关键点,然后根据这些关键点对人脸做对齐校准。
所谓的关键点,就是下图所示的绿色的点,通常是眼角的位置、鼻子的位置、脸的轮廓点等等。
有了这些关键点后,我们就可以把人脸“校准”,或者说是“对齐”。
解释就是原先人脸可能比较歪,这里根据关键点,使用仿射变换将人脸统一“摆正”,尽量去消除姿势不同带来的误差。这一步我们一般叫 Face Alignment 。
3、人脸特征
输入:校准后的单张人脸图像。
输出:一个向量表示。
这一步就是使用深度卷积网络,将输入的人脸图像,转换成一个向量的表示。这个向量就是人脸的特征,例如:
这密密麻麻的 128 维的向量,就是一张人脸的特征,你也可以叫做人脸的编码。
提取特征这种事,卷积神经网络很在行。
举个例子,VGG16 是深度学习中一个比较简单的基本模型。
输入卷积神经网络的是图像,经过一系列卷积后,全连接分类得到类别概率。
整个过程是这样的:
其实,卷积神经网络不断的进行卷积,下采样,这就是一个提取特征的过程,最后通过全链接层得到类别概率。
人脸特征提取,我们也可以这么操作。我们可以去掉全连接层,用计算的特征(一般就是卷积层的最后一层,e.g. 图中的conv5_3)来当作提取的特征进行计算。
与分类任务不同的是,最后使用的 loss 损失函数是不同的。
在理想的状况下,我们希望“向量表示”之间的距离就可以直接反映人脸的相似度:
对于同一个人的人脸图像,对应的向量的欧几里得距离应该比较小。
对于不同人的人脸图像,对应的向量之间的欧几里得距离应该比较大。
所以,每个人脸的类别中心,应该尽可能远一些,这样才能用于区别不同的人。
人脸常用的 loss 有 center loss 、 arcface loss 等。
人脸识别类似于,细粒度的分类。
训练过分类任务的,应该都知道。
训练人和猪的二分类,很好训练,因为人和猪的特征差别很明显。
但训练男人和女人的二分类,就要难一些,因为男人和女人的特征很相近。
为了更好区分男人和女人,就需要使用类别中心间距大的损失函数。
人脸识别,更是一种细粒度的区分,都是人,但你要区分出张三、李四、王二麻。
人脸识别,一般是需要建立一个「检索库」。
简单解释一下,我们要识别张三、李四、王二麻。
那么,我们就要选张三、李四、王二麻每个人的 10 张(自己定)图片。
然后使用我们训练好的人脸特征模型,提取每个人的人脸特征。
这样每个人,就都有 10 个人脸特征了,这就是一个「检索库」。
需要识别的图片,提取人脸特征后,依次与检索库已有的人脸特征去比对,投票选出最接近的人。
人脸识别技术原理清楚了,我们就可以使用这个技术,给仝卓打码。
可以看到,人脸识别技术涉及到的算法较多,自己依次实现是需要时间的。
但这,难不倒身为优秀「调包侠」的我。
开源的第三方库有很多,比如 mediapipe。
里面集成了人脸检测、人脸识别等接口。
使用人脸识别技术,对这一小段视频,给人脸进行打码。
整理一下思路:
首先,我们使用 opencv 这类的程序处理视频,只能处理画面,不能处理声音。
所以,需要先将音频保存,再将处理好的视频和音频进行合成,这样既保证了画面打码,又保证了声音还在。
这块可以使用mediapipe实现。
基于深度学习mediapipe的人脸打码人脸模糊教程pyqt
- import cv2
- import mediapipe as mp
-
-
- class FaceDetector:
- def __init__(self):
- self.mp_face_detection = mp.solutions.face_detection
- self.mp_drawing = mp.solutions.drawing_utils
-
- def rectangle(self, image, mosaic_level):
- success = False
- cv2.imwrite('middle_pic/before_handle.jpg', image)
- with self.mp_face_detection.FaceDetection(
- min_detection_confidence=0.5) as face_detection:
-
- # Flip the image horizontally for a later selfie-view display, and convert
- # the BGR image to RGB.
- # image = cv2.cvtColor(cv2.flip(image, 1), cv2.COLOR_BGR2RGB)
- image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
- # To improve performance, optionally mark the image as not writeable to
- # pass by reference.
- image.flags.writeable = False
- results = face_detection.process(image)
-
- # Draw the face detection annotations on the image.
- image.flags.writeable = True
- image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
- if results.detections:
- for detection in results.detections:
- h, w, c = image.shape
-
- xmin = int(detection.location_data.relative_bounding_box.xmin * w)
- ymin = int(detection.location_data.relative_bounding_box.ymin * h)
- width = int(detection.location_data.relative_bounding_box.width * w)
- height = int(detection.location_data.relative_bounding_box.height * h)
- xmax = xmin + width
- ymax = ymin + height
- if xmax > w:
- width = w - xmin
- if ymax > h:
- height = h - ymin
-
- self.do_mosaic(image, xmin, ymin, width, height, int(mosaic_level * 0.2 * width))
- # 画矩形框
- # image = cv2.rectangle(image, (xmin, ymin), (xmin + width, ymin + height), (0, 255, 0), 2)
- success = True
- cv2.imwrite('middle_pic/after_handle.jpg', image)
-
- return image, success
-
- # 正规马赛克
- def do_mosaic(self, img, x, y, w, h, neighbor):
- """
- :param rgb_img
- :param int x : 马赛克左顶点
- :param int y: 马赛克左顶点
- :param int w: 马赛克宽
- :param int h: 马赛克高
- :param int neighbor: 马赛克每一块的宽
- """
- for i in range(0, h, neighbor):
- for j in range(0, w, neighbor):
- rect = [j + x, i + y]
- color = img[i + y][j + x].tolist() # 关键点1 tolist
- left_up = (rect[0], rect[1])
- x2 = rect[0] + neighbor - 1 # 关键点2 减去一个像素
- y2 = rect[1] + neighbor - 1
- if x2 > x + w:
- x2 = x + w
- if y2 > y + h:
- y2 = y + h
- right_down = (x2, y2)
- cv2.rectangle(img, left_up, right_down, color, -1) # 替换为为一个颜值值
-
- return img
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。