人脸识别离线SDK整合系统(虹软)

人脸识别离线SDK整合系统(虹软)

1 前言

整合人脸识别实现刷脸登录,需要进行一定的步骤:

  • 下载离线SDK

  • 相关配置

  • 后端代码逻辑

  • 前端界面展示

  • 测试

2 整合人脸识别

2.1 下载离线SDK

ArcFace 3.0 免费离线人脸识别SDK:独立离线版SDK,拥有人脸检测、人脸对比、人证比对、人脸跟踪等功能。

进入ArcFace开发平台下载适合自己系统的免费离线SDK,免费版和增值版区别如下图

2.2 相关配置

作者下载的windows64版本的,下载解压后文件目录如下

1
2
3
4
5
6
7
8
9
ArcFace
doc
ARCSOFT_ARC_FACE_JAVA_DEVELOPER'S_GUIDE.pdf //开发文档
libs
WIN64
... //引擎文件
arcsoft-sdk-face-3.0.0.0.jar //jar包
samplecode
FaceEngineTest.java //测试类

还需要在ArFace上获取appId和sdkKey,如下图

将jar包导入自己的项目。

将解压文件保存到合适的地方。

2.3 后端代码逻辑

UserAction.java:面部信息录入方法和登录方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/**
* 录入面部信息
* @return
*/
public String addFace() {
User users = (User) ServletActionContext.getRequest().getSession().getAttribute("user");
if(!users.getLoginPwd().equals(MD5Utils.md5(user.getLoginPwd()))){
jsonData.put("code", 100);
}else{
int isFace = FacesUtil.findFace(user.getFaceImg());
if(isFace == 2){
String faceImg = BaseData.baseData(user.getFaceImg());
user.setFaceImg(faceImg);
userService.addFace(user);
if(users.getFaceImg() != null){
File file = new File("F:\\IDEA\\workspace\\wanjia\\src\\main\\webapp\\upload\\faceimg\\"+users.getFaceImg());
file.delete();
users.setFaceImg(faceImg);
ServletActionContext.getRequest().getSession().setAttribute("user", users);
}
jsonData.put("code", 200);
}else if(isFace == 1) {
jsonData.put("code", 300);
}else {
jsonData.put("code", 400);
}
}
return "addFace";
}
/**
* 用户登录的方法
* @return
*/
public String jsonLogin() {
if(user.getFaceImg() == null){
user = userService.login(user);
}else{
int isFace = FacesUtil.findFace(user.getFaceImg());
if(isFace == 2){
List<User> userList = userService.findUserAll();
user = FacesUtil.faces(user.getFaceImg() ,userList);
}else if(isFace == 1) {
jsonData.put("code", 300);
return "jsonLogin";
}else {
jsonData.put("code", 400);
return "jsonLogin";
}
}
ServletActionContext.getRequest().getSession().setAttribute("user", user);
if(user!=null) {
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Orders.class);
jsonData.put("code", 200);
if(user.getUserType().getUserTypeId()==3) {
jsonData.put("type", 3);
}else if(user.getUserType().getUserTypeId()==2){
detachedCriteria.createAlias("house","h" ).add(Restrictions.eq("h.user.userId", user.getUserId()));
jsonData.put("type", 2);
}else {
detachedCriteria.add(Restrictions.eq("user.userId",user.getUserId()));
jsonData.put("type", 1);
}
jsonData.put("data", user);
boolean flag= orderService.showOrder(detachedCriteria);
if(flag){
jsonData.put("info", 100);
}
}

return "jsonLogin";
}

BaseData.java:后端接受的img信息是BASE64码,需要进行解码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package com.wanjia.utils;

import sun.misc.BASE64Decoder;

import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;


