python人脸识别使用python django框架_基于Django的web人脸识别登录功能设计与实现...

0 引言

人脸识别技术日趋成熟,开源的人脸识别库使大众更容易开发自己的应用方案,降低学习门槛,如旷视科技、商汤科技、海康威视,百度人脸识别SDK、OpenCV的人脸识别库、Python的第三方人脸识别库等;传统的web系统是通过登录页面输入用户名及密码的方式实现,本文研究讨论一种人脸识别登录方式,大致介绍其功能设计及实现原理。

本文使用的是Python的Django框架搭建web页面,使用Python的第三方库face_recognition作为人脸识别工具,验证了通过人脸识别登录系统的可行性。

1 所用技术

1.1 Django框架

Django是Python的开源web开发框架,可以快速开发网站架构,采用MVC(Model、View、Control)的开发模式,使前端视图,后端数据存储,页面逻辑控制分离,极大的提高了网站的开发效率。也是目前大多网站采样的开发模式,笔者最近在学的微信小程序开发也是采用这种MVC的开发模式。具体Django资料参考官方网站,关于Django的部分总结,可参考博文Django 学习笔记,【慕课网】强力Django和杀手级xadmin学习笔记

1.2 Ajax

在网站中比较常见的一种应用技术是Ajax,异步请求,即点击某个按钮,不重新加载整个页面,而是刷新部分页面,比如加载一个图片或者更新一个表格等都是用的这种异步请求原理。

在js中,通过Ajax请求,将前端的数据传送至后台,使用Python语句对其进行处理,并将处理后的数据返回前端。js中Ajax请求格式为:

$.ajax ({

type:"POST",

url:"/login/loginFaceCheck/",

beforeSend:function (xhr,setting) {

xhr.setRequestHeader("X-CSRFToken","{ { csrf_token }}");

},

dataType:'json',

data:{

"id":ID,

"faceImg":RightImage

},

success:function (displayList) {

// 返回成功

},

error:function () {

// 返回失败

}

})

注:

传送的类型可以为post和get,一般来说post的方式比get方式更加安全,在网页中form类型的表单的提交一般都是采用的post。而且本次采用post还有一个原因,data中的faceImg是base64格式编码的图片,数据特别特别长,采用get方式会报错,说url传输太长。

