人脸识别 | Java 实现 AI人工智能技术 - 人脸识别-附源码

最近几天很多人问我,这几天怎么发文慢了?

一是这几天确实比较忙,工作是饭碗,不能砸了吧,不然康哥吃啥,孩子的奶粉又得买了。靠工资肯定不够奶粉啊,还得有自己的一些其他项目,您说对吧,另外还在总结《SpringBoot2.x企业实战教程》,这本电子书从入门到实战项目,总共20章,此处就不具体说了,等写完之后,再来吹吧。总之最近有点忙。

二是在细心的总结有用的知识。康哥是一个重效率的人,公众号宁可不发文,也不会携带软文、烦文、广告,很多没技术含量的只为了点赞的文章,我们是纯、纯技术号。如果咱俩价值观一样,就分享下,是对康哥最大的支持。

好了,跑偏了,今天康哥总结了AV、不,AI的新的技术点【人脸识别】,上几期的图像识别、语音识别、车牌识别、网络爬虫没来得及看的同学,请点击这里。

《Java 实现 AI 人工智能技术 - 语音识别功能》

《Java 实现 AI人工智能技术 - 网络爬虫功》

《使用 Java 实现AI人工智能技术-图像识别功能》

需求: 登录使用人脸识别登录、人脸录入功能

技术点 & 开发工具: Myeclipse、JDK1.8、Tomcat8、SSM框架、HTTPS、JSON、jsp、百度云

人脸识别: 是基于人的脸部特征信息进行身份识别的一种生物识别技术。用摄像机或摄像头采集含有人脸的图像或视频流,并自动在图像中检测和跟踪人脸,进而对检测到的人脸进行脸部识别的一系列相关技术,通常也叫做人像识别、面部识别。

技术流程: 人脸图像采集及检测 人脸图像预处理 人脸图像特征提取 匹配与识别

识别算法: 基于人脸特征点的识别算法(Feature-based recognition algorithms) 基于整幅人脸图像的识别算法(Appearance-based recognition algorithms) 基于模板的识别算法(Template-based recognition algorithms) 利用神经网络进行识别的算法(Recognition algorithms using neural network) 基于光照估计模型理论 优化的形变统计校正理论 独创的实时特征识别理论

开发步骤:

1:首先开通百度云-AI-功能账号,并创建应用,如下图

2:创建应用之后,进入应用内,点击编辑,将人脸识别等功能进行授权

3:新建一个web project,如下图:

4:搭建SSM框架,导包并配置web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    id="WebApp_ID" version="3.1">
    <display-name>FaceDemo</display-name>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/classes/applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>action</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>action</servlet-name>
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

5:配置ApplicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"
    xmlns:mvc="http://www.springframework.org/schema/mvc">

    <context:annotation-config/>
    <context:component-scan base-package="com.spring/web"></context:component-scan>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${mysql.driver}" />
        <property name="url" value="${mysql.url}" />
        <property name="username" value="${mysql.username}" />
        <property name="password" value="${mysql.password}" />
        <!-- 初始化连接大小 -->
        <property name="initialSize" value="30" />
        <!-- 连接池最大数量 -->
        <property name="maxActive" value="1000" />
        <!-- 连接池最大空闲 -->
        <property name="maxIdle" value="50" />
        <!-- 连接池最小空闲 -->
        <property name="minIdle" value="30" />
        <!-- 获取连接最大等待时间 -->
        <property name="maxWait" value="36000" />
    </bean>

    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:db.properties" />
    </bean>

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="mapperLocations" value="classpath:com/spring/web/entity/*.xml" />
    </bean>


</beans>

6:添加登录页面index.jsp

<script>
$(document).ready(function() {
  //粒子背景特效
  $('body').particleground({
    dotColor: '#5cbdaa',
    lineColor: '#5cbdaa'
  });
  //验证码
  createCode();
  //测试提交,对接程序删除即可
  $(".submit_btn").click(function(){
      localhost.href="index.jsp";
      });
});
</script>


<style type="text/css">
* {
    margin: 0;
    padding: 0;
}

body {
    height: 100vh;
    background-position: center;
    overflow: hidden;
}

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;
    opacity: 0.7px;
}

#video {

}

#canvas {
    display: none;
}