/**
* @description: BASE64解码
* @author: fenghao
* @date: 2020/4/10
**/
public class BaseData {
public static String baseData(String img){
byte[] bytes = FacesUtil.baseData(img);
//字节流转文件
FileOutputStream fos = null;
String imgpath = reName();
String name ="F:\\IDEA\\workspace\\wanjia\\src\\main\\webapp\\upload\\faceimg\\"+imgpath;
try {
fos = new FileOutputStream(name);
fos.write(bytes);
} catch (
IOException e) {
e.printStackTrace();
} finally {
if (fos != null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return imgpath;
}
public static String reName() {
String format= new SimpleDateFormat("yyyyMMddHHmmSS").format(new Date());
int num = (int)(Math.random() * (999999 - 100000) + 100000);
return format+num+".jpg";
}

}

FaceUtil.java:人脸比对工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
package com.wanjia.utils;

import com.arcsoft.face.*;
import com.arcsoft.face.enums.DetectMode;
import com.arcsoft.face.enums.DetectOrient;
import com.arcsoft.face.enums.ErrorInfo;
import com.arcsoft.face.toolkit.ImageInfo;
import com.wanjia.domain.User;
import org.springframework.stereotype.Service;
import sun.misc.BASE64Decoder;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static com.arcsoft.face.toolkit.ImageFactory.getRGBData;

/**
* @description: 人脸比对工具类
* @author: fenghao
* @date: 2020/4/9
**/
@Service
public class FacesUtil {
private static String libPath = ""; //刚官网下在的libs\WIN64里的引擎文件
private static String appId = ""; //官网获得的appId
private static String sdkKey = ""; //官网获得的sdkKey
private static int errorCode;
private static FaceEngine faceEngine;
private static ImageInfo imageInfo;
private static List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();

/**
* @param:
* @description: 初始化引擎,项目启动时加载
* @return: void
* @date: 2020/4/24
*/
@PostConstruct
public static void initEngine() {
faceEngine = new FaceEngine(libPath);
//激活引擎
errorCode = faceEngine.activeOnline(appId, sdkKey);
if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
System.out.println("引擎激活失败");
}
ActiveFileInfo activeFileInfo = new ActiveFileInfo();
errorCode = faceEngine.getActiveFileInfo(activeFileInfo);
if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
System.out.println("获取激活文件信息失败");
}
//引擎配置
EngineConfiguration engineConfiguration = new EngineConfiguration();
engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
engineConfiguration.setDetectFaceMaxNum(10);
engineConfiguration.setDetectFaceScaleVal(16);
//功能配置
FunctionConfiguration functionConfiguration = new FunctionConfiguration();
functionConfiguration.setSupportFaceDetect(true);
functionConfiguration.setSupportFaceRecognition(true);
functionConfiguration.setSupportLiveness(true);
engineConfiguration.setFunctionConfiguration(functionConfiguration);
//初始化引擎
errorCode = faceEngine.init(engineConfiguration);
if (errorCode != ErrorInfo.MOK.getValue()) {
System.out.println("初始化引擎失败");
}else{
System.out.println("初始化引擎成功");
}
}

/**
* @param: imgPath
* @description: 解码
* @return: byte[]
* @date: 2020/4/24
*/
public static byte[] baseData(String imgPath){
BASE64Decoder decoder = new BASE64Decoder();
byte[] bytes = new byte[0];
try {
bytes = decoder.decodeBuffer(imgPath);
} catch (IOException e) {
e.printStackTrace();
}
return bytes;
}
/**
* @param: imgPath
* @description: 图像流人脸检测
* @return: void
* @date: 2020/4/24
*/
public static void imageInfoFlow(String imgPath){
byte[] bytes = baseData(imgPath);
imageInfo = getRGBData(bytes);
errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
}

/**
* @param: imgPath
* @description: 图片人脸检测
* @return: void
* @date: 2020/4/24
*/
public static void imageInfo(String imgPath){
imageInfo = getRGBData(new File("F:\\IDEA\\workspace\\wanjia\\src\\main\\webapp\\upload\\faceimg\\"+imgPath));;
errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
}

/**
* @param:
* @description: 活体检测
* @return: int
* @date: 2020/4/24
*/
public static int liveness(){
//设置活体测试
errorCode = faceEngine.setLivenessParam(0.5f, 0.7f);
//人脸属性检测
FunctionConfiguration configuration = new FunctionConfiguration();
configuration.setSupportLiveness(true);
errorCode = faceEngine.process(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList, configuration);
//活体检测
List<LivenessInfo> livenessInfoList = new ArrayList<LivenessInfo>();
errorCode = faceEngine.getLiveness(livenessInfoList);
int liveness = livenessInfoList.get(0).getLiveness();
System.out.println("活体:" + liveness);
return liveness;
}

/**
* @param: imgPath
* @description: 检测是否存在人脸
* @return: boolean
* @date: 2020/4/24
*/
public static boolean findFace(String imgPath){
/*initEngine();*/
imageInfoFlow(imgPath);
int isFace = 0;
if(faceInfoList!=null && faceInfoList.size()>0){
isFace = 1;
int liveness = liveness();
if(liveness == 1){
isFace = 2;
}
}
/*errorCode = faceEngine.unInit();*/
return isFace;
}

/**
* @param: imgPath
* @param: userList
* @description: 人脸比对
* @return: com.wanjia.domain.User
* @date: 2020/4/24
*/
public static User faces(String imgPath , List<User> userList){
/*initEngine();*/
imageInfoFlow(imgPath);
//特征提取
FaceFeature faceFeature = new FaceFeature();
errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature);
System.out.println("特征值大小:" + faceFeature.getFeatureData().length);
float score = 0;
for (User user : userList) {
if(user.getFaceImg() == null){
continue;
}
imageInfo(user.getFaceImg());
//特征提取2
FaceFeature faceFeature2 = new FaceFeature();
if(faceInfoList!=null && faceInfoList.size()>0){
errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature2);
}else{
continue;
}
System.out.println("特征值大小:" + faceFeature2.getFeatureData().length);
//特征比对
FaceFeature targetFaceFeature = new FaceFeature();
targetFaceFeature.setFeatureData(faceFeature.getFeatureData());
FaceFeature sourceFaceFeature = new FaceFeature();
sourceFaceFeature.setFeatureData(faceFeature2.getFeatureData());
FaceSimilar faceSimilar = new FaceSimilar();

errorCode = faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar);
score = faceSimilar.getScore();
if(score > 0.75f){
System.out.println("相似度:" + score);
/*errorCode = faceEngine.unInit();*/
return user;
}else {
System.out.println("相似度:" + score);
}
}
//引擎卸载
/*errorCode = faceEngine.unInit();*/
return null;
}
@PreDestroy
public void unInit(){
errorCode = faceEngine.unInit();
System.out.println("引擎卸载成功");
}
}

