一、介绍
这是一个基于 dlib 人脸 68 关键点 和 眼睛纵横比 EAR 的实时疲劳检测程序。整体思路是:用摄像头读取视频帧,检测人脸,定位眼睛关键点,计算眼睛睁开程度;如果连续多帧眼睛闭合,就认为可能疲劳并给出警告。
二、核心代码讲解
2.1导入库

numpy:数组运算,保存关键的坐标。
dlib:人脸检测和人脸68关键点预测。
cv2:OpenCV,读取摄像头、显示图像、画图。
eucliden_distances:计算两个点之间的欧式距离。
PIL:因为OpenCV的putText不支持中文,所以用PIL在图像上绘制中文。
2.2计算眼睛纵横比:eye_aspect_ratio

眼睛的6个关键点通常顺序为:
eye0:左眼角或外眼角;
eye1:上眼脸外侧
eye2:上眼脸内测
eye3:右眼角或内眼角
eye4:下眼脸内测
eye5:下眼脸外侧
计算逻辑:
A=distance(eye1,eye5):上眼脸外侧到下眼脸外侧的垂直距离。
B=distance(eye2,eye4):上眼脸内侧到下眼脸内侧的垂直距离。
C=distance(eye0,eye3):眼睛水平宽度。
EAR = ((A+B)/2)/C
当眼睛睁开时,垂直距离较大,EAR较大。
当眼睛闭合时,垂直距离变小,EAR变小。
因此EAR可以作为判断闭眼的指标。
euclidean_distances返回的是二维数组,所以最终ear不是普通浮点数,而是形如\[0.31的数组。后面代码用ear00取出数值。
2.3在OpenCV图像上绘制中文:cv2AddChineseText

OpenCV默认的cv2.putText不能直接显示中文,所以这里借助PIL:
1.如果传入的OpenCV的numpy.ndarray,先转成PIL图像。
OpenCV默认颜色顺序是BGR。
PIL默认颜色顺序是RGB。
所以用cv2.cvtColor(img, cv2.COLOR_BGR2RGB)转换。
2.创建ImageDraw.Draw对象,用于在图像上画文字。
3.加载中文字体simhei.ttf,字号由textSize指定。
4.使用draw.text在position位置绘制文字。
5.最后把PIL图像再转回OpenCV的BGR格式并返回。
2.4绘制眼睛凸包:drawEye

cv2.convexHull(eye):根据眼睛的6个点计算凸包,方便画出一个包围眼睛的轮廓。
cv2.drawContours:在frame上画出轮廓。
frame是全局变量,在后面在主循环中定义。
eyeHull:轮廓列表。
-1:画所有轮廓。
(0,255,0):绿色。
1:线宽
2.5初始化变量和模型

COUNTER = 0:记录连续闭眼的帧数。
detector = dlib.get_frontal_face_detector():构造dlib的正脸检测器。
predictor = dlib.shape_predictor:加载68点人脸关键点模型。
cap=cv2.VideoCaputer(0):打开默认摄像头,索引0通常表示第一个摄像头。
2.6主循环:读取摄像头并检测

ret,frame = cap.read():ret表示是否成功读取一帧。frame是当前视频帧。
faces = detector(frame,0):用dlib检测人脸。第二个参数0表示不进行上采样,速度较快,但小脸可能漏检。faces是检测到的人脸矩形列表。
2.7遍历每一张人脸

predictor(frame,face):根据人脸区域预测68个关键点。
shape.parts():返回68个关机点对象。
\[p.x,p.yfor p in shape.parts()]:把每个关键点转成x,y坐标。
np.array():转成NumPy数组,方便切片和计算。
2.8提取左右眼关键点

dlib的68点模型中:
索引36到41:右眼:共6个点。
索引42到47:左眼,共6个点。
2.9计算EAR

分别计算右眼和左眼的纵横比;
取平均值作为当前帧的眼睛睁开程度。
因为eye_aspect_ratio返回的是二维数组,所以ear也是数组。
2.10疲劳判断

逻辑:
如果ear<0.3,认为当前帧眼睛闭合或接近闭合。
COUNTER += 1:连续闭眼帧数加一。
如果连续闭眼达到50帧,就认为可能疲劳,在图像上显示"!!!!危险!!!!"。
如果ear>=0.3,说明眼睛睁开,COUNTER清零。
三、总结
整体流程为:
-
打开摄像头。
-
读取一帧图像。
-
用 dlib 检测人脸。
-
对每张人脸预测 68 个关键点。
-
提取左右眼各 6 个点。
-
计算眼睛纵横比 EAR。
-
如果 EAR 小于 0.3,连续闭眼计数加一。
-
连续闭眼超过 50 帧,显示"!!!!危险!!!!"。
-
绘制眼睛轮廓,显示 EAR 数值。
-
循环执行,直到按 ESC 退出。
-
释放摄像头和窗口。