说明:
-
前端部分:前端使用的是layui组件
-
后端部分:使用的是Django框架
- 注:我会提前说一下我思路,可根据思路,后端可用其他语言自行编写(如:Java 等)
前端思路简单说一下:
-
点击用户登录页的“人脸识别登录”按钮,输入要登录的账户名字,先查看有没有,如果账户存在则打开视频流窗口进行人脸识别
-
当打开识别窗口后,等待3s开始对视频中的人脸进行识别,当检测到人脸的时候会将人脸的范围框出并实时跟踪人脸
-
将识别到的人脸进行截图并将人脸截图转为B64码的形式发送到后端(人脸截图的大小和人脸跟踪时方框大小一致,)
-
在此后端接收前端传过来的B64码进行解码转译,使得与数据库中的用户图片进行对比,来验证是否是同一个人(此处可换做其他后端编程语言如java等)
-
匹配成功后,自行登录跳转。
-
注意请在光线较好的环境下来识别登录
好!思路说完,那就上代码(前端)!!!!
- 当然此时你肯定在html中引用了layui.js 文件了吧!这不用我多说了!!
- 在这之前你要先创建一个名为 `face.js` 的js文件,用于前端人脸识别的处理,
- 在html中提前引用这个js文件,
HTML部分:
搞一个 form表单,里面写一个按钮,再自己调调样式就行!记住自己按钮中的 id 等等的哈~
<!--自己写一个点击按钮!!!亲!! -->
<form action="/login/" method="POST">
{% csrf_token%} <!--这个东西,在django框架中的语法,非django框架可删掉!!!-->
<div class='login_fields'>
<div class='facelogin' style="padding-top:30px; align-items: center;display: flex;justify-content: center;">
<input class="layui-btn layui-btn-primary layui-border-blue" style="border-radius: 20px;width:132p;margin-left:15px;" type="button" id="face_login" lay-submit lay-filter="face_login" value='人脸识别登录'>
</div>
</div>
</form>
js部分(关键)---- face.js :
layui.use(['form','table','layer'],function(){
var form = layui.form;
var layer = layui.layer;
var $ = layui.$;
$(function() {
$('#face_login').click(function() {
//提前说一下:你需要在下面 var video 的里面 添加一个 用户账号的输入框和input按钮 用于对特定用户是否存在的二次校验,这样会更加便捷 !!!!!!
var video = '<div id="videosee"> <video id="video" width="640" height="535" preload autoplay loop muted></video> <canvas id="canvas" ></canvas></div>';
var areaWidth = '640px';
var areaHeight = '200px';
// 打开弹出层
var layerIndex = layer.open({
type: 1,
title: '人脸识别登录',
area: [areaWidth,areaHeight],
content: video,
success: function(layero, index) {
// 获取层元素更改area用
var layerElem = document.getElementById(layero.attr('id'));
// 设置宽度和高度
layerElem.style.width = areaWidth;
layerElem.style.height = areaHeight;
// 获取 video 元素
var videoElement = document.getElementById('video');
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
document.getElementById("videosee").style.display = "none";
//下面的 #ovpost 是一个查询按钮,和刚开始的 var video 中直接添加的用户账号二次校验是否存在 相关联 (本代码中和与其相关的ajax等用户二次校验已删除)
// $("#ovpost").click(function(){
// 更新area的值
var newAreaWidth = '640px';
var newAreaHeight = '655px';
var newOffsetTop = '100px';
var newOffsetLeft = '550px';
layer.style(layerIndex, {
width: newAreaWidth,
height: newAreaHeight,
top: newOffsetTop,
left: newOffsetLeft
});
// 刷新弹窗位置
layer.msg(response.msg);
document.getElementById("videosee").style.display = "block";
document.getElementById("fonts").style.display = "none";
setTimeout(function(){
// 将 canvas 元素大小设置为与 video 元素相同
canvas.width = videoElement.offsetWidth;
canvas.height = videoElement.offsetHeight;
// 设置 video 和 canvas 的位置重合
videoElement.style.position = 'absolute';
canvas.style.position = 'absolute';
canvas.style.top = videoElement.offsetTop + 'px';
canvas.style.left = videoElement.offsetLeft + 'px';
// 初始化 face tracker
var tracker = new tracking.ObjectTracker('face');
tracker.setInitialScale(4);
tracker.setStepSize(2);
tracker.setEdgesDensity(0.1);
// 开始跟踪人脸
tracking.track('#video', tracker, { camera: true });
// 监听 face tracker 的 track event
var timeoutId;
tracker.on('track', function(event) {
// 在每次绘制前清空画布
context.clearRect(0, 0, canvas.width, canvas.height);
console.log('人脸', event.data.length)
if (event.data.length === 0) {
// 未检测到人脸
// layer.msg('未检测到人脸!')
} else if (event.data.length === 1) {
event.data.forEach(function(rect) {
context.strokeStyle = '#a64ceb';
context.lineWidth = 2;
context.strokeRect(rect.x, rect.y, rect.width, rect.height);
// 截取人脸图像
var faceCanvas = document.createElement('canvas'); // 创建一个新的canvas元素
faceCanvas.width = rect.width ;
faceCanvas.height = rect.height ;
// 设置绘图质量
faceCanvas.getContext('2d').imageSmoothingEnabled = true;
faceCanvas.getContext('2d').imageSmoothingQuality = 'high';
faceCanvas.getContext('2d').drawImage(videoElement, rect.x, rect.y, rect.width, rect.height, 0, 0, faceCanvas.width, faceCanvas.height);
var faceDataUrl = faceCanvas.toDataURL(); // 调用toDataURL()方法将canvas内容转换为base64编码
console.log( faceDataUrl);
var formData =new FormData();
formData.append('imgData',faceDataUrl);
$.ajax({
url: '/face_login/',
type: "POST",
dataType:'json',
contentType:false,
processData:false,
headers: {'X-CSRFToken': $('input[name=csrfmiddlewaretoken]').val()},
data: formData,
success: function(response) {
if (response.code === 0){
var formData1 =new FormData();
formData1.append('userid',$('#ovName').val());
//下面的ajax的url是用于判断账户的状态(正常或禁用)
$.ajax({
url: '/XXXXXXXXXXXXXXXXXXXXXX/',
type: "POST",
dataType:'json',
contentType:false,
processData:false,
headers: {'X-CSRFToken': $('input[name=csrfmiddlewaretoken]').val()},
data: formData1,
success: function(response) {
if (response.code === 0){
//如果code=0则识别成功,进行登录跳转
window.location.href = '/admin/'
layer.msg(response.msg);
}else {
layer.msg(response.msg);
return
}
}
});
layer.msg(response.msg);
}else if (response.code === 404){
layer.msg(response.msg);
return
}
}
});
});
}
});
layero.find('.layui-layer-close').on('click', function() {
if (videoElement && videoElement.srcObject) {
var tracks = videoElement.srcObject.getTracks();
tracks.forEach(function(track) {
track.stop();
})
}
layer.close(index);
window.location.href = '/login/';
});
},3000);
}); //
},
});
});
});
});
- 此处js代码完毕,再次声明,上面的是纯核心部分。可参考~
- 如果想要:当B64码传入后端后,对指定用户直接校验您还需要在 上文的js中 按照我所对其相关备注部分, 自行添加相应的功能(指的是:用户二次查询校验功能)
- 如果不添加指定用户的二次校验,(指的是:直接将代码复制拿来用。)那么后端的话,你就需要将b64编译后对所有用户的存储人像照片进行for循环遍历,相当于挨个挨个的去校验匹配,直到有匹配成功为止。(费时费力~)
有什么不懂的地方,可以私信或留言,我会回答到你运行成功实现为止~~~
感觉您出现的问题内容较多,请直接私信吧··········
最后:
-
face.js全部源码地址:待上传更新~~~~
-
layui人脸识别登录-----Django后端部分(需带二次校验) 地址: 待更新~~~没有人需求的话,就随缘更新了,,,,