2.4 前端界面展示

userAddFace.jsp:面部信息录入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>面部信息录入</title>
<script src="${pageContext.request.contextPath}/layui/jquery-3.2.1.js"></script>
<link rel="stylesheet"
href="${pageContext.request.contextPath}/layui/css/layui.css">
<script src="${pageContext.request.contextPath}/layui/layui.js"></script>
</head>
<body style="padding: 25px; font-size: 20px;">
<center>
<div class="layui-row layui-col-space10">
<label class="layui-form-label" style="width: 150px;">登录密码:</label>
<input type="password" class="layui-input" id="loginPwd" lay-verify="required" style="width: 200px;">
<video id="video" style="width: 500px;height: 380px;"></video>
<canvas id="canvas" width="500" height="380" style="display: none;"></canvas>
<div class="layui-col-md12" >
<input type="button" class="layui-btn layui-btn-fluid layui-btn-radius" onclick="faceLogin()" value="录入面部信息">
</div>
</div>
</center>
</body>
<script type="text/javascript">
var video = document.getElementById('video');
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var mediaStreamTrack=null;
if (navigator.mediaDevices.getUserMedia) {
//最新的标准API
navigator.mediaDevices.getUserMedia({video : {width: 1000, height: 1000}}).then(success).catch(error);
} else if (navigator.webkitGetUserMedia) {
//webkit核心浏览器
navigator.webkitGetUserMedia({video : {width: 1000, height: 1000}},success, error)
} else if (navigator.mozGetUserMedia) {
//firfox浏览器
navigator.mozGetUserMedia({video : {width: 1000, height: 1000}}, success, error);
} else if (navigator.getUserMedia) {
//旧版API
navigator.getUserMedia({video : {width: 1000, height: 1000}}, success, error);
}

function success(stream) {
//兼容webkit核心浏览器
// let CompatibleURL = window.URL || window.webkitURL;

//将视频流设置为video元素的源
console.log(stream);

//video.src = CompatibleURL.createObjectURL(stream);
video.srcObject = stream;
video.play();
}
//失败回调
function error(error) {
console.log("访问用户媒体设备失败");
}
//开启摄像头
if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia) {
getUserMedia({video:{width:500,height:500}},success,error)
}else{
alert('你的浏览器不支持访问用户媒体设备');
}