#btn {
    width: 160px;
    height: 50px;
    background: #03a9f4;
    margin: 70px auto 0;
    text-align: center;
    line-height: 50px;
    color: #fff;
    border-radius: 40px;
}
</style>
</head>

<body>

    <form action="${pageContext.request.contextPath}/facelogin.action" method="get">
        <dl class="admin_login">
            <dt>
                <strong>人脸识别登录管理系统</strong><em>开启摄像头,调试角度</em> <strong>请把你的脸放摄像头面前</strong>
            </dt>

            <div id="media">
                <video id="video" width="350" height="200" autoplay></video>
                <canvas id="canvas" width="400" height="300"></canvas>
            </div>
            <dd>
                <input type="button" onclick="query()" value="立即登录" class="submit_btn" />
            </dd>

        </dl>
        <script type="text/javascript" src="js/jquery-3.1.1.min.js"></script>
        <script type="text/javascript">
          //var 是定义变量
          var canvans = document.getElementById("canvas");
          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();
                  }
              });

              function query(){

                  //把流媒体数据画到convas画布上去
                  context.drawImage(video,0,0,400,300);
                  var imgData = canvans.toDataURL();
                 var imgData1 = imgData.split("base64,")[1];

                  $.ajax({
                      type:"post",
                      url:"${pageContext.request.contextPath}/facelogin.action",
                      data:{"img":imgData1},
                      success:function(data){

                          /* alert(data) */
                            var result = eval(data);

                            if(result){
                                 alert("登录成功")
                                } else {
                                    alert("面容识别失败,请继续验证");
                                }
                            }
                        });
            }
            function getBase64() {
                var imgSrc = document.getElementById("canvas").toDataURL("image/png");
                alert(imgSrc);
                return imgSrc.split("base64,")[1];
            };
        </script>
    </form>
</body>
</html>

7:添加人脸录入界面registe.jsp

<body>

    <form action="${pageContext.request.contextPath}/registe.action" method="get">
        <dl class="admin_login">
            <dt>
                <strong>人脸识别头像录入</strong>
                <em></em>
                请输入用户名:<input type="text" name="username" id="username" />
            </dt>
            <div id="media">
                <video id="video" width="350" height="200" autoplay></video>
                <canvas id="canvas" width="600" height="500"></canvas>
            </div>
            <dd>
                <input type="button" onclick="registe()" value="立即注册" class="submit_btn" />
            </dd>

        </dl>
        <script type="text/javascript">

          var canvans = document.getElementById("canvas");
          var video = document.getElementById("video"); //获取video标签
          var context = canvas.getContext("2d");

          var con  ={
              audio:false,
              video:{
              width:1980,
              height:1980,
              }
          };  

          //导航 获取用户媒体对象
              navigator.mediaDevices.getUserMedia(con)
              .then(function(stream){
                  video.src = window.URL.createObjectURL(stream);
                  video.onloadmetadate = function(e){
                      video.play();
                  }
              });

              function registe(){

                  context.drawImage(video,0,0);
                 var imgData = canvans.toDataURL();
                 var imgData1 = imgData.split("base64,")[1];
                 var username = $("#username").val();
                  $.ajax({
                      type:"post",
                      url:"${pageContext.request.contextPath}/registe.action",
                      data: {"img":imgData1,"username":username},
                      success:function(data){
                          alert(data);
                    },error:function(msg){
                          alert("错误");
                    }
                });
            }
        </script>
    </form>
</body>

8:新建一张数据库表users,便于后续做登录信息的认证或者签到功能,结构如下:

