流程
本节总结下人脸图片识别登录的流程,分为以下几步: 用户进入登录界面 ->点击人脸识别登录 ->用户截取图片,点击上传 ->后台接收图片,读取人员数据库内容,逐一对比 ->对比结果处理,满足阈值则通过检测,返回登录用户名,反之,返回失败原因 ->前端接收返回结果,成功,则跳转进入系统;失败则要求用户重传人脸图片
实现
前端代码
首先,在登录界面加入跳转代码
1
<a href="/face/login/">人脸登录</a>
接着在人脸识别界面点击打开摄像头按钮,当人脸进入摄像头视野范围后截取图片进行上传
1 | function $(elem) { |
现在的HTML5在引入webrtc机制,旨在不依赖外部插件为H5开发人员提供更好的音/视频开发支持,这种机制由标准化组织W3C进行H5 API的制定,由浏览器厂商来完成较低层的支持,现在主要的支持浏览器是chrome和Firefox,还有基于chrome内核的浏览器,更多支持可关注webrtc
本次实验所用js代码,先获取各元素,然后从用户获取媒体流,再根据用户的动作与服务器交互
因django后台开启csrf安全验证
1
MIDDLEWARE = ['django.middleware.csrf.CsrfViewMiddleware',]
所以我们要在模板页面加入
{% csrf_token %}
此时每个H5页面都引入了一个隐藏的csrf标签,通过以下代码进行获取:
1 | var csrfToken = document.getElementsByName("csrfmiddlewaretoken"); |
当用户点击update按钮时,我们采用ajax方法将数据post到后台
后台代码
主要涉及两个函数
数据库匹配
1 | def auth_user(img): |
在这里采取往数据库中存用户图片地址的方式记录用户人脸数据,不过,这里在进行用户匹配的时候会有很多重复的动作,当用户增多时,这些重复的动作会是我们优化的一个方向;
对于人脸识别,这里,我用的是开源项目face_recognition,它是基于dlib的人脸识别库,人脸识别的流程:
人脸位置检测:
1
face_recognition.face_locations()
ps:在face_recognition源码中,这最终是通过下面这段调用dlib库函数
1
face_detector = dlib.get_frontal_face_detector()
dlib是基于hog+线性分类器(svm)的分类器,外加图片金字塔和滑动窗口的方法,这种方法是在2005年由Dalal, Triggs提出,dlib实现的这个版本允许我们训练自己的人脸检测器,需要我们自己提供数据集及标注的xml文件,我们获得的检测结果是每张人脸左上、右下两个标记点组成的标记框,将其保存进变量中
人脸编码:
1 | face_recognition.face_encodings() |
将检测出位置的人脸进行编码(缩小图像编码的范围,利于人脸对比),这是为了之后人脸对比做准备,将每张人脸编码为128维向量
人脸比较:
1 | face_recognition.compare_faces(known_face, unknown_face_tmp_encoding, 0.4) |
比较待测人脸的编码向量与每个已知人脸的编码向量,取欧式距离作为计算依据,设定阈值(默认是0.6,2017年在LFW上获得99.38%的好成绩),将通过阈值检测的第一个为true的对象记为匹配账户
注:当时有尝试直接往mysql数据库中存二进制的人脸编码数据,希望能减少之后进行对比的开销,但存在编码问题,所以暂时选择只存储图片路径;其次,若存进数据库,那么到时进行数据库的查询将变得数据量庞大而缓慢,若数据库与服务器不在一个主机上,传输会成为问题;
处理人脸登录请求
1 | def loginFaceCheck(request): |
该函数处理人脸识别登录请求,为get时,渲染login_registration.html页面并返回;为post时,通过request.POST.get(‘faceImg’)获取用户图片,这里关于time的方法是用来查看各个阶段的运行时间,最后组装成Jon返回用户信息