基于百度AI的人像识别开发的登录模块
首先这是一个java的SSM框架的项目,没学过java或没接触过SSM的可能不太适合。数据库用的是mysql整体思路:使用HTML5的video和canvas来截取摄像头拍摄视频的图片base64数据,将拍摄的base64格式数据和之前在数据库中存好的人像数据上传到百度AI的处理中心,进行人像识别分析,并将结果回传,结果数据是json格式的,需要进行有效数据的提取,如果相似度达到90%,就判定..
·
首先这是一个java的SSM框架的项目,没学过java或没接触过SSM的可能不太适合。数据库用的是mysql
整体思路:使用HTML5的video和canvas来截取摄像头拍摄视频的图片base64数据,将拍摄的base64格式数据和之前在数据库中存好的人像数据上传到百度AI的处理中心,进行人像识别分析,并将结果回传,结果数据是json格式的,需要进行有效数据的提取,如果相似度达到90%,就判定为本人,登录验证通过。
数据库设计思路:数据表的结构很简单,一共有三个字段,id、data、username。但是有个问题,base64是非常长的一串数据,想想几万、几十万字符的数据直接存入数据库,是非常不明智的选择,当数据量稍微一多,会严重拖垮数据库的性能。所以正确操作可以将数据转成图片存到本地,数据库中只保存地址。但我作为演示操作,数据量小,就做了个错误的示范,我用longblob类型来保存的base64数据。
下面步入正题:
1.注册百度AI,进入控制台后,点击左侧导航菜单,进入人脸识别模块。
2.点击创建应用,然后添加你所要创建应用的一些信息,创建成功后会进入下图的界面
3.记住你的API key和Secret key,后面会用到。
4.下面开始写代码,首先创建Particleground.jsp,这是用来人像登录的页面,代码如下:
<%@ 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>
<title>管理员登录</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<link rel="stylesheet" type="text/css" href="source/css/style.css"/>
<script type="text/javascript" src="source/js/jquery.min.js"></script>
<script src="source/js/verificationNumbers.js"></script>
<script src="source/js/Particleground.js"></script>
<style type="text/css">
body {
height: 100%;
background: #213838;
overflow: hidden;
}
canvas {
z-index: -1;
position: absolute;
display: none;
}
h1 {
color: #fff;
text-align: center;
font-weight: 100;
margin-top: 40px;
}
#media {
width: 280px;
height: 250px;
margin: 10px auto 0;
border-radius: 30px;
overflow: hidden;
}
</style>
</head>
<body>
<div style="float:right;margin-right:80px;margin-top:40px;"><a href="login.jsp"><img src="source/images/return.png" alt=""></a></div>
<form action="" method="post" style="margin-top:100px;">
<dl class="admin_login">
<dt>
<strong>云通WMS</strong><strong style="margin-top:10px;">请将脸放摄像头前</strong>
</dt>
<div id="media">
<video id="video" width="530" height="300" autoplay></video>
<canvas id="canvas" width="400" height="300"></canvas>
</div>
<%--<dd style="margin-top:20px;" >--%>
<%--<input type="button" onclick="query()" value="立即登录"--%>
<%--class="submit_btn"/>--%>
<%--</dd>--%>
</dl>
</form>
<script type="text/javascript">
//var 是定义变量
var video = document.getElementById("video"); //获取video标签
var context = canvas.getContext("2d");
var con = {
audio: false,
video: {
width: 1980,
height: 1024,
}
};
//获取用户媒体对象
navigator.mediaDevices.getUserMedia(con).then(function (stream) {
video.src = window.URL.createObjectURL(stream);
video.onloadmetadate = function (e) {
video.play();
}
setTimeout(query,1000);
});
function query() {
//把流媒体数据画到convas画布上去
context.drawImage(video, 0, 0, 400, 300);
var baseData = getBase64();
$.ajax({
type: "post",
url: "faceRecognition.do",
async:true,
contentType:"application/x-www-form-urlencoded",
data: {"baseData": baseData},
dataType:'json',
success: function (data) {
var result = eval(data);
if (result) {
window.location.href="index.jsp";
} else {
alert("面容识别失败,请继续验证");
window.location.href="faceRecognition.jsp";
}
}
});
}
function getBase64() {
var imgSrc = document.getElementById("canvas").toDataURL(
"image/png");
return imgSrc.split("base64,")[1];
};
</script>
</body>
</html>
再创建faceEntry.jsp页面,这是用来进行人脸信息采集的页面,代码如下:
<%@ 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>
<title>人脸信息录入</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<link rel="stylesheet" type="text/css" href="source/css/style.css"/>
<script type="text/javascript" src="source/js/jquery.min.js"></script>
<script src="source/js/verificationNumbers.js"></script>
<script src="source/js/Particleground.js"></script>
<style type="text/css">
body {
height: 100%;
background: #213838;
overflow: hidden;
}
canvas {
z-index: -1;
position: absolute;
display: none;
}
h1 {
color: #fff;
text-align: center;
font-weight: 100;
margin-top: 40px;
}
#media {
width: 280px;
height: 250px;
margin: 10px auto 0;
border-radius: 30px;
overflow: hidden;
}
</style>
</head>
<body>
<div style="float:right;margin-right:80px;margin-top:40px;"><a href="login.jsp"><img src="source/images/return.png" alt=""></a></div>
<form action="" method="post" style="margin-top:100px;">
<dl class="admin_login">
<dt>
<strong>信息录入</strong><strong style="margin-top:10px;">请将脸放摄像头前</strong>
</dt>
<div id="media">
<video id="video" width="530" height="300" autoplay></video>
<canvas id="canvas" width="400" height="300"></canvas>
</div>
</dl>
</form>
<script type="text/javascript">
//var 是定义变量
var video = document.getElementById("video"); //获取video标签
var context = canvas.getContext("2d");
var con = {
audio: false,
video: {
width: 1980,
height: 1024,
}
};
//获取用户媒体对象
navigator.mediaDevices.getUserMedia(con)
.then(function (stream) {
video.src = window.URL.createObjectURL(stream);
video.onloadmetadate = function (e) {
video.play();
}
setTimeout(query,1000);
});
function query() {
//把流媒体数据画到convas画布上去
context.drawImage(video, 0, 0, 400, 300);
var baseData = getBase64();
$.ajax({
type: "post",
url: "faceEntry.do",
async:true,
contentType:"application/x-www-form-urlencoded",
data: {"faceData": baseData},
dataType:'json',
success: function (json, textStatus) {
var result = json.flag;
if (result==0) {
alert("您的人脸录入数据已达上限")
} else if(result==2){
alert("信息录入失败,请重新录入");
}else{
window.location.href="index.jsp";
}
}
});
}
function getBase64() {
var imgSrc = document.getElementById("canvas").toDataURL(
"image/png");
return imgSrc.split("base64,")[1];
};
</script>
</body>
</html>
上面JSP页面所依赖的css和js,我会上传到CSDN的资源下载中,在本文的最后会附上链接,我看看能不能设置成免费,尽量分低一点。
5.刚才让记住的两个KEY是为了获取token的,下面是获取token的一个工具类:
package com.hanpeng.utils;
import net.sf.json.JSONObject;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class GetToken {
public static String getToken() {
BufferedReader br = null;
StringBuffer sb = new StringBuffer();
String authHost = "https://aip.baidubce.com/oauth/2.0/token?";
String clientId = "PfaxdmuNuNyGhTcbtD2vkcuf";
String clientSecret = "dV7hZSmDWoNIIuBUNbtzC0XKmVy0v3tw";
String getAccessTokenUrl = authHost
+ "grant_type=client_credentials"
+ "&client_id=" + clientId
+ "&client_secret=" + clientSecret;
try {
URL url = new URL(getAccessTokenUrl);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setRequestMethod("POST");
connection.connect();
br = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String line = "";
while ((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
} catch (Exception e) {
e.printStackTrace();
}
JSONObject jsonObject = JSONObject.fromObject(sb.toString());
String token = jsonObject.getString("access_token");
return token;
}
}
6.下面是LoginController层
//百度人脸识别登录验证
@RequestMapping("faceRecognition")
void faceRecognition(HttpServletRequest request, HttpServletResponse response, String baseData) throws IOException {
System.out.println(baseData);
PrintWriter writer = response.getWriter();
HttpSession session = request.getSession();
boolean flag = false;
List<FaceRecognition> list = service.getBaseList();
for (FaceRecognition faceRecognition : list) {
String image2 = faceRecognition.getFace_base64();
if (service.getResult(baseData, image2)) {
flag = true;
session.setAttribute("username", faceRecognition.getUsername());
break;
}
}
writer.print(flag);
writer.close();
}
//百度人脸信息录入(返回的状态码:0:用户人脸数据存储已达上限,1:人脸信息录入成功, 2:人脸信息录入失败(照片不合格))
@RequestMapping("faceEntry")
public void faceEntry(HttpServletRequest request, HttpServletResponse response, String faceData) throws IOException {
HttpSession session = request.getSession();
String username = (String) session.getAttribute("username");
PrintWriter writer = response.getWriter();
//检测该用户下的人脸信息数据是否超过5条
if (service.queryCountByFaceInfo(username,5)) {
//进行人脸信息录入
if (service.getFaceResult(faceData)) {
writer.write("{\"flag\":\"1\"}");
FaceRecognition faceRecognition = new FaceRecognition(username, faceData);
service.insertFaceInfo(faceRecognition);
}else{
writer.write("{\"flag\":\"2\"}");
}
}else {
writer.write("{\"flag\":\"0\"}");
}
writer.close();
}
7.下面是LoginService接口类
public interface LoginService {
public List<Admin> Login(String username, String password);
public List<FaceRecognition> getBaseList();
public boolean getResult(String image1, String image2) throws IOException;
public boolean getFaceResult(String image) throws IOException;
public void insertFaceInfo(FaceRecognition faceRecognition);
public boolean queryCountByFaceInfo(String username, int n);
public List<Map<String, ?>> userInfo(String userName);
public void upDate(String date, String userName);
public void modifyPassWord(String userName, String passWord);
}
8.下面是LoginService类的实现类LoginServiceImpl类,我只挑了和人脸识别相关的方法:
//人脸识别检测
@Override
public boolean getResult(String image1, String image2) throws IOException {
boolean flag = false;
// 请求url
String url = "https://aip.baidubce.com/rest/2.0/face/v3/match";
try {
List<Map<String, Object>> images = new ArrayList<>();
Map<String, Object> map1 = new HashMap<>();
map1.put("image", image1);
map1.put("image_type", "BASE64");
map1.put("face_type", "LIVE");
map1.put("quality_control", "LOW");
map1.put("liveness_control", "NORMAL");
Map<String, Object> map2 = new HashMap<>();
map2.put("image", image2);
map2.put("image_type", "BASE64");
map2.put("face_type", "LIVE");
map2.put("quality_control", "LOW");
map2.put("liveness_control", "NORMAL");
images.add(map1);
images.add(map2);
String param = GsonUtils.toJson(images);
// 注意这里仅为了简化编码每一次请求都去获取access_token,线上环境access_token有过期时间, 客户端可自行缓存,过期后重新获取。
String accessToken = GetToken.getToken();
String result = HttpUtil.post(url, accessToken, "application/json", param);
System.out.println(result);
//用json提取result中的有效数据
JSONObject myJson = new JSONObject(result);
int error = myJson.getInt("error_code");
if (error == 0) {
JSONObject resultList = (JSONObject) myJson.get("result");
double score = resultList.getDouble("score");
System.out.println(score);
if (score >= 90) {
flag = true;
}
}
return flag;
} catch(Exception e){
e.printStackTrace();
}
return flag;
}
//人脸信息录入
@Override
public boolean getFaceResult(String image) throws IOException {
boolean flag = false;
// 请求url
String url = "https://aip.baidubce.com/rest/2.0/face/v3/detect";
try {
Map<String, Object> map = new HashMap<>();
map.put("image", image);
map.put("face_field", "faceshape,facetype");
map.put("image_type", "BASE64");
String param = GsonUtils.toJson(map);
String accessToken = GetToken.getToken();
String result = HttpUtil.post(url, accessToken, "application/json", param);
JSONObject myJson = new JSONObject(result);
int error = myJson.getInt("error_code");
if(error==0){
flag = true;
}
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
//新增人脸数据
@Override
public void insertFaceInfo(FaceRecognition faceRecognition) {
dao.insertFaceInfo(faceRecognition);
}
//检测该用户的人脸信息数据是否大于N
@Override
public boolean queryCountByFaceInfo(String username,int n) {
if(dao.queryCountByFaceInfo(username)<=4){
return true;
}
return false;
}
注意,上述代码引入了几个帮助类:Base64Util、FileUtil、GsonUtils、HttpUtil。这几个类都会在我上传到CSDN的资源下载中,在本文的最后会附上链接,我看看能不能设置成免费,尽量分低一点。
9.下面是LoginDao:
public interface LoginDao {
List<Admin> queryByNameAndPassword(@Param("username") String username, @Param("password") String password);
List<FaceRecognition> getBaseList();
void insertFaceInfo(FaceRecognition faceRecognition);
int queryCountByFaceInfo(@Param("username") String username);
List<Map<String, ?>> queryUserInfo(@Param("userName") String userName);
void upDate(@Param("date") String date, @Param("userName") String userName);
void modifyPassWord(@Param("userName") String userName, @Param("passWord") String passWord);
}
10.下面是mapping文件,loginDao.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd" >
<mapper namespace="com.hanpeng.dao.LoginDao">
<!-- 按照用户名和密码查询,返回用户id -->
<select id="queryByNameAndPassword" parameterType="String" resultType="com.hanpeng.bean.Admin">
select * from admin where admin_username=#{username} and admin_password=#{password}
</select>
<!--查询人脸识别本地库中的数据-->
<select id="getBaseList" resultType="com.hanpeng.bean.FaceRecognition">
select * from face_Recognition
</select>
<!--新增人脸数据-->
<insert id="insertFaceInfo" parameterType="com.hanpeng.bean.FaceRecognition">
insert into face_Recognition(face_base64,username) values(#{face_base64},#{username})
</insert>
<!--检测该用户的人脸信息数据是否大于N-->
<select id="queryCountByFaceInfo" parameterType="String" resultType="int">
select count(*) from face_Recognition where username=#{username}
</select>
<!-- 按照用户名查询用户信息,返回Map -->
<select id="queryUserInfo" parameterType="String" resultType="Map">
select * from user where username=#{userName}
</select>
<!-- 更新用户登录的时间 -->
<update id="upDate" parameterType="String">
update user set date=#{date} where username=#{userName}
</update>
<!-- 修改用户密码 -->
<update id="modifyPassWord" parameterType="String">
update user set password=#{passWord} where username=#{userName}
</update>
</mapper>
这是资源下载的地址:https://download.csdn.net/download/qq_33609401/10818905
以上就结束了,有什么相关的问题大家可以在下面留言,大家一起共同进步。
谢谢
更多推荐
已为社区贡献2条内容
所有评论(0)