一种基于 dlib 的脸部标记检测器
原文详见:https://www.pyimagesearch.com/2018/04/02/faster-facial-landmark-detector-with-dlib/
by Adrian Rosebrock on April 2, 2018
Translate by: Soih
个人兴趣翻译,请勿传播!
Please DO NOT distribute.
2017年9月,Davis King 发布了 dlib v19.7,在发布说明中,有一段关于脸部5点标记检测器的说明既简短又不起眼:
新增了一个脸部 5点标记的模型,速度比原来的 68 点模型快,而且尺寸小10 倍以上,可以与 HOG 和 CNN 的脸部检测共同使用。
所以,本文介绍的是 dlib 新发布的 5 点脸部标记检测器。相比原始版本,它的速度更快(相比原来版本快8-10%),效率更高而且更小(是原来版本的1/10)。
这篇博客主要讨论 dlib 新的 5 点脸部标记检测器,主要包括:
- 5 点脸部标记检测器如何工作;
- 在实际应用中,选择新的 5 点还是原始 68 点脸部标记检测器的注意事项;
- 如何在代码中实现 5 点脸部标记检测器;
- 5 点脸部标记检测器的案例演示。
如果想要学习有关使用 dlib 进行脸部标记点检测的更多内容,请继续阅读。
本文目录
- 1. 一种基于 dlib 的(速度更快的)脸部标记检测器
- 1.1 Dlib 的 5 点脸部标记检测器
- 1.2 使用 dlib,OpenCV 和 Python 实现脸部标记功能
- 1.3 运行我们的脸部水印检测器
- 1.4 dlib 的 5 点和 68 点脸部标记检测器速度比较
- 1.5 5 点脸部检测器的限制
- 2. 总结
1. 一种基于 dlib 的(速度更快的)脸部标记检测器
在这篇博客的第一部分,首先讨论 dlib 最新的,速度更快、尺寸更小的 5 点脸部标记检测器,并与之前发布的 68 点脸部标记检测器进行比较。
之后,我们将使用 Python,dlib 和 OpenCV 实现脸部标记点的识别,并运行观察实际结果。
最后,我们将探讨 5 点脸部标记检测器的一些限制,并重点给出一些应该使用 68 点标记检测器的场景。
1.1 Dlib 的 5 点脸部标记检测器
上图给出了 dlib 新的 5 点脸部标记检测器和原始的 68 点脸部标记检测器的对比示意。
区别于 68 点检测器定位了眼部、眉毛、鼻子、嘴巴和下颚轮廓,新的 5 点脸部标记检测器将这些信息减少为:
- 2 个点用于代表左眼;
- 2 个点用于代表右眼;
- 1 个点用于代表鼻子。
5 点脸部检测器一个最合适的应用场景是用于脸部对齐。
在加速方面,我发现新的 5 点探测器比原版本快 8 - 10%,但真正有优势的地方是模型的大小:分别是 9.2 MB 和 99.7 MB(小 10 倍以上)。
还有一点很重要,那就是脸部标记检测器往往一开始就非常快(尤其是像在 dlib 中一样,正确实现的情况下)1。
加速方面真正的胜利决定于应用的脸部检测器。一些脸部检测器可能较快(但是可能精度较差)。回想我们之前的睡意检测系列:
- 使用 OpenCV 开展睡意检测
- Raspberry Pi:基于 OpenCV 和 dlib 的脸部标记 + 睡意检测
针对笔记本/桌面环境,我们之前使用的是更精确的 HOG + 线性 SVM 脸部检测器,但是在 Raspberry Pi 上使用了精确度较差但是速度更快的 Haar 级联分类器器来实现实时检测。
一般的,可以遵从下面的指引来选择脸部检测模型:
- Haar 级联分类器: 速度快,但是不够准确,调参的过程很痛苦。
- HOG + 线性 SVM 方法: 精确度一般比 Haar 级联分类器(显著地)高,虚假阳性比例低。一般在测试时只需要调节较少的参数,与 Haar 级联分类器相比速度可能更慢。
- 基于深度学习的检测器: 当正确训练时,可以比 Haar 级联分类器和 HOG + 线性 SVM 方法更加精确,鲁棒性更强。由于模型的深度和复杂性,速度可能很慢。如果使用 GPU 进行推断的话,可以提速(参见这篇OpenCV 深度学习脸部检测器文章)。
在构建利用脸部检测和脸部标记的应用时,请牢记这些指导原则。
1.2 使用 dlib,OpenCV 和 Python 实现脸部标记功能
既然已经讨论了 dlib 的 5 点脸部标记检测器,下面来编写代码观察其实际应用。
打开新文件,命名为 faster_facial_landmarks.py
,插入如下代码:
# 导入必须的包
from imutils.video import VideoStream
from imutils import face_utils
import argparse
import imutils
import time
import dlib
import cv2
第 2 - 8 行是必需的包,特别是包括了 dlib
和从 imutils
导入的两个模块。
其中 imutils 包已经更新,能够处理 68 点和 5 点脸部标记模型,可以通过下面的代码确保这个包得到更新:
pip install --upgrade imutils
再次强调,更新 imutils
后,可以处理 68 点和 5 点脸部标记。
之后,对命令行参数进行解析:
# 构建命令行解析器并解析命令行
ap = argparse.ArgumentParser()
ap.add_argument("-p", "--shape-predictor", required=True, help="path to facial landmark predictor")
args = vars(ap.parse_args())
我们有一个命令行参数: --shape-predictor
。这个参数允许我们在运行时更改脸部水印预测器的路径:
Note: 对命令行参数有困惑?可以查阅之前的对命令行参数详细介绍的博客。
下面,载入形状预测器并初始化视频流:
# 初始化 dlib (基于HOG的)脸部检测器,并创建脸部水印预测器
print("[INFO] loading facial landmark predictor...")
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(args["shape_predictor"])
# 初始化视频流,并预留时间使得摄像头预热
print("[INFO] camera sensor warming up...")
vs = VideoStream(src=1).start()
# vs = VideoStream(usePiCamera=True).start() # Raspberry Pi
time.sleep(2.0)
第 3 行和第 4 行,我们初始化了 dlib 预先训练好的 HOG + 线性 SVM 脸部 detector
并载入了 shape_predictor
文件。
为了访问摄像机,我们将使用 imutils
中的 VideoStream
类。
你可以通过注释或者取消第 7 行和第 8 行来选择不同的摄像头:
- 内置/USB摄像头;
- 在 Raspberry Pi 上使用 PiCamera。
之后,对每一帧进行操作,完成预期任务:
# 对视频流的每一帧分别进行操作
while True:# 从视频流中抓取每一帧图像,并将其调整为最大宽度 400 个像素,并将其转为灰度图像frame = vs.read()frame = imutils.resize(frame, width=400)gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 从灰度图像中检测人脸rects = detector(gray, 0)# 检查是否检测到人脸;如果检测到,在该帧图像上画出人脸的个数if len(rects) > 0:text = "{} face(s) found".format(len(rects))cv2.putText(frame, text, (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
首先,从视频流中读取一帧图像 frame
, 调整其大小,转换为灰度图像(第4 - 6行);
其次,使用 HOG + 线性 SVM detector
来检测灰度图像中的人脸(第 9 行);
之后,确保最少有 1 个图像被检测到的基础上,在原始的图像 frame
上画出检测到人脸的数量。
之后,让我们循环人脸检测并绘制人脸标记:
# 循环运行人脸检测for rect in rects:# 计算人脸的边界框并将其绘制在原始图像帧上(bX, bY, bW, bH) = face_utils.rect_to_bb(rect)cv2.rectangle(frame, (bX, bY), (bX + bW, bY + bH), (0, 255, 0), 1)# 确定人脸区域的脸部标记点,并将其从遍布标记 (x, y) 坐标转换为 Numpy 数组shape = predictor(gray, rect)shape = face_utils.shape_to_np(shape)# 对每个脸部标记循环(x, y)坐标并将其画出for (i, (x, y)) in enumerate(shape):cv2.circle(frame, (x, y), 1, (0, 0, 255), -1)cv2.putText(frame, str(i + 1), (x - 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.35, (0, 0, 255), 1)
从第 2 行开始,我们对所有的 rects
的人脸进行循环:
首先,在第 4 - 5 行,通过使用 imutils
中的 face_utils
模块,在原始图像帧上画出脸部的边界框(更多信息可以阅读这里);
之后,将识别的脸部传递到 predictor
中来确定人脸标记点(第 7 行),然后依次将脸部标记坐标转换为 Numpy 数组;
下面是最有趣的部分,为了可视化标记,我们使用 cv2.circle
画出小点并给每个坐标点标记数字;
在第 10 行,对所有的标记点坐标进行循环,同样也在原始的图像帧上画出小的填充的圆圈。
下面完成脸部标记的脚本:
# 显示图像帧 framecv2.imshow("Frame", frame)key = cv2.waitKey(1) & 0xFF# 如果按下 `q` 键,跳出循环if key == ord("q"):break
# 完成清理工作
cv2.destroyAllWindows()
vs.stop()
上面的代码中,先是显示图像帧(第 2 行),设定如果按下 “q” 键就跳出循环(3 - 7 行),并且结束后完成清理工作(第 9 行和第 10 行)。
1.3 运行我们的脸部水印检测器
完成代码填写后,对其进行测试。
可以从本博客最下面的 “下载(Downloads)” 部分来下载源代码和 5 点脸部标记检测器。
之后,打开终端界面(命令行界面),执行下面的命令:
python faster_facial_landmarks.py --shape-predictor shape_predictor_5_face_landmarks.dat
正如上面的 GIF 所示,我们已经成功的定位了 5 个脸部标记点,包括:
- 2 个点用于代表左眼;
- 2 个点用于代表右眼;
- 1 个点用于代表鼻子的底部。
我在下面的视频中,展示了一个有关面部标记检测器的更长演示:
(视频略)
1.4 dlib 的 5 点和 68 点脸部标记检测器速度比较
在我自己的测试中,发现 dlib 的 5 点脸部标记检测器比原始的 68 点脸部标记检测器快 8 - 10%。
有 8 - 10% 的速度提升意义重大,但是更重要的是模型的尺寸。
原始的 68 点脸部标记模型是 99.7MB,将近 100 MB。
而 5 点脸部标记检测器小于 10 MB,仅有 9.2MB,模型小了 10 倍以上!
当构建自己使用了脸部标记的应用时,更小的模型文件,可以空出更多空间给应用的其他部分。
更小的模型尺寸有很大的意义的,比如想象为移动应用用户节省的下载时间和存储空间!
1.5 5 点脸部检测器的限制
5 点脸部检测器的首要应用将是脸部对齐:
对于脸部对齐,5 点脸部标记点检测器可以较好地替代 68 点检测器,相同的通用算法为:
- ① 计算 5 点脸部标记点;
- ② 基于表示眼睛的两个标记点,分别计算眼睛的中心;
- ③ 利用两眼之间的中点计算眼睛质心之间的角度;
- ④ 利用仿射变换(affine transformation)获得脸部标准旋转对齐2。
虽然 68 点脸部标记检测器可以给出眼睛中心略好 的估计效果,但实际上, 5 点脸部标记检测同样有效。
话虽如此,尽管 5 点脸部标记探测器确实更小(两个模型大小分别是 9.2 MB 和 99.7 MB),但它不能在所有情况下都适用。
这种情况的一个很好例子是睡意检测:
在应用睡意检测时,我们需要使用眼睛标记的 宽度 和 长度 的比例,来计算眼睛长宽比(Eye Aspect Ratio, EAR)。
如果使用 68 点脸部标记检测器,每个眼睛都有 6 个点,使得我们能开展眼睛长宽比的计算。
然而,如果使用 5 点脸部标记检测器,每个眼睛仅有 2 个点(也就是上图 图4 中的 p1p_1p1 和 p2p_2p2 两点),这不足以计算眼睛长宽比。
因此,如果计算搭建一个 睡意检测器 或者需要其他脸部更多点的应用,比如需要:
- 眼睛
- 眉毛
- 鼻子
- 嘴巴
- 下颚轮廓
……的情况下,应该使用 68 点脸部标记检测器,而不是 5 点脸部标记检测器。
2. 总结
这篇博客中,我们讨论了 dlib 新的,更紧凑的 5 点脸部标记检测器。
5 点脸部标记检测器一般可以看做是对 dlib 原始的 68 点脸部标记检测器的替代方案。
在讨论了两个脸部标记检测器的区别后,我提供了应用 5 点标记检测器的版本来检测脸部眼睛和鼻子区域。
在本文测试中,我发现 5 点标记检测器能比 68 点的版本快 8 - 10%,而尺寸 减小了10倍。
在下面表格中输入你的 Email,可以下载本文使用的源代码和 5 点脸部标记检测器。同时,当 PyImageSearch 的博客有更新时,可以获得新的计算机视觉教程。
It’s also important to note that facial landmark detectors tend to be very fast to begin with. ↩︎
Obtain a canonical alignment of the face by applying an affine transformation. ↩︎
一种基于 dlib 的脸部标记检测器相关推荐
- 《MEMDOG:一种基于 Linux 的在线内存检测器》
[1]王小强. MEMDOG:一种基于Linux的在线内存检测器[D].兰州大学,2017. 由于 DRAM 的容量不断地增大,体积不断地减小,因此表示一个位信息的存储单元在不断地缩小,使得 DRAM ...
- LiDARTag:一种基于点云的实时估计基准标记物位姿的系统
点云PCL免费知识星球,点云论文速读. 文章:LiDARTag: A Real-Time Fiducial Tag System for Point Clouds 作者:Jiunn-Kai Huang ...
- python基于dlib的face landmarks
python基于dlib的face landmarks python使用dlib进行人脸检测与人脸关键点标记 Dlib简介: 首先给大家介绍一下Dlib Dlib是一个跨平台的C++公共库,除了线程支 ...
- YOLOv4-5D:一种高效的自动驾驶物体检测器
点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 作者丨CY 来源丨 当交通遇上机器学习 1. 文章信息 本次介绍的文章是2021年3月份发表在IEEE ...
- python dlib opencv人脸识别准确度_基于dlib和opencv库的人脸识别
基于dlib和opencv库的人脸识别 需下载68个特征点的人脸检测模型: http://dlib.net/files/ 文件名为shape_predictor_68_face_landmarks.d ...
- 一种基于人脸追踪和特征分析的疲劳驾驶预警平台
目录 整体描述 1. 嵌入式端: 2.程序端: 3. 辅助功能: 4. 项目整体工作流程 5. 不足之处 效果演示 程序源码 算法篇 基于AdaBoost级联分类器的人脸/眼睛位置检测算法 基于特征脸 ...
- 基于Dlib的疲劳检测系统
需要源码的朋友可以私信我 基于Dlib的疲劳检测系统 1.设计背景及要求 2.系统分析 3.系统设计 3.1功能结构图 3.2基于EAR.MAR和HPE算法的疲劳检测 3.2.1基于EAR算法的眨眼检 ...
- 一种基于深度学习的方法来检测摩托车头盔的使用
背景 据统计使用摩托车头盔可以将道路交通事故中摩托车驾驶员致命伤害的可能性降低42%,尽管如此,遵守摩托车头盔还是较少,尤其是在发展中国家,为了有效开展针对性的头盔使用运动,政府必须收集有关头盔法律遵 ...
- opencv入门基础(七)基于dlib进行本地图片、实时人脸检测
opencv入门基础(七)基于dlib进行本地图片.实时人脸检测 一.背景知识 1.Dlib是一个深度学习开源工具,基于C++开发,也支持Python开发接口. 2.由于Dlib对于人脸特征提取效果很 ...
最新文章
- TensorRT IRNNv2Layer
- iicFPGA程序及仿真
- Docker Caffe部署
- 计算机组成原理we指什么,计算机组成原理课后习题答案一到九章
- python LAADS+Selenium下载MODIS数据
- python解析二维码_Python二维码生成识别实例详解
- PHP 中 shell_exec() 中的反撇号操作符的变体 可用作后门
- activiti 工作流_JAVA-工作流引擎-activiti-Tasks介绍
- vc6.0垃圾文件清理工具_C盘空间逐渐被垃圾文件填满,详细清理方法介绍
- 云管平台-FIT2CLOUD CMP2.0
- 多文件自平衡云传输(三)节点选择和资源分配 —————— 开开开山怪
- 2018蓝桥模拟赛 天上的星星
- 腾讯互娱技术总监张正:《天涯明月刀》后台技术创新
- sql 中英文格式的时间转数字格式
- 旧约圣经对基督(弥赛亚)的预言
- [软件工程]关于调查报告的响应和看到张恂的批评
- Android优雅的ui倒计时,Hurry - 一款颜值超高的日历+倒计时 APP - Android 应用 - 生活 - 【最美应用】...
- 计算机与算盘有什么区别
- 什么是网站结构,为什么它很重要?
- 常用字符集总结(utf-8,unicode,ASCII,GBK)
热门文章
- 服务器内存不显示内存品牌,服务器内存不显示
- NX二次开发-UFUN读取图纸尺寸的值UF_DRF_ask_dimension_text
- SAP SMARTFORMS文本内容手动换行输出
- 南京农业大学教务系统大学生抢课——基于python的selenium包+谷歌浏览器
- 【Android+OkHttp3+Jsoup】 模拟登录教务系统 抓取课表和成绩
- 1.19.5.4.流上的Join、常规Join、时间区间Join、时态表Join、基于处理时间的时态Join、时态表函数Join、用法
- 基于linux的web自动化(selenium+jenkins+linux+firefox)
- 习题5-6 对称轴 UVa1595
- java 项目启动初始化_Spring项目启动时执行初始化方法
- 【日常Exception】第二十四回:nested exception is java.lang.NoClassDefFoundError: redis/clients/jedis/util/Pool