function getFace() {
context.drawImage(video,0,0,500,380);
this.img=canvas.toDataURL('image/jpg');
//获取完整的base64编码
this.img=img.split(',')[1];
return this.img;
}
function offUserMedia() {
if(mediaStreamTrack!=null)
mediaStreamTrack.getTracks()[0].stop();
}
function faceLogin() {
layui.use('layer', function() {
var layer = layui.layer;//加载layer模块
var imgpath = getFace();
var userId = '${user.userId}';
var loginPwd = $("#loginPwd").val();
$.ajax({
data : {
"userId":userId,
"loginPwd":loginPwd,
"faceImg":imgpath
},
type : "post",
dataType : 'json',
url : "${pageContext.request.contextPath}/userAction_addFace",
success : function(data) {
if (data.code == 200) {
layer.msg("面部信息录入成功",{icon:1,time:1000},function(){
window.parent.location.reload();
});
}else if(data.code==100){
layer.msg("登录密码输入错误",{icon:2,time:1000},function(){
$("#loginPwd").val("");
});
}else if(data.code==400) {
layer.msg("未识别到人脸",{icon:2,time:1000});
}else if(data.code==300) {
layer.msg("活体检测未通过",{icon:2,time:1000});
}else {
layer.msg("面部信息录入失败",{icon:2,time:1000});
}
}
});
});
}
</script>
</html>

faceLogin.jsp:刷脸登录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>万家登录</title>
<script src="${pageContext.request.contextPath}/layui/jquery-3.2.1.js"></script>
<link rel="stylesheet"
href="${pageContext.request.contextPath}/layui/css/layui.css">
<script src="${pageContext.request.contextPath}/layui/layui.js"></script>
<style type='text/css'>
#code {
font-family: Arial, 宋体;
font-style: italic;
color: green;
border: 0;
padding: 2px 3px;
letter-spacing: 3px;
font-weight: bolder;
font-size: 25px;
}
</style>
</head>
<body style="text-align: center">
<!--------------------------导航栏---------------------------->
<ul class="layui-nav layui-bg-cyan">
<li class="layui-nav-item"><a href="javascript:;" style="font-size: 30px;font-weight: bold; font-family:楷体;">万家</a></li>
<li class="layui-nav-item"><a href="${pageContext.request.contextPath}/page_indexUI">首页</a></li>
<li class="layui-nav-item"><a href="${pageContext.request.contextPath}/userUI_login">密码登录</a></li>
<li class="layui-nav-item layui-this"><a href="${pageContext.request.contextPath}/userUI_faceLogin">刷脸登录</a></li>
<li class="layui-nav-item"><a href="${pageContext.request.contextPath}/userUI_register">注册</a></li>
<li class="layui-nav-item"><i
class="layui-icon layui-icon-cellphone"
style="color: #FFFFFF; margin-left: 100px;"></i>咨询电话:029-88888888</li>
</ul>
<!--------------------------轮播图---------------------------->
<div class="layui-carousel" id="test1" style="z-index: -1;">
<div carousel-item>
<div>
<img src="img/1.jpg">
</div>
<div>
<img src="img/2.jpg">
</div>
<div>
<img src="img/3.jpg">
</div>
<div>
<img src="img/4.jpg">
</div>
</div>
</div>

<!--------------------------登录框---------------------------->
<div class="layui-row layui-col-space30" style="margin-top: -600px;">
<!-- 占4格,往右移动4格(等于在中间),背景色灰色 -->
<div
class="layui-col-md4 layui-col-md-offset4 layui-bg-gray layui-anim layui-anim-scale">
<!-- 标题占12格 -->
<div class="layui-row">
<div class="layui-col-md12">
<h1>
<i class="layui-icon layui-icon-release"
style="font-size: 40px; color: #2F4056; margin-right: 10px;"></i>万家
LoginPage
</h1>
</div>
</div>
<!-- 两个占12格表单 -->
<div class="layui-row layui-col-space10">
<div class="layui-col-md12">
<video id="video" class="layui-col-md12"></video>
<canvas id="canvas" width="514" height="370" style="display: none;"></canvas>
</div>
<div class="layui-col-md12" >
<input type="button" class="layui-btn layui-btn-fluid layui-btn-radius" onclick="faceLogin()" value="登录">
</div>

