人脸的各个部位是按照特定的位置存在的,所以便可以对其进行序列设置。
这就是一个人脸序列的设计,当然我们可以有自己的设置,但是接下来的思路采用的模型正是利用的这个序列设置,我们只需要明白可以这样设计即可。
基于此,我们的思路是这样的:
(1)将上述的序列按照指定部位设置好,打包成一个字典。
Face_section_index = OrderedDict([
("jaw", (0, 17)),
("left_eyebow", (22, 27)),
("right_eyebow", (17, 22)),
("nose", (27, 36)),
("left_eye", (42, 48)),
("right_eye", (36, 42)),
("mouth", (48, 68))
])
(2)接着我们要读入我们要识别的视频
(3)加载已有模型,识别视频帧中的人脸,以及人脸各部位的坐标
# 获取人脸的检测器,detector可以检测图像中的人脸,并返回人脸的位置信息
detector = dlib.get_frontal_face_detector()
# 加载已经训练好的人脸模型用于读取68个坐标
predictor = dlib.shape_predictor(args["shape_predictor"])
faces = detector(gray, 0)
shape = predictor(gray, face)
(4)考虑到一帧视频中不一定只有一张脸,所以我们要加一个for循环识别每一个脸的各部位坐标,同时视频是多帧的,需要一个while循环来读取每一帧,考虑结束必然是帧读完还可以是esc退出
(5)如何判断是在眨眼呢,我们依据一篇论文来进行判断,上面提到有个公式对应眼睛部位的6个坐标,我们计算出来的数值只要小于一定的阈值,就算是眨眼
# 特殊公式计算眼睛6个坐标的含义值
def cal_eye_value(eye):
# 计算竖直方向距离
A = dist.euclidean(eye[1], eye[5])
B = dist.euclidean(eye[2], eye[4])
# 计算水平方向距离
C = dist.euclidean(eye[0], eye[3])
# 特殊计算公式,可参考readme中指定的论文
value = (A + B) / (2.0 * C)
return value
(6)如何界定眨眼多少次就算是疲劳,故需要一个限制,这里我设置连续三帧眨眼就算是疲劳,总数增加一个
(7)释放视频,关闭窗口
vs.release()
cv2.destroyAllWindows()
(8)当然,其中我们画出一些图案在视频中实时显示记录
完整代码:wang-lixiang/blink_detection: 对视频中的人脸进行识别,并记录其眨眼的情况,以此可以来判断是否处于疲劳驾驶的状态 (github.com)