Python 3 利用 Dlib 实现摄像头人脸检测特征点标定
0. 引言
利用 Python 开发,借助 Dlib 库捕获摄像头中的人脸,进行实时人脸 68 个特征点标定;
支持多张人脸;
有截图功能;

图 1 工程效果示例( gif )

图 2 工程效果示例( 静态图片 )
1. 开发环境
Python: 3.6.3
Dlib: 19.7
OpenCv, NumPy
import dlib # 人脸检测的库 Dlib
import numpy as np # 数据处理的库 NumPy
import cv2 # 图像处理的库 OpenCv
2. 源码介绍
其实实现很简单,主要分为两个部分:摄像头调用 + 人脸特征点标定
2.1 摄像头调用
介绍下 OpenCv 中摄像头的调用方法,用到以下几个 OpenCv 函数:
cv2.VideoCapture(0) 创建一个对象;
cv2.VideoCapture.set(propId, value) 设置视频参数;
cv2.VideoCapture.isOpened() 检测读取视频是否成功;
cv2.VideoCapture.read() 返回是否读取成功和读取到的帧图像;
(具体可以参考官方文档:https://docs.opencv.org/2.4/modules/highgui/doc/reading_and_writing_images_and_video.html)
关于 cv2 中 VideoCapture 类的一些函数参数的说明如下:
# Sort by coneypo
# Updated at 10, Oct
# Blog: http://www.cnblogs.com/AdaminXie ###### 1. cv2.VideoCapture(), 创建cv2摄像头对象 / Open the default camera ######
"""
Python: cv2.VideoCapture() → <VideoCapture object> Python: cv2.VideoCapture(filename) → <VideoCapture object>
filename – name of the opened video file (eg. video.avi) or image sequence (eg. img_%02d.jpg, which will read samples like img_00.jpg, img_01.jpg, img_02.jpg, ...) Python: cv2.VideoCapture(device) → <VideoCapture object>
device – id of the opened video capturing device (i.e. a camera index). If there is a single camera connected, just pass 0.
"""
cap = cv2.VideoCapture(0) ##### 2. cv2.VideoCapture.set(propId, value),设置视频参数; #####
"""
propId:
CV_CAP_PROP_POS_MSEC Current position of the video file in milliseconds.
CV_CAP_PROP_POS_FRAMES 0-based index of the frame to be decoded/captured next.
CV_CAP_PROP_POS_AVI_RATIO Relative position of the video file: 0 - start of the film, 1 - end of the film.
CV_CAP_PROP_FRAME_WIDTH Width of the frames in the video stream.
CV_CAP_PROP_FRAME_HEIGHT Height of the frames in the video stream.
CV_CAP_PROP_FPS Frame rate.
...
value: 设置的参数值/ Value of the property
"""
cap.set(3, 480) ##### 3. cv2.VideoCapture.isOpened(), 检查摄像头初始化是否成功, 返回true或false / check if open camera successfully #####
cap.isOpened() ##### 4. cv2.VideoCapture.read([imgage]) -> retval,image, 读取视频 / Grabs, decodes and returns the next video frame #####
"""
返回两个值:
一个是布尔值true/false,用来判断读取视频是否成功/是否到视频末尾
图像对象,图像的三维矩阵
"""
flag, im_rd = cap.read()
2.2 人脸特征点标定
调用预测器 “shape_predictor_68_face_landmarks.dat” 进行 68 点标定,这是 Dlib 训练好的模型,可以直接调用,进行人脸 68 个人脸特征点的标定;
需要进行的后续工作是,利用坐标值进行特征点绘制;
具体可以参考我的另一篇博客(Python 3 利用 Dlib 19.7 实现人脸68个特征点的标定);

图 3 Dlib 中人脸 68 个特征点位置说明
2.3 源码
既然已经能够利用训练好的模型进行特征点检测,需要进行的工作是将摄像头捕获到的视频流,转换为 OpenCv 的图像对象,这样才能进行人脸特征点检测;
然后利用返回的特征点坐标值,绘制特征点,实时的再绘制到摄像头界面上,达到实时人脸检测追踪的目的;
利用 cv2.VideoCapture() 创建摄像头对象,然后利用 flag, im_rd = cv2.VideoCapture.read() 读取摄像头视频,im_rd 就是视频中的一帧帧图像;
然后就类似于单张图像进行人脸检测,对这一帧帧的图像 im_rd 利用 Dlib 进行特征点标定,然后绘制特征点;
可以按下 's' 键来获取当前截图,会存下带有时间戳的本地图像文件如 “screenshoot_1_2018-05-14-11-04-23.jpg”;
或者按下 'q' 键来退出摄像头窗口;
有四个 python 文件:
how_to_use_camera.py OpenCv 调用摄像头;
get_features_from_image.py 绘制 "data/face_to_detect/face_x.jpg" 本地图像人脸文件的特征点;
get_features_from_camera.py 从摄像头实时人脸检测绘制特征点;
remove_ss.py: 删除 "data/screenshots/" 路径下的所有截图;
( 源码都上传到了 GitHub: https://github.com/coneypo/Dlib_face_detection_from_camera )
这里只给出 get_features_from_camera.py 的源码;
get_features_from_camera.py:
# 调用摄像头,进行人脸捕获,和 68 个特征点的追踪 # Author: coneypo
# Blog: http://www.cnblogs.com/AdaminXie
# GitHub: https://github.com/coneypo/Dlib_face_detection_from_camera # Created at 2018-02-26
# Updated at 2019-01-28 import dlib # 机器学习的库 Dlib
import numpy as np # 数据处理的库 numpy
import cv2 # 图像处理的库 OpenCv
import time
import timeit
import statistics # 储存截图的目录
path_screenshots = "data/screenshots/" detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor('data/dlib/shape_predictor_68_face_landmarks.dat') # 创建 cv2 摄像头对象
cap = cv2.VideoCapture(0) # cap.set(propId, value)
# 设置视频参数,propId 设置的视频参数,value 设置的参数值
cap.set(3, 480) # 截图 screenshots 的计数器
cnt = 0 time_cost_list = [] # cap.isOpened() 返回 true/false 检查初始化是否成功
while cap.isOpened(): # cap.read()
# 返回两个值:
# 一个布尔值 true/false,用来判断读取视频是否成功/是否到视频末尾
# 图像对象,图像的三维矩阵
flag, im_rd = cap.read() # 每帧数据延时 1ms,延时为 0 读取的是静态帧
k = cv2.waitKey(1) # 取灰度
img_gray = cv2.cvtColor(im_rd, cv2.COLOR_RGB2GRAY) # start point
start = timeit.default_timer() # 人脸数
faces = detector(img_gray, 0) # print(len(faces)) # 待会要写的字体
font = cv2.FONT_HERSHEY_SIMPLEX # 标 68 个点
if len(faces) != 0:
# 检测到人脸
for i in range(len(faces)):
landmarks = np.matrix([[p.x, p.y] for p in predictor(im_rd, faces[i]).parts()]) for idx, point in enumerate(landmarks):
# 68 点的坐标
pos = (point[0, 0], point[0, 1]) # 利用 cv2.circle 给每个特征点画一个圈,共 68 个
cv2.circle(im_rd, pos, 2, color=(139, 0, 0)) # 利用 cv2.putText 输出 1-68
cv2.putText(im_rd, str(idx + 1), pos, font, 0.2, (187, 255, 255), 1, cv2.LINE_AA) cv2.putText(im_rd, "faces: " + str(len(faces)), (20, 50), font, 1, (0, 0, 0), 1, cv2.LINE_AA) # end point
stop = timeit.default_timer()
time_cost_list.append(stop - start)
print("%-15s %f" % ("Time cost:", (stop - start))) else:
# 没有检测到人脸
cv2.putText(im_rd, "no face", (20, 50), font, 1, (0, 0, 0), 1, cv2.LINE_AA) # 添加说明
im_rd = cv2.putText(im_rd, "press 'S': screenshot", (20, 400), font, 0.8, (255, 255, 255), 1, cv2.LINE_AA)
im_rd = cv2.putText(im_rd, "press 'Q': quit", (20, 450), font, 0.8, (255, 255, 255), 1, cv2.LINE_AA) # 按下 's' 键保存
if k == ord('s'):
cnt += 1
print(path_screenshots + "screenshot" + "_" + str(cnt) + "_" + time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) + ".jpg")
cv2.imwrite(path_screenshots + "screenshot" + "_" + str(cnt) + "_" + time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) + ".jpg", im_rd) # 按下 'q' 键退出
if k == ord('q'):
break # 窗口显示
# 参数取 0 可以拖动缩放窗口,为 1 不可以
# cv2.namedWindow("camera", 0)
cv2.namedWindow("camera", 1) cv2.imshow("camera", im_rd) # 释放摄像头
cap.release() # 删除建立的窗口
cv2.destroyAllWindows() print("%-15s" % "Result:")
print("%-15s %f" % ("Max time:", (max(time_cost_list))))
print("%-15s %f" % ("Min time:", (min(time_cost_list))))
print("%-15s %f" % ("Average time:", statistics.mean(time_cost_list)))
实时输出处理时间:
...
Time cost: 0.065273
Time cost: 0.059348
Time cost: 0.093570
Time cost: 0.091448
Time cost: 0.084946
Time cost: 0.089457
Time cost: 0.084367
Time cost: 0.094103
Time cost: 0.096082
Time cost: 0.073331
Time cost: 0.073685
Time cost: 0.065583
Time cost: 0.061161
Time cost: 0.061650
Time cost: 0.060952
Time cost: 0.084485 Result:
Max time: 0.112430
Min time: 0.057525
Average time: 0.085478
笔记本 CPU: i5-6200U@2.30GHz, Memory: 8G 处理时间平均在 0.08s;
# 请尊重他人劳动成果,转载或者使用源码请注明出处:http://www.cnblogs.com/AdaminXie
# 如果对您有帮助,欢迎在 GitHub 上 star 支持下: https://github.com/coneypo/Dlib_face_detection_from_camera
# 如有问题可以联系本人邮箱,商业合作勿扰谢谢: coneypo@foxmail.com
Python 3 利用 Dlib 实现摄像头人脸检测特征点标定的更多相关文章
- Python 3 利用 Dlib 实现摄像头实时人脸检测和平铺显示
1. 引言 在某些场景下,我们不仅需要进行实时人脸检测追踪,还要进行再加工:这里进行摄像头实时人脸检测,并对于实时检测的人脸进行初步提取: 单个/多个人脸检测,并依次在摄像头窗口,实时平铺显示检测到的 ...
- Python 3 利用 Dlib 和 sklearn 人脸笑脸检测机器学习建模
0. 引言 利用机器学习的方法训练微笑检测模型,输入一张人脸照片,判断是否微笑: 精度在 95% 左右( 使用的数据集中 69 张没笑脸,65 张有笑脸 ): 图1 测试图像与检测结果 项目实现的笑脸 ...
- Haar、pico、npd、dlib等多种人脸检测特征及算法结果比较
原文:opencv.pico.npd.dlib.face++等多种人脸检测算法结果比较 NDP检测结果: 结果分析: Pico(Pixel Intensity Comparison-based Obj ...
- Python 3 利用 Dlib 19.7 实现摄像头人脸识别
0.引言 利用python开发,借助Dlib库捕获摄像头中的人脸,提取人脸特征,通过计算欧氏距离来和预存的人脸特征进行对比,达到人脸识别的目的: 可以自动从摄像头中抠取人脸图片存储到本地: 根据抠取的 ...
- Python 3 利用 Dlib 实现人脸检测和剪切
0. 引言 利用 Python 开发,借助 Dlib 库进行人脸检测 / face detection 和剪切: 1. crop_faces_show.py : 将检测到的人脸剪切下来,依次排序平 ...
- Python 3 利用 Dlib 19.7 实现人脸识别和剪切
0.引言 利用python开发,借助Dlib库进行人脸识别,然后将检测到的人脸剪切下来,依次排序显示在新的图像上: 实现的效果如下图所示,将图1原图中的6张人脸检测出来,然后剪切下来,在图像窗口中依次 ...
- Python 3 利用 Dlib 19.7 和 sklearn机器学习模型 实现人脸微笑检测
0.引言 利用机器学习的方法训练微笑检测模型,给一张人脸照片,判断是否微笑: 使用的数据集中69张没笑脸,65张有笑脸,训练结果识别精度在95%附近: 效果: 图1 示例效果 工程利用pytho ...
- Python 3 利用 Dlib 19.7 进行人脸检测
0. 引言 / Overview 介绍 Dlib 中基于 HOG,Histogram of Oriented Gradients / 方向梯度直方图 实现 Face Detect / 人脸检测 的两个 ...
- Python 3 利用 Dlib 实现人脸 68个 特征点的标定
0. 引言 利用 Dlib 官方训练好的模型 “shape_predictor_68_face_landmarks.dat” 进行 68 个点标定: 利用 OpenCv 进行图像化处理,在人脸上画出 ...
随机推荐
- LoadRunner调用java函数测试oracle
LoadRunner调用java函数测试oracle 测试oracle的方法有很多,可以使用loadrunner的oracle协议直接调用oracle进行测试,也可以调用开发的java程序对oracl ...
- DataFrame查找
一 通过索引取数据 (ix/loc/iloc) loc (根据索引名称取数据 , 适合多列) iloc (根据索引序号取数据, 适合多列) at (和loc类似,只用于取单列, 性能更好) ia ...
- 404 Note Found 队-Alpha 事后诸葛亮
目录 设想和目标 计划 资源 变更管理 设计/实现 测试/发布 团队的角色,管理,合作 总结: 本小组和其他组的评分 分工和贡献分 全组讨论的照片 问题 第一组提问回答:爸爸饿了队 第二组提问回答:拖 ...
- +QFTPOPEN: 603,0 怎么把这样一个字符串中的 603 提取出来给一个 uint32_t 的变量那
+QFTPOPEN: 603,0 怎么把这样一个字符串中的 603 提取出来给一个 uint32_t 的变量那? 注意冒号后面有个空格!!! 答案:要使用 sscanf 标准库函数! char s ...
- selenium java maven 自动化测试(一) helloworld
本教程使用selenium-java,简单的完成了网页访问 网页内容获取,表单填写以及按钮点击. 1. 使用maven构建项目 在pom中添加如下依赖: <dependency> < ...
- css一边固定,另一边自适应的方法
第一种: 第二种:
- css布局-内容自适应屏幕
css页面布局,实现内容部分自适应屏幕,当内容高度小于浏览器窗口高度时,页脚在浏览器窗口底部:当内容高度高于浏览器窗口高度时,页脚自动被撑到页面底部. <style type="tex ...
- jq写无缝轮播
今天分享一下我自己早几天写的一个效果:无缝轮播,虽然不难,很简单,也没有封装处理过,但是还是希望能帮到一些前端的小伙伴吧,如果有小伙伴感觉有更简化的写法希望可以一起交流一下,技术在于交流嘛,我的邮箱是 ...
- day 33 线程
1.线程理论 什么是线程:线程是cpu的最小执行单位(实体),进程是操作系统的数据资源分配单位 2.线程的两种创建方式(重点) 查看线程的pid:使用os模块查看id,线程的id应该是相同的 3. ...
- 如何将M文件转成独立可执行程序
如何将MATLAB程序编译成独立可执行的程序?生成独立可执行的程序(exe文件)步骤 1.安装编译器.可有多种选择,matlab自带了一个LCC,推荐使用VC++6.0,我基于VS 2013实现 ...