</div>
</div>
</div>
<!--------------------------底部---------------------------->
<div class="layui-container"
style="background-color: #FFFFFF; margin-top: 150px;">
<span class="layui-breadcrumb" lay-separator="|"> <a
href="javascript:;">© 万家 租房</a> <a href="javascript:;">娱乐</a> <a
href="javascript:;">八卦</a> <a href="javascript:;">体育</a> <a
href="javascript:;">搞笑</a> <a href="javascript:;">视频</a> <a
href="javascript:;">游戏</a> <a href="javascript:;">综艺</a>
</span>
</div>

<script>
//注意:导航 依赖 element 模块,否则无法进行功能性操作
layui.use('element', function() {
var element = layui.element;
});

layui.use('carousel', function() {
var carousel = layui.carousel;
//建造实例
carousel.render({
elem : '#test1',
width : '100%',
height : '700px',
anim : 'fade',
indicator : 'none',
arrow : 'none'
});
});
var video = document.getElementById('video');
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var mediaStreamTrack=null;
if (navigator.mediaDevices.getUserMedia) {
//最新的标准API
navigator.mediaDevices.getUserMedia({video : {width: 1000, height: 1000}}).then(success).catch(error);
} else if (navigator.webkitGetUserMedia) {
//webkit核心浏览器
navigator.webkitGetUserMedia({video : {width: 1000, height: 1000}},success, error)
} else if (navigator.mozGetUserMedia) {
//firfox浏览器
navigator.mozGetUserMedia({video : {width: 1000, height: 1000}}, success, error);
} else if (navigator.getUserMedia) {
//旧版API
navigator.getUserMedia({video : {width: 1000, height: 1000}}, success, error);
}

function success(stream) {
//兼容webkit核心浏览器
// let CompatibleURL = window.URL || window.webkitURL;

//将视频流设置为video元素的源
console.log(stream);

//video.src = CompatibleURL.createObjectURL(stream);
video.srcObject = stream;
video.play();
}
//失败回调
function error(error) {
console.log("访问用户媒体设备失败");
}
//开启摄像头
if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia) {
getUserMedia({video:{width:500,height:500}},success,error)
}else{
alert('你的浏览器不支持访问用户媒体设备');
}

function getFace() {
context.drawImage(video,0,0,514,370);
this.img=canvas.toDataURL('image/jpg')
//获取完整的base64编码
this.img=img.split(',')[1];
return this.img;
}
function offUserMedia() {
if(mediaStreamTrack!=null)
mediaStreamTrack.getTracks()[0].stop();
}
function faceLogin() {
layui.use('layer', function() {
var layer = layui.layer;//加载layer模块
var imgpath = getFace();
$.ajax({
data : {
"faceImg":imgpath
},
type : "post",
dataType : 'json',
url : "${pageContext.request.contextPath}/userAction_jsonLogin",
success : function(data) {
if (data.code == 200) {
if (data.type == 3) {
layer.msg("欢迎您管理员"+data.data.loginName,{icon:1,time:1000},function(){
window.location.href="${pageContext.request.contextPath}/page_adminUI";
});
}else if(data.type == 2){
layer.msg("欢迎您房主"+data.data.loginName,{icon:1,time:1000},function(){
if(data.info == 100){
layer.msg("有租户房屋已到期,请及时处理",{icon:1,time:1000},function (){
window.location.href="${pageContext.request.contextPath}/page_admin";
});
}else{
window.location.href="${pageContext.request.contextPath}/page_admin";
}
});
}else{
layer.msg("欢迎您租户"+data.data.loginName,{icon:1,time:1000},function(){
if(data.info == 100){
layer.msg("您有房屋已到期,请及时处理",{icon:1,time:1000},function(){
window.location.href="${pageContext.request.contextPath}/page_indexUI";
});
}else{
window.location.href="${pageContext.request.contextPath}/page_indexUI";
}
});
}
} else if(data.code == 400) {
layer.msg("未检测到人脸",{icon:2,time:1000});
} else if(data.code == 300) {
layer.msg("活体检测未通过",{icon:2,time:1000});
} else {
layer.msg("刷脸登录失败:面部识别不匹配",{icon:2,time:1000});
}
}
});
</script>
</body>
</html>

前端界面展示的js和css下载:LayUI

2.5 测试

面部信息录入界面展示:

登录界面展示:

到此,人脸识别整合系统登录完成。

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×