百度人脸识别java html5
1、前端thymeleaf+h5
index.html 人脸识别+定位,用的百度sdk
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no"> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <link rel="shortcut icon" href="farvirate.ico" type="image/x-icon" /> <link type="text/css" rel="stylesheet" th:href="@{/static/html5/font-awesome-4.7.0/css/font-awesome.min.css}" /> <link type="text/css" rel="stylesheet" th:href="@{/static/html5/animate.min.css}" /> <link type="text/css" rel="stylesheet" th:href="@{/static/html5/home.css}" /> <link type="text/css" rel="stylesheet" th:href="@{/static/html5/swiper-3.4.2.min.css}" /> <script type="text/javascript" th:src="@{/static/easyui/jquery.min.js}"></script> <script type="text/javascript" th:src="@{/static/layer-3.1.1/layer/layer.js}"></script> <script type="text/javascript" th:src="@{/static/html5/swiper-3.4.2.jquery.min.js}"></script> <script type="text/javascript" src="https://api.map.baidu.com/api?v=2.0&ak=C93b5178d7a8ebdb830b9b557abce78b"></script> </head> <body> <canvas width="620px" id="canvas" height="720px" style="display: none;"></canvas> <input id="reg_id" type="hidden" th:value="${reg_id}" /> <div id="allmap" style="display:none;"></div> <div class="swiper-container swiper-no-swiping"> <div class="swiper-wrapper"> <div class="swiper-slide searchBox"> <div class="search"> <div class="sTop"> <h2> <span>在线</span>报到 </h2> </div> <i class="fa fa-search sIcon"></i> <!-- <input type="text" placeholder="请输入身份证号" /> --> <input id="idcard" name="idcard" type="text" placeholder="请输入身份证号" value=""> <button id="next" onclick="nextSwiper(1);"> <i class="fa fa-chevron-right"></i> </button> </div> </div> <div class="swiper-slide white"> <div class="infor"> <div class="header"></div> <div class="inforTop clearfix"> <div class="userImg"> <img id="admission_photo" th:src="@{/static/html5/images/djz.jpg}" /> </div> <div class="userInfor"> <h3> <i class="fa fa-vcard"></i><span id="name"></span><b id="gender"></b> </h3> <p class="clearfix"> <label>学号</label><span id="student_id"></span> </p> <p> <label>专业</label><span id="major_name"></span> </p> <p> <label>班级</label><span id="class_name"></span> </p> </div> </div> <div class="inforCon basic"> <h3> <span>基本信息</span> </h3> <table cellpadding="0" cellspacing="0" width="100%" class="inforTable"> <tr> <td>出生日期</td> <td><span id="date_birth"></span></td> <td>籍贯</td> <td><span id="hometown"></span></td> </tr> <tr> <td>身份证号</td> <td colspan="3"><span id="id_number"></span></td> </tr> <tr> <td>政治面貌</td> <td><span id="political_affiliation">团员</span></td> <td>民族</td> <td><span id="nation">汉族</span></td> </tr> <tr> <td>家庭地址</td> <td colspan="3"><span id="family_address"></span></td> </tr> </table> </div> </div> <button id="cameraBtn" class="check" onclick="">确认信息并进行身份验证</button> </div> <div class="swiper-slide"> <div class="topBg"> <div class="videoBox"> <!-- <video id="webcam" class="myVideo"></video> --> <video id="webcam" class="myVideo" autoplay playsinline></video> </div> <div class="borderBox"></div> <div class="fgBg"></div> </div> <div class="bottomBg girl"></div> <div id="demo"></div> <!-- <button class="check" onclick="getCurLocation()">开始验证</button> --> <button class="check" onclick="getFaceImg();">开始验证</button> </div> </div> <!-- 遮罩层DIV --> <div id="overlay" class="overlay"></div> <!-- Loading提示 DIV --> <div id="loadingTip" class="loading-tip"> <img th:src="@{/static/html5/images/loading.gif}" /> </div> </div> <script type="text/javascript"> var studentInfo; var index; var pos; var basePath = '[[${#httpServletRequest.getScheme() + "://" + #httpServletRequest.getServerName() + ":" + #httpServletRequest.getServerPort() + #httpServletRequest.getContextPath()}]]'; var regEx = /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/; var swiper = new Swiper('.swiper-container', { simulateTouch : false, onSlideChangeStart: function(swiper){ var currentIndex = swiper.clickedIndex var activeIndex = swiper.activeIndex; if(currentIndex==0 && activeIndex==1){//第一页,滑动到第二页,校验身份证号码 var result = checkIdCard(); if(!result){ layer.msg("请输入正确的身份证号码"); //alert("请输入正确的身份证号码"); return; }else{ nextSwiper(activeIndex); } } } }); const video = document.getElementById('webcam'); const button = document.getElementById('cameraBtn'); let currentStream; button.addEventListener('click', event => { nextSwiper(2); var constraints = { video: {'facingMode': "user"}, audio: false }; navigator.mediaDevices .getUserMedia(constraints) .then(stream => { currentStream = stream; video.srcObject = stream; return navigator.mediaDevices.enumerateDevices(); }) .catch(error => { console.error(error); }); }); function checkIdCard(){ var idcard = $('#idcard').val();//获取用户输入的身份证号码 var result = regEx.test(idcard); return result; } //填好身份证,点按钮或滑动,滑动到第二个页面 function nextSwiper(index) { //滑动前,获取第二个页面学生信息; if (index === 1) { var result = checkIdCard(); if(!result){ layer.msg("请输入正确的身份证号码"); //alert("请输入正确的身份证号码"); }else{ $.ajax({ url : basePath + '/h5/getStudentInfo', async : false, cache : false, data : { "idcard" : $('#idcard').val() }, error : function(result) {// 请求失败处理函数 layer.msg(result.msg); //alert(result.msg); }, success : function(result) { //请求成功后处理函数 debugger; studentInfo = result; swiper.slideTo(index); //将获取的学生信息赋值 if (result.admission_photo) { $('#admission_photo').attr("src",basePath + "/uploadImg/admission_photo/"+ result.admission_photo); } $('#name').html(result.name); $('#gender').text(result.gender); $('#student_id').html(result.student_id); $('#major_name').html(result.major_name); $('#class_name').html(result.class_name); //基本信息 $('#date_birth').html(result.date_birth); $('#hometown').html(result.hometown); $('#id_number').html(result.id_number); $('#political_affiliation').html(result.political_affiliation); $('#nation').html(result.nation); $('#family_address').html(result.family_address); } }) } } else if (index === 2) {//滑到 swiper.slideTo(index); startFace(); } } function startFace() { navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia; if (navigator.getUserMedia) { navigator.getUserMedia({ audio : false, video : { width : 400, height : 400, facingMode : "user" } }, function(stream) { debugger; var video = document.querySelector('video'); try { video.src = window.URL.createObjectURL(stream); } catch (e) { console.log(e); video.srcObject = stream; //注意,不同版本video.src和video.srcObject两种 } video.onloadedmetadata = function(e) { video.play(); }; }, function(err) { console.log("The following error occurred: " + err.name); }); } else { console.log("getUserMedia not supported"); } } //获取视频中人脸,转换成图片,发送后台请求,识别图片 function getFaceImg() { showLoading(); debugger; var video = document.querySelector('video'); var canvasObj = document.querySelector('canvas') var context1 = canvasObj.getContext('2d'); context1.fillStyle = "#000000"; context1.fillRect(0, 0, 300, 300); context1.drawImage(video, 0, 0, 300, 300); var url = canvasObj.toDataURL(); //toDataURL()获取的数据有images前缀,要split取后面一部分传给后台,后台直接用 var face = url.split(",")[1]; $('#idcard').val(studentInfo.id_number); $.ajax({ url: basePath+'/h5/checkFace', type:"POST", async: false, cache: false, data: {"face":face,"idcard":studentInfo.id_number}, success: function(data) { hideLoading(); debugger; var data = $.parseJSON(data); if(data.success){ registerFun(); }else{ var msg = data.msg; if('不是待报到学生'==msg){ //关闭当前人脸识别页面,避免人脸识别百度接口多次调用,产生多次费用 window.close(); }else{ layer.msg(msg); } } }, error:function(msg) { console.log(msg); } }); } //base64转换为Blob function dataURItoBlob(base64Data) { var byteString; if (base64Data.split(",")[0].indexOf("base64") >= 0) byteString = atob(base64Data.split(",")[1]); else byteString = unescape(base64Data.split(",")[1]); var mimeString = base64Data.split(",")[0].split(":")[1].split(";")[0]; var ia = new Uint8Array(byteString.length); for (var i = 0; i < byteString.length; i++) { ia[i] = byteString.charCodeAt(i); } return new Blob([ ia ], { type : mimeString }); } var geolocation = new BMap.Geolocation(); var gc = new BMap.Geocoder(); var map = new BMap.Map("allmap"); geolocation.getCurrentPosition(function(r) { if (this.getStatus() == BMAP_STATUS_SUCCESS) { var pt = r.point; gc.getLocation(pt, function(rs){ var address = rs.addressComponents; var mk = new BMap.Marker(r.point); map.addOverlay(mk); var latCurrent = r.point.lat; var lngCurrent = r.point.lng; var myPoint = new BMap.Point(lngCurrent, latCurrent); debugger; pos = { lat : latCurrent, lng : lngCurrent, nation : address.nation==undefined?null:address.nation, province : address.province==undefined?null:address.province, city : address.city==undefined?null:address.city, district : address.district==undefined?null:address.district, street : address.street==undefined?null:address.street, streetNumber : address.streetNumber==undefined?null:address.streetNumber, adcode : address.adcode==undefined?null:address.adcode, address : rs.address==undefined?null:rs.address, business : rs.business==undefined?null:rs.business, } }); } else { alert('failed' + this.getStatus()); } }, { enableHighAccuracy : true }) function registerFun(){ var data={}; data["reg_id"]=$('#reg_id').val(); data["complete"]="报到成功"; data["location"]=pos; data["step_id"]="4"; data["school_address"]=null; $.ajax({ url : basePath+'/h5/registe', method: "POST", dataType: "json", contentType: "application/json;charset=utf-8", async: false, data:JSON.stringify(data), error : function(result) {// 请求失败处理函数 alert(result.msg); }, success : function(result) { //请求成功后处理函数 debugger; if (result.success) { window.close(); layer.msg('报到成功', {icon: 1}); //sleep 1秒钟,再关闭,让用户能看到提示消息 var start = (new Date()).getTime(); while ((new Date()).getTime() - start < 1000) { continue; } window.close(); }else { layer.msg('报到失败', {icon: 1}); } } }) } /** * 显示遮罩层 */ function showOverlay() { // 遮罩层宽高分别为页面内容的宽高 $('.overlay').css({'height':$(document).height(),'width':$(document).width()}); $('.overlay').show(); } /** * 显示Loading提示 */ function showLoading() { // 先显示遮罩层 showOverlay(); // Loading提示窗口居中 $("#loadingTip").css('top', (getWindowInnerHeight() - $("#loadingTip").height()) / 2 + 'px'); $("#loadingTip").css('left', (getWindowInnerWidth() - $("#loadingTip").width()) / 2 + 'px'); $("#loadingTip").show(); $(document).scroll(function() { return false; }); } /** * 隐藏Loading提示 */ function hideLoading() { $('.overlay').hide(); $("#loadingTip").hide(); $(document).scroll(function() { return true; }); } //浏览器兼容 取得浏览器可视区高度 function getWindowInnerHeight() { var winHeight = window.innerHeight || (document.documentElement && document.documentElement.clientHeight) || (document.body && document.body.clientHeight); return winHeight; } // 浏览器兼容 取得浏览器可视区宽度 function getWindowInnerWidth() { var winWidth = window.innerWidth || (document.documentElement && document.documentElement.clientWidth) || (document.body && document.body.clientWidth); return winWidth; } </script> </body> </html>
后台Controller
@ResponseBody @RequestMapping(value = "/h5/checkFace", method = RequestMethod.POST) public Object checkFace(String face, String idcard) { try { //1.在线活体检测 boolean isLive = FaceUtil.faceverify(faceProperties.getAipFace(), face); if (isLive) {// 检测到是人脸,继续搜索是谁的脸 // 2.人脸搜索 org.json.JSONObject res = FaceUtil.search(faceProperties.getAipFace(), face); System.out.println(res.toString(2)); String msg = String.valueOf(res.get("error_msg")); if ("SUCCESS".equals(msg)) { //TODO 3.找到人脸,怕有误差,进一步判断身份证号码 /*JSONObject result = res.getJSONObject("result"); JSONArray users = result.getJSONArray("user_list"); Gson gson = new Gson(); UserInfo userInfo = gson.fromJson(users.get(0).toString(), UserInfo.class); System.out.println(userInfo); if(idcard.equals(userInfo.getIdcard())){ return renderSuccess("检测成功"); }else { return renderError("身份证号码不匹配"); }*/ return renderSuccess("检测成功"); } else { return renderError("没有搜索到匹配的人脸图像"); } } else { return renderError("没有检测到有效的人脸图像"); } } catch (JsonSyntaxException e) { e.printStackTrace(); return renderError("检测失败"); } catch (JSONException e) { e.printStackTrace(); return renderError("检测失败"); } }
人脸识别工具类:调用百度接口
public class FaceUtil { static BASE64Encoder encoder = new sun.misc.BASE64Encoder(); static BASE64Decoder decoder = new sun.misc.BASE64Decoder(); static String imageType = "BASE64"; /** * 图片路径编码成字符串 * @param image * @return */ public static String getImageBinary(String image) { File f = new File(image); try { BufferedImage bi = ImageIO.read(f); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(bi, "jpg", baos); byte[] bytes = baos.toByteArray(); return encoder.encodeBuffer(bytes).trim(); } catch (IOException e) { e.printStackTrace(); } return null; } /** * 查询所有组列表 * @param client * @return */ public static String getGroup(AipFace client) { // 传入可选参数调用接口 try { HashMap<String, String> options = new HashMap<String, String>(); options.put("start", "0"); options.put("length", "50"); // 组列表查询 JSONObject res = client.getGroupList(options); String msg = res.getString("error_msg"); if ("SUCCESS".equals(msg)) { JSONObject arr = res.getJSONObject("result"); JSONArray list = arr.getJSONArray("group_id_list"); String groupIdList = list.join(","); groupIdList = groupIdList.replace("\",\"", ","); groupIdList = groupIdList.replace("\"", ""); System.out.println("获取分组:"+groupIdList); return groupIdList; } return null; } catch (JSONException e) { e.printStackTrace(); return null; } } /** * 在线活体检测 * @param client * @param face * @return */ public static boolean faceverify(AipFace client,String face) { //在线活体检测 try { FaceVerifyRequest req = new FaceVerifyRequest(face,imageType); ArrayList<FaceVerifyRequest> list = new ArrayList<FaceVerifyRequest>(); list.add(req); JSONObject res = client.faceverify(list); String msg = String.valueOf(res.get("error_msg")); if("SUCCESS".equals(msg)) { return true; } return false; } catch (JSONException e) { e.printStackTrace(); return false; } } /** * 人脸搜索:在所有分组库中搜索,不存在,返回result为空,存在返回分数最高的排名max_user_num个用户信息 * @param client * @param face * @return */ public static JSONObject search(AipFace client,String face) { HashMap<String, String> options = new HashMap<String, String>(); options.put("max_face_num", "1"); options.put("match_threshold", "70"); options.put("quality_control", "NORMAL"); options.put("liveness_control", "LOW"); options.put("max_user_num", "1"); String groupIdList = getGroup(client); System.out.println("groupIdList:"+groupIdList); // 人脸搜索 try { JSONObject res = client.search(face, imageType, groupIdList, options); System.out.println(res.toString(2)); return res; } catch (JSONException e) { e.printStackTrace(); return null; } } }
要引入maven包:
<dependency> <groupId>com.baidu.aip</groupId> <artifactId>java-sdk</artifactId> <version>4.11.3</version> </dependency> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>20160810</version> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.5</version> </dependency>
swiper
simulateTouch : false 禁止滑动,只对PC有用,对移动端无效