基於百度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;
    width: 320px;
    height: 240px;
}

#photos {
    border: 1px solid #666666;
    width: 320px;
    height: 240px;
}

.btn {
    width: 320px;
    height: auto;
    margin: 5px 0px;
}

.btn input[type=button] {
    width: 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 + "\nStatus: " + 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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM