一、项目情况
【0801更新】
最近事情实在太多,本想着项目结束后,把自己的心得体会好好整理一下,发现好像也没有什么能分享给大家的,暂且不再更新此主题了。
如果有其他想法,我会在其他文章中写。
不过最近这段时间给我最大的体会是:聚焦。最重要的事只有一件,把最重要的事情解决了,就解决了80%的问题。
项目介绍
这是一个人脸识别和眨眼计数,得出疲劳状态的项目。
写到博客上面,一方面记录整理有序,一方面也把掉坑的过程记录下来,给自己也给大家做一个避坑参考。
总体路线
项目整体目的,就是通过PERCLOS P80的方法,识别人体疲劳状态。
经过前期研究,通过计算EAR(眼睛长宽比),以及与闭眼阈值的比较,得出眨眼的过程,结合P80原则计算得出疲劳的状态。
思路
由于起步阶段,具体实现思路在下面的“实现思路”中进行具体描述以及不断纠正。
本人算是DeepLearning刚刚起步的小白,之前实践过一些人工神经网络的毕设项目,在matlab中调试BP、RBF神经网络,对深度学习、机器视觉算是从头学习。记录下整个过程,向大家学习,项目的不足之处也请各位大佬们不吝赐教。
闲话少叙接下来就看项目思路和遇坑。
我把遇坑单独拿出来放到另一个博客里面了,和这篇博客对应:https://blog.csdn.net/newsahara/article/details/122875650
二、实现思路
思路1:利用OpenCV提供的dlib人脸探测器以及68个关键点的预测器
Dlib官方训练好的68_face_facemark模型,可以直接拿来用。
下载地址:http://dlib.net/files/
下载文件:shape_predictor_68_face_landmarks.dat.bz2
# 基于HOG级联识别脸部
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
返回值是<class ‘dlib.dlib.rectangle’>,就是一个矩形,坐标为[(x1, y1) (x2, y2)]。就是绿色方框的左上右下坐标。
结果如图:
思路1问题
有了眼部周围的六个特征点坐标,就可以计算EAR了,然后计算源选择摄像头。
这里有一个问题,实时性和鲁棒性太差。
检测的实时视频太慢,头稍微一偏,就识别不到脸部了。
解决方法
通过其他实时性、鲁棒性更好的模型,做脸部识别,然后在脸部方框中,计算眼部周围6个特征点坐标,而不是计算整个面部的68个特征点。
符合且自己还算够得着的模型有YOLOV5、MTCNN模型。
思路2
YoloV5识别脸部 -> 再通过YoloV5回归眼部周围6个关键点
YoloV5的下载和安装不赘述。遇到的坑往下看遇到的问题。
真正的难点在于:如何通过YoloV5回归眼部周围6个关键点
要训练自己的模型,一定要找到合适的数据集,遍寻整个网络,确定采用wlfw的人眼数据集。
数据集介绍移步这里:https://github.com/midasklr/98-FaceLandmarks
P.S.特别感谢上面数据集的作者,他将JD和WLFW dataset做了重新整理,实打实给我们节省了很多时间,点赞!
目前需要研究的就是上面的难点
刚刚看到了这篇博客,恍然大悟,奉上链接:yolov5-face
最关键的一句是:
getitem()时,对每张图片,对应标注的数据维度为[ num_objects,14] ,每一行的数据格式为[x, y, w, h, x1, y1, x2, y2, x3, y3, x4, y4, x5, y5]. 前四个为归一化的人脸bbox的中心和宽高,后面10个为归一化的人脸5点关键点的坐标。
所以,既然5个关键点可以训练,结合wlfw的数据,我可以把后面的5个点扩充为左右眼部的12个特征点。
有了思路就往下干。
- 数据集处理
WLFW的数据集最初是98个点,我需要将数据集处理成为YOLOV5的数据集的样子,将txt文件,拷贝到excel中,作为.CSV文件,处理会比较快。98个点的分布如下图:
因此,我需要的点是右眼60-67,左眼68-75。
----数据集标签处理----
①完成60-75的点位的确认;
②将wflw的数据集格式转为yolov5的数据集格式
在这里要写一个脚本,将数据集改为yolov5需要的数据集,可能要稍微花费一点点时间。
yolov5的坐标转换以及归一化,我参考的是这个博客:YoloV5归一化
做这个小脚本还是听花费时间的,毕竟本人的python编程能力也有限。
很多知识都是现百度的,不过还好,不管怎么样呢,处理完成了。
有了数据集,在训练时又发生了这个错误:
cannot reshape array of size 35 into shape (2)
一波未平,一波又起,接着查找解决办法。
问题原因确定了:annotation的向量维度变化,不再是5个,而是更多,需要修改相关的代码。
已经看了两个全天的yolo_face代码了,将yolo_face的5个关键点输入修改为识别眼部周围12个关键点的难度,目前来看远远超出了我的能力范围。大致过程描述如下:
- 我想的是可以简单的将5个关键点,直接扩展为label里的数据,但是维度变化在face的代码里限制很多,比如遇到了plandmarks的维度就很不好解决,现在看好像是网络model的输出需要调整,不知道对不对,通过调参数我已经不会调了,只好暂时放下这个思路,转向其他的思路。
- 昨晚上又挣扎了一下,把代码调通可以训练了,BUT,我完全不知道自己的调试参数对不对,只能说训练了,只能说Tensor的维度对上了,能够计算,这样的调参数没有任何意义,相当于还是没有摸透里面的门道,所以还需要继续努力。不过,yolo做关键点的检测暂时放一放了,寻找其他模型来做关键点检测。yolo可以做目标检测。
YoloV5项目小计: 一共花了一周左右的时间,目前掌握的有:yoloV5网络训练的方法、其数据集的制作、数据集的整理(修改、归一化),可以自己编写脚本改动数据集。
思路3:MTCNN模型识别人脸+人眼关键点
MTCNN原文参考地址:MTCNN原文传送
总体方法的参考博客:参考博客地址
MTCNN训练非常简单,用WFLW数据集和landmark数据集也很容易搞通训练,但是有一个非常严重的问题,就是我的显卡内存比较小,只有2G,当MTCNN的R网络输出结果时,一张图片可能会遇到很多张脸,作为O-net网络的输入直接爆掉显存OOM…无奈我只能暂时将这些大的图片记录下来,然后从训练集数据中删除掉。
更严重的是,训练的o_net网络,最后loss居然是NaN,也就是出现负数了,第一次训练出现这样的问题没关系,继续死磕MTCNN,必须搞通它。
(3.22继续开始)
今天想继续用MTCNN做关键点检测。
思路4:Retinaface网络模型
step1:实现网络训练
由于,呃,自己的电脑和水平确实不够,MTCNN训练多人脸场景时候,显卡爆了,OOM。。。所以我选了利用anchor方式的一次性多任务训练网络,借助wider的数据,训练了2天,远远没有达到能够应用的程度,但是,这是标志性的事情,起码,我把整个训练调通了。
小结一下整个过程:
利用pytorch的框架,训练集的读取,也就是dataset的继承部分,一定要写好,变成合适的部分。
网络模型部分:需要将网络的输入和predict部分,改为自己想要得到的。
Loss计算部分,需要结合自己的模型进行具体修改。
然后剩下的就是等待网络模型的参数训练完毕,哈哈,过程描述很简单,遇到了很多的问题,只是最近工作忙,根本没时间记录。
然后下一步需要做的工作还有很多,了解一下训练的中断与继续训练,如何计算EAR、EAR mean,如何评价网络…
- Torch的中断与继续训练可以从保存权重文件、加载权重文件实现。
step2:固定bbox,仅训练Landmarks(暂缓实现)
整个网络的模型,可以一次实现3种检测:分类、bbox回归、landmark回归,我的思路是利用已经训练好的网络,仅对landmark进行眼部周围16点的训练。
思路5:
采用目标检测和分类的方法:
识别眼睛 -> 对睁眼、闭眼进行分类 -> Perclose方法识别疲劳
识别眼睛方法:MTCNN、Retinaface
对睁眼、闭眼进行分类:vgg-16的迁移学习,或者ResNet的迁移学习
整体思路
优化思路:
1数据集:
- 更换数据集,改换专门的人脸landmark的数据集,wflw数据集里面,太多太小的人脸数据,并不好。
- 通过dlib识别闭眼的图片,对关键点进行标识,取得相应的数据集
2网络模型:
- 在更换数据集基础上,再尝试MTCNN模型、Retinaface模型(mobilenet和resnet都尝试一下)
环境配置篇
今天在单位找到了一台联想SR658服务器+RTX2080Ti的环境。下决心把服务器环境搭好、调通,这样以后我再训练什么网络的时候,起码不会因为硬件原因,导致训练不下去了(就像MTCNN的教训一样,人脸数量一多久OOM爆卡),同时训练速度也会大幅提升。
今天(3.16)刚把anaconda、pycharm安装好,后面要把环境配置好,然后就可以训练我的retinaface网络了。
今天(3.18)把我从京东二手拍拍店买的一块gtx1050Ti显卡装上并且环境调通了。为什么要把自己的台式机也装上环境呢,主要靠虑更加便于训练,有了自己的炼丹炉,怎么都好用不是,单位的大显卡可能还得排队用。
(05.31)时间飞逝,我得跟大家汇报最近这段时间的情况,4月初开始出差,到5月中旬回家,后续居家隔离、居家办公,一直未能到单位,在训练环境这块不能有很好的进展。
算法方面,之前用retina face训练的网络,效果真的很差,图就不上了,就是眼睛的位置根本合不上。我在思考是什么问题,如果是我自己数据的问题,训练那么多轮,训练效果很好,但是测试时候,数据差到爆,我就不知道怎么办了。
目前还在想办法攻克中。
最近看到一位B站博主的一句话,对于科研工作是很有道理的,就是:宁要深刻的片面,也不要肤浅的全面。
论文这块,就在一个点,往深了整。
叮~~~~
我觉得有必要为我买显卡的这家店做一个单独广告:大家可以在京东搜索精瑞二手电脑专营店:https://mall.jd.hk/index-791507.html。这家店真的服务超级赞,我第一次买的gtx 1060,最后由于电源小了,无法给显卡单独供电(原谅我这个硬件小白),店家二话不说帮换成了1050Ti,显卡装上就能用,真的很放心、很开心的一次购物体验,而且我是拿到了他们中关村店里,发现很专业的团队,确实让人放心,让我能够买到实惠、可靠的显卡,再次表示感谢,大家如果有需要,也可以考虑他们。
- 安装显卡驱动
- 安装cuda tookit 和 cudnn,我的是v10.0+v7.6.5,参考博客:[博客链接](https://blog.csdn.net/xinxiang7/article/details/108541316)
- 配置anaconda和pycharm环境
思路创新
我在想,如果要出论文,可是要有创新点的,结合上面的所有思路,我的创新点在哪里呢?继续多读论文吧,多看看别人的思路,给自己找找出路。
鼓励一下自己:
最近已经停两周时间了。这两周一直在忙工作上的事情,实在是抽不出身继续我的“深度大业”,今晚终于有时间了,有时候工作确实耽误自己的学习,可是为了生存,不能不继续工作,谁不是负重前行着往前走呢?别瞎想,埋头干。