• 基于百度AI+jquery-webcam+servlet实现人脸识别登录,兼容各主流浏览器


    1、注册百度AI账号,获取到AI开发资格

         详情参见个人博客:你的第一个人脸识别demo(http://www.cnblogs.com/guo-eric/p/8109411.html

    2、环境准备

    首先按照第一步说明将百度的AI类文件和用到的三方类文件下载到本地,需要的文件有:

         

    然后从jquery-webcam官网下载操作摄像头的插件:

    下载地址:https://www.xarg.org/project/jquery-webcam-plugin/

    下载后解压文件:

    最后将jquery的js文件引入,我这里用的是1.8.3:如上面截图所示

    3、前端页面开发:采用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>
    <meta charset="utf-8">
    <title>jQuery-webcam-master</title>
    <script src="js/jquery-1.8.3.min.js"></script>
    <script type="text/javascript" src="js/jquery.webcam.min.js"></script>
    <style type="text/css">
    #webcam {
        border: 1px solid #666666;
         320px;
        height: 240px;
    }
    
    #photos {
        border: 1px solid #666666;
         320px;
        height: 240px;
    }
    
    .btn {
         320px;
        height: auto;
        margin: 5px 0px;
    }
    
    .btn input[type=button] {
         150px;
        height: 50px;
        line-height: 50px;
        margin: 3px;
    }
    </style>
    
    </head>
    <body>
        <input type="text" id="uid" value="">
        <div id="webcam"></div>
    
        <div class="btn">
            <input type="button" value="注册" id="regBtn" onclick="action('reg');" /> 
            <input type="button" value="登录" id="saveBtn" onclick="action('login');" />
        </div>
    
        <div id="photos">
    
            <img src="" id="img">
    
        </div>
    </body>
    
    
    <script type="text/javascript">
        $(document).ready(function() {
            var pos = 0, ctx = null, saveCB, image = [];
            //创建画布指定宽度和高度
            var canvas = document.createElement("canvas");
            canvas.setAttribute('width', 320);
            canvas.setAttribute('height', 240);
            //如果画布成功创建
            if (canvas.toDataURL) {
                //设置画布为2d,未来可能支持3d
                ctx = canvas.getContext("2d");
                //截图320*240,即整个画布作为有效区(cutx?)
                image = ctx.getImageData(0, 0, 320, 240);
    
                saveCB = function(data) {
                    //把data切割为数组
                    var col = data.split(";");
                    var img = image;
                    //绘制图像(这里不是很理解算法)
                    //参数data  只是每行的数据  ,例如320*240 大小的照片,一张完整的照片下来需要240个data,每个data有320个rgb
                    for (var i = 0; i < 320; i++) {
                        //转换为十进制
                        var tmp = parseInt(col[i]);
                        img.data[pos + 0] = (tmp >> 16) & 0xff;
                        img.data[pos + 1] = (tmp >> 8) & 0xff;
                        img.data[pos + 2] = tmp & 0xff;
                        img.data[pos + 3] = 0xff;
                        pos += 4;
                    }
                    //当绘制320*240像素的图片时发给后端php
                    if (pos >= 4 * 320 * 240) {
                        //把图像放到画布上,输出为png格式
                        ctx.putImageData(img, 0, 0);
                        //alert('图片保存成功');
                        $.ajax({
                            url : 'upload.do?method='+method+'&uid='+$('#uid').val(),
                            type : "POST",
                            dataType : 'json',
                            async : false,
                            data : {image : canvas.toDataURL("image/png")},
                            success : function(data) {    
                                alert(data.flag+'---'+data.message);
                                var msg = data.message;
                                if (msg != "success") {
                                    resultflag=false;
                                }
                            },
                            error : function(error) {
                                tip('访问数据异常', '异常提示');
                                return true;
                            }
                        });
                    /*     $.post("upload.do", {
                            type : "data",
                            image : canvas.toDataURL("image/png"),
                            function(data,status){
                                alert("Data: " + data + "
    Status: " + status);
                              }
                        }); */
                        pos = 0;
                    }
                };
    
            } else {
                saveCB = function(data) {
                    //把数据一点点的放入image[]
                    image.push(data);
                    pos += 4 * 320;
                    if (pos >= 4 * 320 * 240) {
                        $.post("upload.do", {
                            type : "pixel",
                            image : image.join('|')
                        });
                        pos = 0;
                    }
                };
            }
    
            //                /**
            //                 * 获取canvas画布的内容 getImageData
            //                 * 内容放回到canvas画布 putImageData
            //                 * 获取ImgData的每一个像素 ImgData.data
            //                 * getImageData(起始点的横坐标, 起始点的纵坐标, 获取的宽度, 获取的高度)
            //                 * putImageData(绘制点的横坐标, 绘制点点纵坐标, imgData的起始点横坐标, imgData的起始点纵坐标, 宽度, 高度)
            //                 */
            $("#webcam").webcam({
                width : 320,
                height : 240,
                mode : "callback",
                swffile : "js/jscam_canvas_only.swf",
                onTick : function(remain) {
    
                    if (0 == remain) {
                        jQuery("#status").text("Cheese!");
                    } else {
                        jQuery("#status").text(remain + " seconds remaining...");
                    }
                },
                onSave : saveCB,
                onCapture : function() {
                    webcam.save();
                },
    
                debug : function(type, string) {
                    console.log(type + ": " + string);
                }
            });
            
            
        });
    
        //拍照
        //var iCount = setInterval(action,10000);//循环执行
        //var i = 1;
        var method = 'login';
        function action(action) {
                var uid = $('#uid').val();
                if('' == uid){
                    alert('uid不能为空');
                    return ;
                }
                if(action != null){
                    method = action;
                }
                /* if(i == 1){
                    clearInterval(iCount);
                } */
                webcam.capture();
        }
    </script>
    
    </script>
    </html>

    4、servlet接收传经来的base64编码的图片文件,并进行登录和注册的处理

    package com.hengyunsoft.face.login;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.PrintWriter;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.json.JSONObject;
    
    import sun.misc.BASE64Decoder;
    
    import com.baidu.aip.face.AipFace;
    import com.hengyunsoft.face.aip.FaceManage;
    
    /**
     * Servlet implementation class UploadFile
     */
    @WebServlet("/upload.do")
    public class Login extends HttpServlet {
        private static final long serialVersionUID = 1L;
        //设置APPID/AK/SK
        public static final String APP_ID = "10580034";
        public static final String API_KEY = "CUEBLydMIEhyHXGgjuBLMCDx";
        public static final String SECRET_KEY = "xPATdkt3lpn0TiWZyGtfUs1rYrN5HgI6";
           
        /**
         * @see HttpServlet#HttpServlet()
         */
        public Login() {
            super();
            // TODO Auto-generated constructor stub
        }
    
        /**
         * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
         */
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            try {
                uploadPhoto(request, response);
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
         */
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doGet(request, response);
        }
    
        /**
    
         * 功能描述:拍照并上传图片
    
         *
    
         * @since 2016/5/24
    
         */
    
        public void uploadPhoto(HttpServletRequest req, HttpServletResponse resp) throws Exception {
            resp.setContentType("application/text; charset=utf-8");
    
            String basePath = "upload/" + getDate("yyyyMMdd") + "/";
            String filePath = req.getSession().getServletContext().getRealPath("/") + basePath;
            String fileName = getDate("yyyyMMddHHmmss") + ".png";
            //默认传入的参数带类型等参数:data:image/png;base64,
            PrintWriter out = resp.getWriter();
            JSONObject j = new JSONObject();
    
            String imgStr = req.getParameter("image");
            String uid = req.getParameter("uid");
            String method = req.getParameter("method");
            if (null != imgStr) {
                imgStr = imgStr.substring(imgStr.indexOf(",") + 1);
            }
    
           
           //文件上传到服务器
            Boolean flag = GenerateImage(imgStr, filePath, fileName);
            String message = "没有检测到图片";
            if (flag) {
                //拿到base64编码的图片,就可以调用百度的API进行验证
                AipFace client = new AipFace(APP_ID, API_KEY, SECRET_KEY);
                if(method.equals("login")){
                    message = login(filePath, fileName, j, uid, client);
                }else if (method.equals("reg")) {
                    message = register(filePath, fileName, j, uid, client);
                }
                
            }
            
            j.put("message", message);
            out.write(j.toString());
        }
    
        /**
         * 登录
         * 
         * @param filePath
         * @param fileName
         * @param j
         * @param uid
         * @param client
         * @return
         */
        private String login(String filePath, String fileName, JSONObject j,
                String uid, AipFace client) {
            String message;
            double matchPercent = FaceManage.verifyUser(client, filePath + fileName,uid);
            if (matchPercent > 90) {
                System.out.println("验证成功,人脸匹配度是:"+matchPercent);
                j.put("flag", true);
                message = "验证成功,人脸匹配度是:"+matchPercent;
            }else{
                System.out.println("验证失败,人脸匹配度是:"+matchPercent);
                j.put("flag", false);
                message = "验证失败,人脸匹配度是:"+matchPercent;
            }
            return message;
        }
    
        /**
         * 注册
         * 
         * @param filePath
         * @param fileName
         * @param j
         * @param uid
         * @param client
         * @return
         */
        private String register(String filePath, String fileName, JSONObject j,
                String uid, AipFace client) {
            String message;
            int matchPercent = FaceManage.addUser(client, filePath + fileName,uid);
            if (matchPercent == 1) {
                System.out.println("注册成功");
                j.put("flag", true);
                message = "注册成功";
            }else{
                System.out.println("注册失败");
                j.put("flag", false);
                message = "注册失败";
            }
            return message;
        }
    
        
        
    
        /**
    
         * 功能描述:base64字符串转换成图片
    
         *
    
         * @since 2016/5/24
    
         */
    
        public boolean GenerateImage(String imgStr, String filePath, String fileName) {
    
            try {
                if (imgStr == null) {
                    return false;
                }
                BASE64Decoder decoder = new BASE64Decoder();
                //Base64解码
                byte[] b = decoder.decodeBuffer(imgStr);
                //如果目录不存在,则创建
                File file = new File(filePath);
                if (!file.exists()) {
                    file.mkdirs();
                }
                //生成图片
    
                OutputStream out = new FileOutputStream(filePath + fileName);
                out.write(b);
                out.flush();
                out.close();
                return true;
    
            } catch (Exception e) {
                System.out.println("生成图片异常:{}"+e.getMessage());
                return false;
    
            }
    
        }
    
        public String getDate(String pattern){
            return new SimpleDateFormat(pattern).format(new Date());
        }
    }

    其中web.xml的配置如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
      <display-name>AipFaceSys</display-name>
      <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
      </welcome-file-list>
      <servlet>
        <servlet-name>UploadFile</servlet-name>
        <servlet-class>com.hengyunsoft.UploadFile</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>UploadFile</servlet-name>
        <url-pattern>*.do</url-pattern>
      </servlet-mapping>
    </web-app>

    其中servlet中用到的FaceManage等类,都在 博客:你的第一个人脸识别demo((http://www.cnblogs.com/guo-eric/p/8109411.html)中有明确说明,有问题,请联系我,和大家一起学习进步!

     FAQ:

              倘若浏览器报错了:提示webcam.capture is not a function ,这是因为jquery-webcam必须用在项目中,才能够正常使用。

            

      如果IE浏览器中摄像头显示不出来,需要按照以下操作设置:

             1)合理设置浏览器,启用flash的正确方法:

             Internet Explorer,设置,安全,禁用ActiveX筛选(去掉勾)

             2)管理加载项,启用Shockwave Flash Object

  • 相关阅读:
    Docker+Jenkins更换国内插件源
    招聘java工程师
    Apache seaTunnel 数据集成平台
    DBeaver连接MySQL问题的解决
    iphone的mov文件复制到电脑的方法
    IDEA中RestfulToolkit插件的安装及使用
    lwm2m 的notify 的机制
    ALI云接入学习
    CAT1 UIS8910模组对接阿里云平台
    任务的堆栈究竟有何魔力
  • 原文地址:https://www.cnblogs.com/guo-eric/p/8371861.html
Copyright © 2020-2023  润新知