CREATE TABLE `users` (
  `id` int(50) NOT NULL AUTO_INCREMENT,
  `username` varchar(100) DEFAULT NULL,
  `password` varchar(100) DEFAULT NULL,
  `headphoto` varchar(5000) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8

9:逆向工程生成这张表的接口和实体以及dao

10:添加如下结构的类

11:核心代码,其它类的代码,可联系康哥获取,或者参考文末的下载地址。

UserController.java:

/**
 * 人脸识别后台控制器
* @author likang
* @date 2018年8月9日
 */
@Controller
public class UserControll {

    private static String accessToken;

    @Resource
    private FaceService faceService;

    /**
     * 用户人脸识别头像录入(每个用户建议只允许录入一次)
     * @param request
     * @param response
     * @param model
     */
    @RequestMapping("/registe.action")
    public @ResponseBody void registe(HttpServletRequest request, HttpServletResponse response, Model model) {
        String img = request.getParameter("img"); // 图像数据
        String username = request.getParameter("username"); // 用户名
        // 注册百度云 人脸识别 提供的信息
        String APP_ID = "11644574";
        String API_KEY = "mGZF5fUuRpHk3QBBs3vsGRd7";
        String SECRET_KEY = "wFI1UYM5eAE6HMp8qguq8mH9qaCTwgPf";
        AipFace client = new AipFace(APP_ID, API_KEY, SECRET_KEY);
        face(username, img, response, request, client);
    }

    /**
     *作用:     1.将base64编码的图片保存 
     *        2.将图片路径保存在数据库里面
     *        3.将人脸图片识别在人脸库中注册 
     */
    public void face(String username, String img, HttpServletResponse response, HttpServletRequest request,
            AipFace client) {
        Users user = new Users();
        // 图片名称
        String fileName = System.currentTimeMillis() + ".png";
        String basePath = request.getSession().getServletContext().getRealPath("picture/");

        // 往数据库里面插入注册信息
        user.setUsername(username);
        user.setHeadphoto("/picture/" + fileName);
        faceService.save(user);
        // 往服务器里面上传图片
        GenerateImage(img, basePath + "/" + fileName);
        // 给人脸库中加入一个脸
        boolean flag = facesetAddUser(client, fileName, username,img);
        try {
            PrintWriter out = response.getWriter();
            // 中文乱码,写个英文比较专业 哈哈
            if (flag == false) {
                out.print("Please aim at the camera!!");// 请把脸放好咯
            } else {
                out.print("Record the success of the image!!"); // 注册成功
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public boolean GenerateImage(String imgStr, String imgFilePath) {
        if (imgStr == null) // 图像数据为空
            return false;
        Decoder decoder = Base64.getDecoder();
        try {
            // Base64解码
            byte[] bytes = decoder.decode(imgStr);
            for (int i = 0; i < bytes.length; ++i) {
                if (bytes[i] < 0) {// 调整异常数据
                    bytes[i] += 256;
                }
            }
            // 生成jpeg图片
            OutputStream out = new FileOutputStream(imgFilePath);
            out.write(bytes);
            out.flush();
            out.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }




    public boolean facesetAddUser(AipFace client, String path, String username, String img) {

         String url = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/add";
            try {
                Map<String, Object> map = new HashMap<>();
                map.put("image", img);
                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","BASE64");
                map.put("quality_control", "LOW");

                String param = GsonUtils.toJson(map);

                // 注意这里仅为了简化编码每一次请求都去获取access_token,线上环境access_token有过期时间, 客户端可自行缓存,过期后重新获取。
                accessToken = GetTon.getToken();

                String result = HttpUtil.post(url, accessToken, "application/json", param);
                System.out.println(result);

                JSONObject fromObject = JSONObject.fromObject(result);

                Object errormsg = fromObject.get("error_msg");
                    if (errormsg.toString().equals("SUCCESS")) {
                        return true;
                    }
                return false; 
            }catch (Exception e) {
                e.printStackTrace();
            }
            return false;
    }

     public boolean search(String img) {
            // 请求url
            String url = "https://aip.baidubce.com/rest/2.0/face/v3/search";
            try {
                Map<String, Object> map = new HashMap<>();
                map.put("image", img);
                map.put("liveness_control", "NORMAL");
                map.put("group_id_list", "group_repeat");
                map.put("image_type", "BASE64");
                map.put("quality_control", "LOW");

                String param = GsonUtils.toJson(map);

                // 注意这里仅为了简化编码每一次请求都去获取access_token,线上环境access_token有过期时间, 客户端可自行缓存,过期后重新获取。
                accessToken = GetTon.getToken();

                String result = HttpUtil.post(url, accessToken, "application/json", param);
                System.out.println(result);

                JSONObject fromObject = JSONObject.fromObject(result);
                JSONObject resultscore = fromObject.getJSONObject("result");
                JSONArray jsonArray = resultscore.getJSONArray("user_list");

                for (int i = 0; i < jsonArray.size(); i++) {
                    JSONObject object = (JSONObject) jsonArray.get(i);
                    double resultList = object.getDouble("score");
                    System.out.println(resultList);
                    if (resultList >= 90) {
                        return true;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return false;
        }


     /**
      * 用户人脸识别登录功能
      * @param request
      * @param response
      * @param model
      * @return
      */
    @RequestMapping("/facelogin.action")
    public @ResponseBody String onListStudent(HttpServletRequest request, HttpServletResponse response, Model model) {
        String img = request.getParameter("img"); // 图像数据
        try {
            boolean tag = search(img);
            PrintWriter writer = response.getWriter();
            if (tag) {
                request.getSession().setAttribute("user", "likang");
                writer.print(tag);
                writer.close();
                return null;
            }else {
                writer.print(tag);
                writer.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "redirect:/404.jsp";
        }
        return null;
    }


    public boolean getResult(HttpServletRequest request, String imStr1, String imgStr2) {

        accessToken = GetTon.getToken();
        boolean flag = false;
        // 请求url
        String url = "https://aip.baidubce.com/rest/2.0/face/v3/match";
        try {
             byte[] bytes1 = FileUtil.readFileByBytes("");
             byte[] bytes2 = FileUtil.readFileByBytes("");
             String image1 = Base64Util.encode(bytes1);
             String image2 = Base64Util.encode(bytes2);

            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 result = HttpUtil.post(url, accessToken, "application/json", param);
            System.out.println(result);
            // return result;
            JSONObject fromObject = JSONObject.fromObject(result);

            JSONArray jsonArray = fromObject.getJSONArray("result");

            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject object = (JSONObject) jsonArray.get(i);
                double resultList = object.getDouble("score");
                if (resultList >= 90) {
                    flag = true;

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }
}

12:将项目部署到tomcat应用服务器,访问使用

源码下载地址:

链接:https://pan.baidu.com/s/1FBQutG3HDhcXLZJlAsT1KQ 密码:5ofd

原文发布于微信公众号 - 码神联盟(lkchatspace)

原文发表时间:2018-08-09

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Golang语言社区

剖析Go的读写锁

package main import ( "fmt" "sync" "time" ) func main() { rw := new(...

37415
来自专栏IT派

Python高性能计算库——Numba

摘要: 在计算能力为王的时代,具有高性能计算的库正在被广泛大家应用于处理大数据。例如:Numpy,本文介绍了一个新的Python库——Numba, 在计算性能方...

6968
来自专栏数据分析

[数据清洗]-Pandas 清洗“脏”数据(一)

概要 准备工作 检查数据 处理缺失数据 添加默认值 删除不完整的行 删除不完整的列 规范化数据类型 必要的转换 ...

9857
来自专栏自然语言处理

结巴中文分词原理分析4

本机是win10 64位,已经安装了pip工具,关于pip下载安装(here),然后win+R,输入pip install jieba,效果如下:

1172
来自专栏玉树芝兰

如何用Python处理自然语言?(Spacy与Word Embedding)

本文教你用简单易学的工业级Python自然语言处理软件包Spacy,对自然语言文本做词性分析、命名实体识别、依赖关系刻画,以及词嵌入向量的计算和可视化。

1781
来自专栏Linyb极客之路

浅谈黑盒测试和白盒测试

  从图中可以直接看出来,黑盒测试就当整个程序是个黑盒子,我们看不到它里面做了些什么事情,只能通过输入输出看是否能得到我们所需的来测试。而白盒测试可以当盒子是透...

2341
来自专栏牛客网

网易java后台实习生面试面经

3030
来自专栏PPV课数据科学社区

【学习】使用hadoop进行大规模数据的全局排序

1. Hellow hadoop~~! Hadoop(某人儿子的一只虚拟大象的名字)是一个复杂到极致,又简单到极致的东西。 说它复杂,是因为一个hadoop...

3003
来自专栏架构师小秘圈

MapReduce极简教程

一个有趣的例子 你想数出一摞牌中有多少张黑桃。直观方式是一张一张检查并且数出有多少张是黑桃? ? MapReduce方法则是: 给在座的所有玩家中分配这摞牌 ...

4008
来自专栏人工智能LeadAI

拼图游戏和它的AI算法

写了个拼图游戏,探讨一下相关的AI算法。拼图游戏的复原问题也叫做N数码问题。 拼图游戏 N数码问题 广度优先搜索 双向广度优先搜索 A*搜索 游戏设定 实现一个...

57811

扫码关注云+社区

领取腾讯云代金券