概述
基本要求就是针对一段视频,里面的人判断是否完成了随机指定的某个动作(左转、右转、抬头、点头、张嘴、眨眼)。这属于非静默的活体识别,需要用户配合。
基本方案
使用dlib的人脸检测和关键点检测算法,获得人脸的基本姿态信息。但是dlib的68点信息无法直接用于头部姿态估计。我自己设计了一种简单高效的算法,把68点信息抽象为为一个4维向量,格式为(x, y, is_mouth_open, is_eye_open),前两个值分别表示水平和垂直上的转动程度,注意不是角度,可以认为是对关键点的线性回归值,但是单位不是度。通过合理设计,x\y这两个值基本只和68个点的相对位置有关,和脸和摄像头的距离和图片分辨率等无关,实现了不错的鲁棒性。is_mouth_open, is_eye_open这两个值是布尔类型值,就是用一些阈值判断出来的,也是缩放无关的。
基本效果如下:
一些优化技巧
上面一段讲的是对单帧图片进行人脸姿态估计,对一段视频进行活体识别需要逐帧处理。但是整个过程有点慢,为了加速,使用了下面几个技巧。
1.缩小图片分辨率。适当降低分辨率可以尽快检测速度,对最终结果影响不大。
2.间隔抽帧。我们要看的是动作过程,两帧间画面差距很小,没有必要每一帧都识别。
3.减少检测范围。人脸转动不会动很多,可以在上次检测的人脸附件检测人脸,减少检测的像素数。
4.适当引入跟踪。opencv的跟踪算法比dlib的人脸检测快,适当使用跟踪预测下一帧人脸的位置可加快速度。另外对于侧脸过大的时候,其实关键点还是可以定位到的,这时却检测不到了。利用跟踪算法可以在侧脸过大时多跟踪几帧。