各位同学好,今天和大家分享一下如何使用MediaPipe完成人脸实时跟踪检测,先放张图看效果,FPS值为14,右侧的输出为:每帧图像是人脸的概率,检测框的左上角坐标及框的宽高。
有需要的可以使用 cv2.VideoCapture(0) 捕获电脑摄像头。本节就用视频进行人脸识别。
人脸检测的相关说明见官方文档:
MediaPipe 人脸检测是一种识别速度超快的方法,具有 6 个特征点和多面支持。它基于BlazeFcae一个轻量级且性能良好的面部检测器,专为移动GPU推理量身定制。该探测器的超实时性能使其能够应用于任何需要精确感兴趣面部区域作为其他任务特定模型输入的实时取景器体验,例如3D面部关键点或几何估计(例如 MediaPipe Face Mesh)面部特征或表情分类以及面部区域分割。
从mediapipe中导入检测方法,今天我们使用人脸检测 mediapipe.solutions.face_detection。
(1)mediapipe.solutions.face_detection.FaceDetection() 人脸检测函数
参数:
min_detection_confidence: 默认为 0.5。人脸检测模型的最小置信值 (0-1之间),高于该置信度则将检测视为成功。
返回值:
detections:检测到的人脸的集合,其中每个人脸都表示为一个检测原始消息,其中包含 人脸的概率、1 个边界框、6 个关键点(右眼、左眼、鼻尖、嘴巴中心、右耳、左耳)。边界框由 xmin 和 width (由图像宽度归一化为 [0, 1])以及 ymin 和 height (由图像高度归一化为 [0, 1])组成。每个关键点由 x 和 y 组成,分别通过图像宽度和高度归一化为 [0, 1]。
返回值.score: 获取图像是人脸的概率
返回值.location_data: 获取识别框的 x, y, w, h 和 6个关键点的 x, y
返回值.location_data.relative_bounding_box: 获取识别框的 x, y, w, h
返回值.location_data.relative_keypoints: 6个关键点的 x, y 组成的列表
(2)mediapipe.solutions.drawing_utils.draw_landmarks() 绘制手部关键点的连线
参数:
image: 需要画图的原始图片
landmark_list: 检测到的手部关键点坐标
connections: 连接线,需要把那些坐标连接起来
landmark_drawing_spec: 坐标的颜色,粗细
connection_drawing_spec: 连接线的粗细,颜色等
使用 cv2.VideoCapture() 读取视频文件时,文件路径最好不要出现中文,防止报错。
变量.read() 每次执行就从视频中提取一帧图片,需要循环来不断提取。用success来接收是否能打开,返回True表示可以打开。img保存返回的的每一帧图像。
由于读入视频图像通道一般为RGB,而opencv中图像通道的格式为BGR,因此需要 cv2.cvtColor() 函数将opencv读入的视频图像转为RGB格式 cv2.COLOR_BGR2RGB。
结果如下图所示,准确找到了人脸位置,并绘制识别框。右侧打印识别框和关键点信息。
在这里我更加关注识别框的位置位置,不太关心关键点的坐标信息,因此接下来我们单独绘制识别框,并把每一帧图像的人脸概率显示出来。如果有同学更关注人脸关键点,可以使用mediapipe的人脸网状检测,能得到的关键点非常多,这个我在后续章节也会写。
因此,接下来我们在上面代码的基础上继续补充。detection.location_data.relative_bounding_box 获取检测框的左上角坐标和检测框的宽高,保保存在bbox中。如下我们可以看到识别框的信息都是归一化之后的,需要将其转换为像素坐标。
转换方法也很简单,只需要将比例长度x和w乘以实际图像宽度即可得到像素长度下的x和w,同理y和h。注意,像素长度一定是整数,如[200,200],比例长度是小数,如[0.5, 0.5]
使用自定义矩形绘制函数cv2.rectangle(),现在有了像素坐标下的左上坐标xy,框的宽w和高h。就可以在原图像img上把框绘制出来。
detection.score 获取检测框的人脸概率值,返回只有一个元素的列表。detection.score[0] 提取这个元素,返回浮点型数值。
结果如下图所示,右侧输出每帧图像的每个识别框的概率和框坐标
接下来把识别框做的好看一些,只需要修改矩形框样式即可,我们接着上面的代码编辑。把识别框宽度调细一些,在四个角上添加粗线段。
修改后的检测框效果如下
我们将坐标信息存放在了boxlist中,boxlist.append([index, detection.score, bbox]) 存放人脸索引、评分、检测框信息,把它打印出来看一下,比如某帧图像所在的视频有3张脸,每一帧都会输出0、1、2三个识别框的概率,左上角坐标xy,框的宽高wh