注意到Django中post表单的传送都会有{ { csrf_token}},这是一种安全机制。但是这次是按钮传送,而不是前端的form表单,因此必须要加上一句话,beforeSend:function (xhr,setting) {xhr.setRequestHeader("X-CSRFToken","{ { csrf_token }}");,在传送前强制加上{ { csrf_token}}

有传送的url,则只需要在django的urls中做相应的配置,即可运行对应的函数。在函数中必须返回json格式的数据,才能进入返回成功success函数中。

1.3 face_recognition

Python的第三方开源人脸识别库face_recognition的安装及使用说明参见官方github,地址为:https://github.com/ageitgey/face_recognition。总的来说其识别率达到99.38%以上。

1.4 tracking

javascript的开源第三方库tracking,A modern approach for Computer Vision on the web,具体可以参考其github,地址为https://github.com/eduardolundgren/tracking.js。其在本次实现中其的作用仅仅是在web页面加载摄像头,并框选出人脸部分。

1.5 其他

还用到的一些技术知识包括Html、CSS、Javascript、BootStrap、JQuery,不过用的只是一些皮毛的技术。

2 实施方案

2.1 操作流程

具体操作步骤是:点击身份核验按钮,判断是否有权限,并在前台显示。当两个摄像头都完成认证,且为不同的人脸时,完成验证,登录系统。

初始为未认证,见图1;如果未检测到人脸见图2;检测到人脸但未授权见图3;检测到人脸且授权见图4;在10s内未完成另一个摄像头的验证,则显示超时见图5.如果在10s内两个摄像头都完成人脸验证,则进入系统;当两个摄像头验证为同一个人时,报错,见图6;注:本次左右摄像头图像一样,是因为都用的是笔记本的摄像头。

图1 未认证

图2 未检测到人脸

图3(将人脸库中笔者的人脸删掉进行验证)未授权

图4 认证成功

图5 超时

图6 相同用户

程序大致流程包括:加载页面,加载人脸库,web页面加载摄像头并显示,摄像头获取的图片传至后台,后台解析图片并保存在本地,图片与人脸库对比,返回核验结果,前端显示,间隔时间判断,是否相同人脸判断等。操作流程见图7.其中右侧摄像头的程序流程与左相同。

图7 核验流程

2.2 部分代码

从前端获取图片并利用Ajax传送至后端,从后端获取核验结果在前端显示部分代码

// 身份认证标志及名字

var IdentifyNo1 = false;

var IdentifyNo2 = false;

var AuthNameNo1 ='';

var AuthNameNo2 ='';

// 计时器

var timeout;

$(document).ready(function () {

// 按钮 身份验证

$("#CheckNo1").click(function () {

var video = document.getElementById('video');

var canvas = document.getElementById('canvasL');

var context = canvas.getContext('2d');

context.drawImage(video,0,0,canvas.width,canvas.height);

var LeftImage = canvas.toDataURL("image/png");

var ID = 0;

// 利用Ajax 技术,将登陆界面人脸图片base64编码格式的图片传至后台

$.ajax ({

type:"POST",

url:"/login/loginFaceCheck/",

//必须添加 csrf_token

beforeSend:function (xhr,setting) {

xhr.setRequestHeader("X-CSRFToken","{ { csrf_token }}");

},

dataType:'json',

data:{

"id":ID,

"faceImg":LeftImage

},

success:function (displayList) {

// 处理认证后的数据

if (displayList.canLogin === true){

$('#DisplayNo1').text("验证成功: "+displayList.AuthName).removeClass("label-danger").addClass("" +

"label-success");

IdentifyNo1 = true;

AuthNameNo1 = displayList.AuthName;

if (IdentifyNo2 === true){

clearTimeout(timeout);

}

else{

// 开始计数,10s内,另一个如果没完成则验证失败

timeout = setTimeout(function () {

$('#DisplayNo1').text("验证失败: 超时").removeClass("label-success").addClass("label-danger");

IdentifyNo1 = false;

AuthNameNo1 = '';

},10000);

}

LoginSys(IdentifyNo1 ,AuthNameNo1, IdentifyNo2,AuthNameNo2);

}

else{

$('#DisplayNo1').text("验证失败: "+displayList.AuthName).removeClass("label-success").addClass("label-danger");

IdentifyNo1 = false;

AuthNameNo1 = '';

}

},

error:function () {

$('#DisplayNo1').text("验证失败: 未检测到人脸").removeClass("label-success").addClass("label-danger");

IdentifyNo1 = false;

AuthNameNo1 = '';

}

})

});

后端view处理函数

def loginFaceCheck(request):

## 人脸登陆验证

if request.method == "POST" and request.is_ajax():

# 获取base64格式的图片

faceImage = request.POST.get('faceImg')

# 提取出base64格式,并进行转换为图片

index = faceImage.find('base64,')

base64Str = faceImage[index+6:]

img = base64.b64decode(base64Str)

# 将文件保存

backupDate = time.strftime("%Y%m%d_%H%M%S")

if int(request.POST.get('id')) == 0 :

fileName = BASE_LOGIN_LEFT_PATH +"LeftImg_%s.jpg" % (backupDate)

else:

fileName = BASE_LOGIN_RIGHT_PATH + "RightImg_%s.jpg" % (backupDate)

file = open(fileName, 'wb')

file.write(img)

file.close()

# 删除多余的图片

filesLeft = os.listdir(BASE_LOGIN_LEFT_PATH)

filesLeft.sort()

leftImgCount = filesLeft.__len__()

filesRight = os.listdir(BASE_LOGIN_RIGHT_PATH)

filesRight.sort()

RightImgCount = filesRight.__len__()

if leftImgCount > 100:

# 图片超过100个,删除一个

os.unlink(BASE_LOGIN_LEFT_PATH +filesLeft[0])

if RightImgCount > 100:

# 图片超过100个,删除一个

os.unlink(BASE_LOGIN_RIGHT_PATH + filesRight[0])

# 对图片进行人脸识别比对

canLogin = False

AuthName = "未授权用户"

# 1> 加载相机刚拍摄的人脸

unknown_face = face_recognition.load_image_file(fileName)

unknown_face_tmp_encoding = []

try:

unknown_face_tmp_encoding = face_recognition.face_encodings(unknown_face)[0]

except IndexError:

canLogin = False # 图片中未发现人脸

# 2> 进行比对

### 第一种方法

# results = face_recognition.face_distance(known_face,unknown_face_tmp_encoding)

# 小于0.6即对比成功。但是效果不好,因此我们设置阈值为0.4,

# for i, face_distance in enumerate(results):

# if face_distance <= 0.4:

# canLogin = True

# AuthName = os.listdir(BASE_LOGIN_AUTH_PATH)[i][:-4]

### 第二中方法

results1 = face_recognition.compare_faces(known_face,unknown_face_tmp_encoding,0.4)

for i, face_distance in enumerate(results1):

if face_distance == True:

canLogin = True

AuthName = os.listdir(BASE_LOGIN_AUTH_PATH)[i][:-4]

JsonBackInfo = {

"canLogin": canLogin,

"AuthName": AuthName

}

return JsonResponse(JsonBackInfo)

3 小结

通过人脸识别可以完成web页面的登录功能,且有较高的正确识别率。这种方案避免了手动输入表单的繁琐,同时通过双身份认证人脸识别登录系统保证了系统的安全性。不足之处,一是需要提前在后端把已知的管理员人脸图片放入目录内,二是由于人脸较多,在初次加载页面时加载时间长。

以上,望读者大神们批评指正~

二赛君原创文章,转载请注明出处。

注:有偿提供开发技术指导,提供源代码。扫码,码上解决您的问题。

你可能感兴趣的:(django框架)