本次的博客是自己软件工程课设的作业,写博客是为了记录自己的学习过程,然后总结,同时可以给需要的人作参考。

1、在做这个项目的时候,也是个大三学生,所以懂得并不多,因此在网上看见了一些相关的资源,但是都不是很清醒比较混乱,因此做完这个项目就想发表下自己的意见,以帮助需要的人(这里我们可以用数据库,也可以不用数据库,因为我做的这个项目并不是仅仅一个人脸识别,还有其他的业务,所以我用到了数据库,如果仅仅想弄个人脸注册登录的业务,可以不需要数据库)

让我们进入正题吧:

一、Web端人脸识别主要有三个技术思路:

1.前端的人脸识别,例如使用Tensorflow.js,2.后台人脸识别,有很多开源或者免费的SDK可以使用3.前后端结合,即结合以上两种方法,虽然系统复杂度提高,但对于系统的安全性,以及减轻服务器负担都有很大提升。

(本次的实验是调用百度云的Api以及前后端结合的方式去实现人脸注册以及登录的功能)

让我们先看下效果图吧:

1、登录的首页:
2、注册页面,因为我们想要人脸登录,首先要注册你自己的人脸保存百度云脸库中去

3、人脸识别登录

在这个登录页面我们要好好讲一讲,因为在做这个项目的时候,自己花了很多时间。
1、首先我们要明白,我这个前端页面调用电脑摄像头是自动截取图片的每1秒截取一张,所以不用我们点击确认登录(这里我们也没有这个按钮),它把我们的图片以base64字节码的形式采用异步Ajax的形式传到后台。
··

4、遇到错误上后台查找原因(遇到最多的就是你的脸不在摄像头的正中间,也就是有效范围)

二、因为在百度云上申请自己的账号(免费),注册自己的人脸库

1、我的百度云人脸库

2、如何创建人脸库(刚开始你们自己肯定没有所以需要创建,创建成功会给你一个API key 及Secret Key,这回头我们在程序中调用人脸库,这个就是地址)

3、连接百度云人脸库,无论是人脸检测、人脸搜索、人脸对比,身份验证、都需要首先获取access_token(这个类百度云Api文档里面都有,我知道大家懒,所以直接复制在这里面了)

