使用Dlib库实现人脸识别,比opencv更加好用
一、Dlib 库核心功能与代码细节解析
1. 人脸检测基础流程
Dlib 的人脸检测基于HOG 特征 + SVM 分类器,核心通过dlib.get_frontal_face_detector()
实现,返回人脸边界框(dlib.rectangle
对象),包含left()
/top()
/right()
/bottom()
等方法获取坐标。
代码示例(摄像头实时检测):
import dlib
import cv2detector = dlib.get_frontal_face_detector() # 初始化检测器
cap = cv2.VideoCapture(0) # 打开摄像头while True:ret, frame = cap.read()# 检测人脸(第二个参数为upsample_num_times,值越大检测越小的人脸)faces = detector(frame, 0) # 返回人脸列表for face in faces:# 绘制边界框cv2.rectangle(frame, (face.left(), face.top()), (face.right(), face.bottom()), (255, 0, 0), 2)cv2.imshow("Dlib Face Detection", frame)if cv2.waitKey(1) == 27:break
2. 68 点人脸关键点检测
需加载预训练模型shape_predictor_68_face_landmarks.dat
,输出 68 个关键点坐标(按面部区域分组):
- 0-16:下巴轮廓
- 17-21:左眉;22-26:右眉
- 27-30:鼻骨;31-35:鼻孔
- 36-41:右眼;42-47:左眼
- 48-59:嘴部外轮廓;60-67:嘴部内轮廓
代码示例(关键点提取与绘制):
import dlib
import cv2
import numpy as npdetector = dlib.get_frontal_face_detector()
# 加载关键点模型(需提前下载)
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")img = cv2.imread("face.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = detector(gray)for face in faces:# 获取关键点(shape.parts()返回68个点对象)shape = predictor(gray, face)# 转换为Numpy数组便于处理landmarks = np.array([[p.x, p.y] for p in shape.parts()])# 绘制关键点for (x, y) in landmarks:cv2.circle(img, (x, y), 2, (0, 255, 0), -1)cv2.imshow("Landmarks", img)
3. 基于关键点的应用扩展
(1)疲劳检测(疲劳检测.py
核心解析)
通过计算眼睛纵横比(EAR) 判断闭眼状态:
- EAR = (垂直距离均值) / 水平距离
- 阈值
<0.3
视为闭眼,连续 50 帧闭眼触发警报
def eye_aspect_ratio(eye):# 垂直方向关键点距离(1-5、2-4)A = euclidean_distances(eye[1].reshape(1, 2), eye[5].reshape(1, 2))B = euclidean_distances(eye[2].reshape(1, 2), eye[4].reshape(1, 2))# 水平方向关键点距离(0-3)C = euclidean_distances(eye[0].reshape(1, 2), eye[3].reshape(1, 2))return ((A + B) / 2.0) / C # 计算EAR# 提取左右眼关键点
rightEye = shape[36:42] # 右眼:36-41号点
leftEye = shape[42:48] # 左眼:42-47号点
ear = (eye_aspect_ratio(leftEye) + eye_aspect_ratio(rightEye)) / 2.0
(2)表情识别(表情识别.py
核心解析)
通过嘴部关键点计算两个指标:
- MAR(嘴宽高比):嘴部垂直距离均值 / 水平距离(判断张嘴幅度)
- MJR(嘴宽 / 脸颊宽比):嘴部宽度 / 脸颊宽度(判断微笑程度)
def MAR(shape):# 嘴部垂直距离(50-58、51-57、52-56)A = euclidean_distances(shape[50].reshape(1,2), shape[58].reshape(1,2))B = euclidean_distances(shape[51].reshape(1,2), shape[57].reshape(1,2))C = euclidean_distances(shape[52].reshape(1,2), shape[56].reshape(1,2))# 嘴部水平距离(48-54)D = euclidean_distances(shape[48].reshape(1,2), shape[54].reshape(1,2))return ((A+B+C)/3)/D # 平均垂直距离/水平距离def MJR(shape):M = euclidean_distances(shape[48].reshape(1,2), shape[54].reshape(1,2)) # 嘴宽J = euclidean_distances(shape[3].reshape(1,2), shape[13].reshape(1,2)) # 脸颊宽(3-13号点)return M/J
二、Dlib 与 OpenCV 的深度对比
技术细节 | Dlib | OpenCV |
---|---|---|
人脸检测原理 | HOG+SVM(精度高,对模糊图像鲁棒性强) | Haar 级联(速度快但易受光照影响)、DNN(精度接近 Dlib) |
关键点支持 | 内置 68 点 / 5 点预训练模型,调用简单 | 无原生关键点模型,需手动实现或集成其他库 |
实时性 | 单帧处理约 30ms(取决于 CPU,适合近景) | Haar 级联单帧处理约 10ms(适合远景实时检测) |
扩展性 | 提供机器学习工具(如 SVM、决策树) | 侧重图像处理(滤波、变换、特征提取) |
代码对比(摄像头人脸检测):
# OpenCV Haar级联检测
opencv_faces = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
faces = opencv_faces.detectMultiScale(gray, 1.1, 4) # 返回(x,y,w,h)# Dlib检测
detector = dlib.get_frontal_face_detector()
faces = detector(gray) # 返回dlib.rectangle对象
三、实际代码应用场景详解
1. 实时关键点可视化(关键点检测.py
)
- 功能:从摄像头实时采集图像,检测人脸并标注 68 个关键点编号。
- 关键代码:
# 循环处理每一帧 while True:ret, frame = cap.read()gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)faces = detector(gray)for face in faces:shape = predictor(gray, face)landmarks = np.matrix([[p.x, p.y] for p in shape.parts()])for idx, point in enumerate(landmarks):pos = (point[0,0], point[0,1])cv2.circle(frame, pos, 2, (0,255,0), -1) # 绘制点cv2.putText(frame, str(idx), pos, ...) # 标注编号cv2.imshow("Landmarks", frame)
2. 面部特征轮廓绘制(轮毂绘制.py
)
- 功能:通过
drawLine
(连线)和drawConvexHull
(凸包)绘制面部轮廓。 - 核心函数:
def drawConvexHull(image, shape, start, end):# 提取指定范围关键点(如36-41为右眼)facial_points = shape[start:end+1]hull = cv2.convexHull(facial_points) # 计算凸包cv2.drawContours(image, [hull], -1, (0,255,0), 2) # 绘制轮廓
3. 年龄性别预测(年龄性别预测.py
)
- 技术栈:OpenCV 的 DNN 模块(而非 Dlib),加载 Caffe 预训练模型。
- 流程:
- 用
faceNet
检测人脸边界框 - 截取人脸区域,转换为模型输入格式(
blobFromImage
) - 分别输入
genderNet
和ageNet
预测结果
# 性别预测 genderNet.setInput(blob) gender = genderList[genderNet.forward()[0].argmax()] # 年龄预测 ageNet.setInput(blob) age = ageList[ageNet.forward()[0].argmax()]
- 用
四、总结
- Dlib 优势:在人脸关键点检测和精细化特征分析(如表情、疲劳)中表现优异,适合需要高精度面部特征的场景。
- OpenCV 优势:全能型视觉工具,擅长图像处理、摄像头交互和快速目标检测,常作为 Dlib 的辅助工具(如图像读写、显示)。
- 组合用法:实际项目中常结合两者 —— 用 Dlib 提取关键点,用 OpenCV 进行图像预处理(如灰度转换)和结果可视化。