package com.baidu.ai.aip.auth;import org.json.JSONObject;import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;/*** 获取token类*/
public class AuthService {/*** 获取权限token* @return 返回示例:* {* "access_token": "24.460da4889caad24cccdb1fea17221975.2592000.1491995545.282335-1234567",* "expires_in": 2592000* }*/public static String getAuth() {// 官网获取的 API Key 更新为你注册的String clientId = "百度云应用的AK";// 官网获取的 Secret Key 更新为你注册的String clientSecret = "百度云应用的SK";return getAuth(clientId, clientSecret);}/*** 获取API访问token* 该token有一定的有效期,需要自行管理,当失效时需重新获取.* @param ak - 百度云官网获取的 API Key* @param sk - 百度云官网获取的 Securet Key* @return assess_token 示例:* "24.460da4889caad24cccdb1fea17221975.2592000.1491995545.282335-1234567"*/public static String getAuth(String ak, String sk) {// 获取token地址String authHost = "https://aip.baidubce.com/oauth/2.0/token?";String getAccessTokenUrl = authHost// 1. grant_type为固定参数+ "grant_type=client_credentials"// 2. 官网获取的 API Key+ "&client_id=" + ak// 3. 官网获取的 Secret Key+ "&client_secret=" + sk;try {URL realUrl = new URL(getAccessTokenUrl);// 打开和URL之间的连接HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();connection.setRequestMethod("GET");connection.connect();// 获取所有响应头字段Map<String, List<String>> map = connection.getHeaderFields();// 遍历所有的响应头字段for (String key : map.keySet()) {System.err.println(key + "--->" + map.get(key));}// 定义 BufferedReader输入流来读取URL的响应BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));String result = "";String line;while ((line = in.readLine()) != null) {result += line;}/*** 返回结果示例*/System.err.println("result:" + result);JSONObject jsonObject = new JSONObject(result);String access_token = jsonObject.getString("access_token");return access_token;} catch (Exception e) {System.err.printf("获取token失败!");e.printStackTrace(System.err);}return null;}}
在这里也很容易出错,我就在获取**access_token** 中吃了亏,如果获取不到,则控制台上面不会有 access_token的字符串,如果成功获取access_token的字符串,就会默认在控制台下打印,
  • 正常的access_token的样子:

三、前端如何获取我们的摄像头(在这里我花了很多时间,因为自己做的是后端开发,前端还没能力写出【有能力的同学Pass这句话!!】,只能翻阅大量资料,但是网上都是不足的,我在这里将给大家一个完整的前端Jsp代码)

3.1、注册的页面(注册页面大家可以自己写其实就是文件上传,我自己这个业务比较复杂)

<%--Document   : indexCreated on : 2020-5-10, 9:49:31Author     : Administrator
--%><%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="zh-cn">
<head><title>欢迎使用</title><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="stylesheet" href="css/pintuer.css"><script src="js/jquery.js"></script><script src="js/pintuer.js"></script>
</head>
<body>
<!--头部开始-->
<%--        <%@include file="WEB-INF/jspf/header.jspf" %>--%>
<!--头部结束--><!--内容开始-->
<div class="container padding-big-top padding-big-bottom"><div class="line-big"><div class="xl12 xs3 xm3 xb7"><form method="post" action="/faceinsert" enctype="multipart/form-data"><div class="form-group"><div class="label"><label for="yno">用户编号</label></div><div class="field"><input type="text" class="input" id="sno" name="yno" size="50" placeholder="用户编号" value="${yonghu.yno}" data-validate="required:必填" /></div></div><div class="form-group"><div class="label"><label for="username">用户名</label></div><div class="field"><input type="text" class="input" id="snmae" name="username" size="50" placeholder="用户名" value="${yonghu.username}" data-validate="required:必填"/></div></div><div class="form-group"><div class="label"><label for="userloginname">用户登录名</label></div><div class="field"><input type="text" class="input" id="ssex" name="userloginname" size="50" placeholder="用户登录名"  value="${yonghu.userloginname}"/></div></div><div class="form-group"><div class="label"><label for="password">密码</label></div><div class="field"><input type="text" class="input" id="ssex" name="password" size="50" placeholder="密码"  value="${yonghu.userloginname}"/></div></div><div class="form-group"><div class="label"><label for="apassword">确认密码</label></div><div class="field"><input type="text" class="input" id="ssex" name="apassword" size="50" placeholder="确认密码"  value="${yonghu.userloginname}"/></div></div><div class="form-group"><div class="label"><label for="name">姓名</label></div><div class="field"><input type="text" class="input" id="sage" name="name" size="50" placeholder="姓名"  value="${yonghu.name}" data-validate="required:必填"/></div></div><div class="form-group"><div class="label"><label for="sex">性别</label></div><div class="field"><input type="text" class="input" id="sdept" name="sex" size="50" placeholder="性别" value="${yonghu.sex}" data-validate="required:必填"/></div></div><div class="form-group"><div class="label"><label for="username">电话</label></div><div class="field"><input type="text" class="input" id="phone" name="tel" size="50" placeholder="电话"  value="${yonghu.tel}" data-validate="required:必填"/></div></div><div class="form-group"><div class="label"><label for="username">邮箱</label></div><div class="field"><input type="text" class="input" id="phone" name="email" size="50" placeholder="电话"  value="${yonghu.email}" data-validate="required:必填"/></div></div><%--                <div>  <!--验证码-->--%>
<%--                    <input  type="text" name="checkCode"/>--%><%--                    <img alt="验证码" id="imagecode" src="/ImageServlet"/>--%>
<%--                    <a href="javascript:void(0)" οnclick="myReload()">看不清楚</a><br>--%><%--                    <script type="text/javascript">--%>
<%--                        function myReload()--%>
<%--                        {--%><%--                            document.getElementById("imagecode").src ="/ImageServlet?"+Math.random();--%>
<%--                        }--%>
<%--                    </script>--%>
<%--                </div>--%><p style="color: red">${err}</p><div><input placeholder="请选择头像" type="file" name="image"/></div><div class="form-button"><button class="button" type="submit">提交</button></div></form></div><div class="xl12 xs9 xm9 xb5 padding-small-top"><img src="data:images/1.jpg" alt="学生信息管理系统" width="500px" height="350px"/></div></div>
</div>
<!--内容结束--><!--尾部开始-->
<%--        <%@include file="WEB-INF/jspf/footer.jspf" %>--%>
<!--尾部结束-->
</body>
</html>

3.2获取getface.Js的代码

$(function () {let mediaStreamTrack = null;openMedia();setTimeout("tishi()", "1000");  <!---缓存1000毫秒-->setTimeout("tishi2()", "3000");setTimeout("takePhoto()", "5000");})
var number = 0;function tishi() {$("#flag").html("正在打开摄像头")
}function tishi2() {$("#flag").html("请正视摄像头")
}function tishi3() {window.location.href = "login.jsp";
}function openMedia() {let constraints = {video: {width: 500, height: 500},audio: false};//获得video摄像头let video = document.getElementById('video');let promise = navigator.mediaDevices.getUserMedia(constraints);promise.then((mediaStream) => {mediaStreamTrack = typeof mediaStream.stop === 'function' ? mediaStream : mediaStream.getTracks()[1];video.srcObject = mediaStream;video.play();});
}// 拍照
function takePhoto() {//获得Canvas对象number++;let video = document.getElementById('video');let canvas = document.getElementById('canvas');let ctx = canvas.getContext('2d');ctx.drawImage(video, 0, 0, 500, 500);// toDataURL  ---  可传入'image/png'---默认, 'image/jpeg'let img = document.getElementById('canvas').toDataURL();// 这里的img就是得到的图片console.log('img-----', img);document.getElementById('imgTag').src = img;$("#flag").html("正在识别");$.ajax({url: "/faceloginServlet",    //请求的url地址dataType: "text",   //返回格式为jsonasync: true,//请求是否异步,默认为异步,这也是ajax重要特性// contentType:"application/json",data: {"imagebast64": img}, //参数值type: "POST", //请求方式success: function (data) {//     if(data=="fail"||data.score.substr(0,2)<80){//         $("#flag").html("识别失败,请保持人像处于框内 2秒后重新识别");//         if(number<3){//             setTimeout("takePhoto()","3000");//         }else {//             $("#flag").html("识别失败请使用账号密码登录 三秒后回到主页");//             setTimeout("tishi3()","3000");//         }//     }//     if(data.score.substr(0,2)>80){//         window.location.href="/display"//     }////////// }alert(data);var scoreMatch = data.split(".")[0];if (scoreMatch > 72) {console.log("cheng---gong");window.location.href = "/display";} else {window.location.href = "login.jsp";}}})}// 关闭摄像头
function closeMedia() {mediaStreamTrack.stop();
}

3.3 facelogin.jsp文件

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %>
<!doctype html>
<html lang="zh">
<head><title>js调用摄像头拍照上传图片</title><meta charset="utf-8">
</head>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/Getface.js"></script>
<style>.getface{position: absolute;top: 20%;left: 35%;}.tishi{font-size: 20px;}
</style>
<body>
<div align="center"><p id="flag" class="tishi"></p>
</div>
<div class="getface"><video id="video" width="400px" height="400px" autoplay="autoplay"></video><canvas id="canvas" width="400px" height="400px" style="display: none;"></canvas><img id="imgTag" src="" alt="imgTag" style="display: none;">
</div>
</body>

ok!!!,按照上面的原封不动你就已经把前端的代码搭建好了

四、百度云人脸技术有好几项技术,这里我们的项目只用到了人脸搜索和人脸库管理中(人脸注册)这两个技术就够了(如果对人脸对比,和人脸检测有兴趣,可以自己观看文档)

4.1、在后端的开发中我们首先要在百度云人脸识别的文档中下载几个类,这是给你准备好的直接在地址栏复制就可下载

/**
* 重要提示代码中所需工具类
* FileUtil,Base64Util,HttpUtil,GsonUtils请从
* https://ai.baidu.com/file/658A35ABAB2D404FBF903F64D47C1F72
* https://ai.baidu.com/file/C8D81F3301E24D2892968F09AE1AD6E2
* https://ai.baidu.com/file/544D677F5D4E4F17B4122FBD60DB82B3
* https://ai.baidu.com/file/470B3ACCA3FE43788B5A963BF0B625F3
* 下载
*/

我们来解释下这几个类是干什么用的:
1、FileUtil:这个类是帮助我们读取前端传来登录头像的数据,作为字符串返回
2、Base64Util:这个类辅助上面的一个类,帮我们解析传过来的数据(我们知道前端我们使用Base64字节码传的,所以就必须用BaseUtil这个工具类去解析)
3、HttpUtil:这个类让我们可以在程序中,就可以请求百度云的Ip,感觉很牛皮,至今不知道为什么,知道的欢迎在评论告诉我
4.这个学过Json数据格式的都知道,这个是处理Json与字符串之间转换的工具类

4.2、前期的准备工作已经做好,让我们写后端代码吧
4.2.1、我们知道想要用人脸识别技术就首先注册自己的人脸到百度云人脸库中去


package com.baidu.ai.aip;import com.baidu.ai.aip.utils.HttpUtil;
import com.baidu.ai.aip.utils.GsonUtils;import java.util.*;/**
* 人脸注册
*/
public class FaceAdd {/*** 重要提示代码中所需工具类* FileUtil,Base64Util,HttpUtil,GsonUtils请从* https://ai.baidu.com/file/658A35ABAB2D404FBF903F64D47C1F72* https://ai.baidu.com/file/C8D81F3301E24D2892968F09AE1AD6E2* https://ai.baidu.com/file/544D677F5D4E4F17B4122FBD60DB82B3* https://ai.baidu.com/file/470B3ACCA3FE43788B5A963BF0B625F3* 下载*/public static String add() {// 请求urlString url = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/add";try {Map<String, Object> map = new HashMap<>();map.put("image", "027d8308a2ec665acb1bdf63e513bcb9");map.put("group_id", "group_repeat");map.put("user_id", "user1");map.put("user_info", "abc");map.put("liveness_control", "NORMAL");map.put("image_type", "FACE_TOKEN");map.put("quality_control", "LOW");String param = GsonUtils.toJson(map);// 注意这里仅为了简化编码每一次请求都去获取access_token,线上环境access_token有过期时间, 客户端可自行缓存,过期后重新获取。String accessToken = "[调用鉴权接口获取的token]";String result = HttpUtil.post(url, accessToken, "application/json", param);System.out.println(result);return result;} catch (Exception e) {e.printStackTrace();}return null;}public static void main(String[] args) {FaceAdd.add();}
}

这是官方给的代码,通过上面我自己的代码,我相信照这两个你们会搭建好自己的业务代码(这里可以根据前端实现图片上传功能,再将图片转base64数据上传到人脸库,这里group_id为注册人脸库用户组时自己设置的,以实现注册功能,)

4.2.2、然后我们就可以人脸登录,然后调用百度云人脸搜索的功能了,如何搜索到你目前登录的和你刚刚注册的一样,就会登录进去,否则失败


package utils;/*** @author Administrator**/import java.util.*;import entity.AuthService;
import utils.GsonUtils;
import utils.HttpUtil;/**
* 人脸搜索
*/
public class faceSearch {/*** 重要提示代码中所需工具类* FileUtil,Base64Util,HttpUtil,GsonUtils请从* https://ai.baidu.com/file/658A35ABAB2D404FBF903F64D47C1F72* https://ai.baidu.com/file/C8D81F3301E24D2892968F09AE1AD6E2* https://ai.baidu.com/file/544D677F5D4E4F17B4122FBD60DB82B3* https://ai.baidu.com/file/470B3ACCA3FE43788B5A963BF0B625F3* 下载*/public static String search(String image) {// 请求urlString url = "https://aip.baidubce.com/rest/2.0/face/v3/search";try {Map<String, Object> map = new HashMap<>();String substring = image.substring(image.indexOf(",")+1, image.length());map.put("image", substring); //图片base64数据map.put("liveness_control", "NONE");  //活体检测控制无map.put("group_id_list", "testFaceLogin");  //指定用户组group 人脸库总已经存在的用户组map.put("image_type", "BASE64");     //图片类型,这里转化过的base64map.put("quality_control", "LOW");   //图片质量控制String param = GsonUtils.toJson(map);AuthService auth = new AuthService();String accessToken = auth.getAuth();// 注意这里仅为了简化编码每一次请求都去获取access_token,线上环境access_token有过期时间, 客户端可自行缓存,过期后重新获取。String result = HttpUtil.post(url, accessToken, "application/json", param);String score = result.split(",")[9].split(":")[1];System.out.println(result);System.out.println(score);return score;} catch (Exception e) {e.printStackTrace();}return null;}}

上面的图片是我自己人脸登录的Servlet,结合下面官方给的,我相信你们就理解了人脸搜索功能的意思,通过人脸搜索类任何去匹配人脸库中最像的一个给出分数,然后把这个分数用输出流传递给前端,在前段设置个阀值(我设置的是75),如何大于75分说明在人脸库中找到了你目前登录人的信息,则给予通过,否则相反

这是刚刚Getface.js文件中的

到这我们所有的人脸识别工作就结束了,根据自己需要自行修改,可能需要某些jar包有啥问题了,如果实在找不到了可以私信我。

java web+前端实现 人脸登录功能(专注细节)相关推荐

  1. java web mysql 登陆_javaweb登录功能实现,eclipse开发工具,mysql作为数据库

    [实例简介] 简单的网页登录,表单的提交,servlet的处理,mysql数据库的链接 [实例截图] [核心代码] javaweb登录功能的实现 └── javaweb登录功能的实现 ├── mysq ...

  2. Java Web 实现 QQ第三方登录

    java web 实现QQ第三方登录功能 首先点击该链接进入腾讯开放平台 ,注册成为开发者 2.注册成功后到这个页面 3.创建web应用 4.填写基本信息(以前的这里会让你填写回调地址 ,现在改了) ...

  3. Java Web 前端高性能优化(二)

    2019独角兽企业重金招聘Python工程师标准>>> ######一.上文回顾 上回我们主要从图片的合并.压缩等方面介绍前端性能优化问题(详见Java Web 前端高性能优化(一) ...

  4. Java Web 前端高性能优化(二) 1

    一.上文回顾 上回我们主要从图片的合并.压缩等方面介绍前端性能优化问题(详见Java Web 前端高性能优化(一)) 本次我们主要从图像BASE64 编码.GZIP压缩.懒加载与预加载以及 OneAP ...

  5. java实现简单扫码登录功能(模仿微信网页版扫码)

    java实现简单扫码登录功能 模仿微信pc网页版扫码登录 使用js代码生成qrcode二维码减轻服务器压力 js循环请求服务端,判断是否qrcode被扫 二维码超时失效功能 二维码被扫成功登录,服务端 ...

  6. [转]你会做Web上的用户登录功能吗?

    Web上的用户登录功能应该是最基本的功能了,可是在我看过一些站点的用户登录功能后,我觉得很有必要写一篇文章教大家怎么来做用户登录功能.下面的文章告诉大家这个功能可能并没有你所想像的那么简单,这是一个关 ...

  7. php web裁剪图片上传,WEB前端实现裁剪上传图片功能

    最后的效果如下: 这里面有几个功能,第一个是支持拖拽,第二个压缩,第三个是裁剪编辑,第四个是上传和上传进度显示,下面依次介绍每个功能的实现: 1. 拖拽显示图片 拖拽读取的功能主要是要兼听html5的 ...

  8. 实现Web上的用户登录功能

    https://coolshell.cn/articles/5353.html Web上的用户登录功能应该是最基本的功能了,可是在我看过一些站点的用户登录功能后,我觉得很有必要写一篇文章教大家怎么来做 ...

  9. Web上的用户登录功能安全

    转载自:http://www.daimami.com/web/217218.htm 你会做Web上的用户登录功能吗? Web上的用户登录功能应该是最基本的功能了,可是在我看过一些站点的用户登录功能后, ...

最新文章

  1. Android Studio 引入aar文件
  2. 声明一个const数组
  3. 沃尔沃投资两家以色列科技创企 布局人工智能
  4. jQuary的相关动画效果
  5. 1982:【19CSPJ普及组】数字游戏 scratch C++
  6. linux运行c程序a. out,无法运行已编译的文件 – bash:./ a.out:权限被拒绝. (我试过chmod)...
  7. java读取日志_Java实时监控日志文件并输出的方法详解
  8. keepalived+mysql双主高可用配置
  9. Retrofit源码解析之请求流程概述
  10. html判断安装没安装qq,QQ提示安装路径无效您没有权限怎么办 QQ2015提示安装路径无效您没有权限的解决方法...
  11. QTP(Quick Test Professional)安装详细教程
  12. 自助建站平台实力比拼:凡科、微企点、建站之星、宝华建站、微魔方、上线了...
  13. PHP响应式营销型万能H5建站系统源码
  14. java手风琴代码_[Java教程]18款jquery抽屉式手风琴导航特效代码
  15. VB问题——ByRef参数类型不符
  16. 人工智能和人类智能的本质区别是什么(五)
  17. 图书馆信息管理系统文档
  18. MQ消息队列(三)RabbitMQ及Erlang安装过程中常见问题
  19. Docker知识点总结
  20. 跨境电商亚马逊卖家最需要关注的四个维度的数据

热门文章

  1. 用mask-rcnn训练自己的数据
  2. 数据仓库—stg层_数据产品-数据仓库分层建模
  3. 乱世识英雄 你选什么品牌的ERP
  4. bzoj 2121 字符串游戏
  5. 网页防篡改技术发展趋势
  6. python阶乘的代码_python编码阶乘
  7. 我的世界怎么在服务器中显示键位,我的世界神奇宝贝mod怎么玩 基本键位介绍...
  8. 【数据结构(C语言描述)】环形队列
  9. linux 卸载x264,问一些linux下x264编码的问题
  10. 兰伯特(Lambert)方程的求解算法3