【AI】Java+Fileupload+JSTL+Face++实现人脸识别系统

news/2024/5/18 14:31:38 标签: java, jstl, 人工智能, 技术, 中国

一、前言

      人工智能(Artificial Intelligence),英文缩写为AI。它是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。

      在现在我们的生活中,我们越来越多的接触到人工智能了。2016年3月,阿尔法围棋与围棋世界冠军、职业九段棋手李世石进行围棋人机大战,以4比1的总比分获胜;2016年末2017年初,该程序在中国棋类网站上以“大师”(Master)为注册帐号与中日韩数十位围棋高手进行快棋对决,连续60局无一败绩;2017年5月,在中国乌镇围棋峰会上,它与排名世界第一的世界围棋冠军柯洁对战,以3比0的总比分获胜。

      小编从中感觉到了人工智能的第三次浪潮即将到来。随后小编最近研究了人工智能的人脸识别技术,刚开始研究了javacv、opencv,到现在研究的Face++,这个技术越来越成熟,也在不断的更新。下面带来人脸识别。

二、Face++介绍

      Face++TM是新一代云端视觉服务平台,提供一整套世界领先的人脸检测,人脸识别,面部分析的视觉技术服务。网页地址请点直击

      提供的技术包括了人脸检测、追踪、人脸关键点检测、 微笑分析、 性别、年龄、种族、1:1人脸验证、 1:N人脸识别、大规模人脸搜索。

      小编亲测:上传狗或非人的照片,Face++是不会进行测试的。这个辩证的还是相当准确的,值得信赖。

这里写图片描述

这里写图片描述

三、实现过程

      这里小编先说一下实现思路,小编把要解析的图片上传到服务器,然后通过调用face++的接口,对图片进行分析,得到分析的json数据。然后解析这些输入为中文,在界面显示分析结果。

这里写图片描述

3.0 项目环境要求

  • commons-io-2.5.jar

  • commons-fileupload-1.3.3.jar (用于上传图片)

  • net.sf.json jar (用于解析返回的Json)

  • jstl.jar

  • standard.jar (用于显示解析后的数据)

3.1 建立项目

      建立一个java web项目:AresFace

这里写图片描述

3.2 上传图片:使用Apache的org.apache.commons.fileupload组件

这里写图片描述
      上传图片前台代码:

      核心就是一个提交表单,这个提交表单,要求为post,而且要enctype=”multipart/form-data”

      然后方法提交到后台的UploadHandleServlet.java的servlet中,调用post方法,执行上传图片操作。


<%@ 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">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="description" content="">
<meta name="keywords" content="">
<meta name="author" content="templatemo">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

<title>Stimulus HTML CSS Template</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/bootstrap.min.css">
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/animate.css">
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/font-awesome.min.css">
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/templatemo-style.css">

<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,700" rel="stylesheet">

</head>
<body data-spy="scroll" data-target=".navbar-collapse" data-offset="50">

${file}
${message}
<div class="preloader">
     <div class="spinner">
          <span class="spinner-rotate"></span>
     </div>
</div>

<section id="contact" class="parallax-section">
     <div class="container">
          <div class="row">

               <div class="col-md-6 col-sm-12">
                    <div class="contact-form">
                         <div class="wow fadeInUp section-title" data-wow-delay="0.2s">
                              <h1 class="color-white">Welcome to face recognition.</h1>
                              <p class="color-white">Author:Ares.</p>
                         </div>

                         <div id="contact-form">
                              <form action="${pageContext.request.contextPath}/servlet/UploadHandleServlet"" method="post" enctype="multipart/form-data" >
                                   <div class="wow fadeInUp" data-wow-delay="1s">
                                        <input name="username" type="text" class="form-control" id="fullname" placeholder="Your Name">
                                   </div>
                                  <!-- <div class="wow fadeInUp" data-wow-delay="1.2s">
                                        <input name="email" type="email" class="form-control" id="email" placeholder="Your Email">
                                   </div> -->
                                   <!-- <div class="wow fadeInUp" data-wow-delay="1.4s">
                                        <textarea name="message" rows="5" class="form-control" id="message" placeholder="Write your message..."></textarea>
                                   </div> -->

            <div class="wow fadeInUp" data-wow-delay="1.2s">
                                        <input type="file" name="file1" class="form-control "/>
                                   </div>

                                   <div class="wow fadeInUp col-md-6 col-sm-8" data-wow-delay="1.4s">
                                         <input name="submit" type="submit" class="form-control" id="submit" value="Send">
                                   </div>
                              </form>
                         </div>

                    </div>
               </div>

               <div class="col-md-3 col-sm-6">
             <div class="background-image contact-img" ></div> 
                   <!--  <img alt="" src="images/contact-img.jpg" style="min-height: 75vh;" class="background-image ">  -->
               </div>

               <div class="bg-dark col-md-3 col-sm-6">
                    <div class="contact-thumb">
                         <div class="wow fadeInUp contact-info" data-wow-delay="0.6s">
                              <h3 class="color-white">Visit my office</h3>
                              <p> Zhi Sheng Chong off center four floor, Guangyang District , Langfang , China</p>
                         </div>

                         <div class="wow fadeInUp contact-info" data-wow-delay="0.8s">
                              <h3 class="color-white">Contact.</h3>
                              <p><i class="fa fa-phone"></i> 183-3360-2097</p>
                              <p><i class="fa fa-envelope-o"></i> <a href="mailto:18333602097@163.com">18333602097@163.com</a></p>
                              <p><i class="fa fa-globe"></i> <a href="http://blog.csdn.net/kisscatforever?viewmode=contents">www.Ares.com</a></p>
                         </div>

                    </div>
               </div>

          </div>
     </div>
</section>


<!-- Footer Section -->
<footer style="background-position: 100% 106px;padding-top: 30px;">
        <div class="container">
                <div class="row">

               <div class="col-md-12 col-sm-12">
                    <div class="wow fadeInUp footer-copyright" data-wow-delay="1.8s">
                         <p>Copyright &copy; 2016 Your Company

                    | More Templates <a href="http://blog.csdn.net/kisscatforever?viewmode=contents" target="_blank" title="王雷">王雷@Ares.com</a> - Collect from <a href="http://blog.csdn.net/kisscatforever?viewmode=contents" title="技术天地" target="_blank">技术天地</a></p>
                    </div>
        <ul class="wow fadeInUp social-icon" data-wow-delay="2s">
                         <li><a href="#" class="fa fa-facebook"></a></li>
                         <li><a href="#" class="fa fa-twitter"></a></li>
                         <li><a href="#" class="fa fa-google-plus"></a></li>
                         <li><a href="#" class="fa fa-dribbble"></a></li>
                         <li><a href="#" class="fa fa-linkedin"></a></li>
                    </ul>
               </div>

        </div>
        </div>
</footer>

<!-- SCRIPTS -->

<script src="${pageContext.request.contextPath}/js/jquery.js">javascript"></script>
<script src="${pageContext.request.contextPath}/js/bootstrap.min.js">javascript"></script>
<script src="${pageContext.request.contextPath}/js/jquery.parallax.js">javascript"></script>
<script src="${pageContext.request.contextPath}/js/smoothscroll.js">javascript"></script>
<script src="${pageContext.request.contextPath}/js/wow.min.js">javascript"></script>
<script src="${pageContext.request.contextPath}/js/custom.js">javascript"></script>

</body>
</html>

      UploadHandleServlet.java 上传图片并解析json数据

      使用Apache文件上传组件处理文件上传步骤:

      1、创建一个DiskFileItemFactory工厂

      2、创建一个文件上传解析器

      注意:解决上传文件名的中文乱码upload.setHeaderEncoding(“UTF-8”);

      3、判断提交上来的数据是否是上传表单的数据

       4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List集合,每一个FileItem对应一个Form表单的输入项

/**
     * serlet 的post方法,用于上传图片和显示人脸分析后的信息
     */
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
        String savePath = this.getServletContext().getRealPath("/images");
        File file = new File(savePath);
        String filename = null;
        List<Attributes> Attributeslist = new ArrayList<Attributes>();
        // 判断上传文件的保存目录是否存在
        if (!file.exists() && !file.isDirectory()) {
            System.out.println(savePath + "目录不存在,需要创建");
            // 创建目录
            file.mkdir();
        }
        // 消息提示
        String message = "";
        try {
            // 使用Apache文件上传组件处理文件上传步骤:
            // 1、创建一个DiskFileItemFactory工厂
            DiskFileItemFactory factory = new DiskFileItemFactory();
            // 2、创建一个文件上传解析器
            ServletFileUpload upload = new ServletFileUpload(factory);
            // 解决上传文件名的中文乱码
            upload.setHeaderEncoding("UTF-8");
            // 3、判断提交上来的数据是否是上传表单的数据
            if (!ServletFileUpload.isMultipartContent(request)) {
                // 按照传统方式获取数据
                return;
            }
            // 4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
            List<FileItem> list = upload.parseRequest(request);
            for (FileItem item : list) {
                // 如果fileitem中封装的是普通输入项的数据
                if (item.isFormField()) {
                    String name = item.getFieldName();
                    // 解决普通输入项的数据的中文乱码问题
                    String value = item.getString("UTF-8");
                    // value = new String(value.getBytes("iso8859-1"),"UTF-8");

                    System.out.println(name + "=" + value);
                } else {// 如果fileitem中封装的是上传文件
                        // 得到上传的文件名称,
                    filename = item.getName();
                    System.out.println(filename);
                    if (filename == null || filename.trim().equals("")) {

                        continue;
                    }
                    // 注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:
                    // c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt
                    // 处理获取到的上传文件的文件名的路径部分,只保留文件名部分
                    filename = filename
                            .substring(filename.lastIndexOf("\\") + 1);
                    // 获取item中的上传文件的输入流
                    InputStream in = item.getInputStream();
                    // 创建一个文件输出流
                    FileOutputStream out = new FileOutputStream(savePath + "\\"
                            + filename);
                    // 创建一个缓冲区
                    byte buffer[] = new byte[1024];
                    // 判断输入流中的数据是否已经读完的标识
                    int len = 0;
                    // 循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
                    while ((len = in.read(buffer)) > 0) {
                        // 使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\"
                        // + filename)当中
                        out.write(buffer, 0, len);
                    }
                    // 关闭输入流
                    in.close();
                    // 关闭输出流
                    out.close();
                    // 删除处理文件上传时生成的临时文件
                    item.delete();

                    System.out.println("文件上传成功!");
                }
            }

            //face++解析上传的图片,返回解析json数据
            String faceMessage = FaceDetect
                    .getFaceMessage("D:/Ares/Java/.metadata/.plugins/org.eclipse.wst.server.core/tmp1/wtpwebapps/AresFace/images/"
                            + filename);

            request.setAttribute("file", filename);
            request.setAttribute("faceMessage", faceMessage);

            // 使用 net.sf.json.JSONObject 解析json
            JSONObject jsonObject = JSONObject.fromObject(faceMessage);

            System.out.println("image_id:" + jsonObject.get("image_id"));
            System.out.println("request_id:" + jsonObject.get("request_id"));
            System.out.println("花费的时间:" + jsonObject.get("time_used") + "毫秒");
            request.setAttribute("time_used",
                    "花费的时间:" + jsonObject.get("time_used") + "毫秒");

            Attributeslist = JsontoList(faceMessage);


            message = "人脸识别结果如下:";

            request.setAttribute("message", message);
        } catch (Exception e) {
            message = "文件上传失败!";
            e.printStackTrace();

        }
        request.setAttribute("AttributesList", Attributeslist);
        // 信息界面显示
        request.getRequestDispatcher("/message.jsp").forward(request, response);
    }

java类来获取解析后的图片的数据">3.3 使用face++提供的java类来获取解析后的图片的数据

      建立类FaceDetect(face++提供的代码,需要用户注册先)

      Face++官网:https://console.faceplusplus.com.cn/documents/6329752

这里写图片描述

      这里需要说明的几点是:

      1.方法参数:输入图片的url

      2.注册Face++后的api_key和api_secret。

      3.设置要显示的属性

这里写图片描述
这里写图片描述

      建立FaceDetect类:

java">package com.dmsd.util;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;

import javax.net.ssl.SSLException;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
public class FaceDetect {

        javadoc">/**
         * 根据上传的图片路径获取face++解析的人脸信息
         *javadoctag"> @author Ares
         *javadoctag"> @param path 路径
         *javadoctag"> @return String 
         */
        public static String getFaceMessage(String path){
                 File file = new File(path);
                        byte[] buff = getBytesFromFile(file);
                        String url = "https://api-cn.faceplusplus.com/facepp/v3/detect";
                HashMap<String, String> map = new HashMap<String, String>();
                HashMap<String, byte[]> byteMap = new HashMap<String, byte[]>();
                map.put("api_key", "Q01U_nrXThBS6zs-5dQ********JCcD");
                map.put("api_secret", "U6h4ilxGtOjTeWjmF_jT********-IW");
                map.put("return_attributes", "gender,age,smiling,headpose,emotion,ethnicity,beauty,mouthstatus,eyegaze");
                byteMap.put("image_file", buff);

                try{
                    byte[] bacd = post(url, map, byteMap);
                    String str = new String(bacd);
                    System.out.println(str);
                    return str;
                }catch (Exception e) {
                    e.printStackTrace();
                }
                return "";
        }

        private final static int CONNECT_TIME_OUT = 30000;
    private final static int READ_OUT_TIME = 50000;
    private static String boundaryString = getBoundary();

    javadoc">/**
     * 文件转换为二进制
     *javadoctag"> @author face++
     *javadoctag"> @param f 文件
     *javadoctag"> @return byte[] 二进制
     */
    protected static byte[] post(String url, HashMap<String, String> map, HashMap<String, byte[]> fileMap) throws Exception {
        HttpURLConnection conne;
        URL url1 = new URL(url);
        conne = (HttpURLConnection) url1.openConnection();
        conne.setDoOutput(true);
        conne.setUseCaches(false);
        conne.setRequestMethod("POST");
        conne.setConnectTimeout(CONNECT_TIME_OUT);
        conne.setReadTimeout(READ_OUT_TIME);
        conne.setRequestProperty("accept", "*/*");
        conne.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundaryString);
        conne.setRequestProperty("connection", "Keep-Alive");
        conne.setRequestProperty("user-agent", "Mozilla/4.0 (compatible;MSIE 6.0;Windows NT 5.1;SV1)");
        DataOutputStream obos = new DataOutputStream(conne.getOutputStream());
        Iterator iter = map.entrySet().iterator();
        while(iter.hasNext()){
            Map.Entry<String, String> entry = (Map.Entry) iter.next();
            String key = entry.getKey();
            String value = entry.getValue();
            obos.writeBytes("--" + boundaryString + "\r\n");
            obos.writeBytes("Content-Disposition: form-data; name=\"" + key
                    + "\"\r\n");
            obos.writeBytes("\r\n");
            obos.writeBytes(value + "\r\n");
        }
        if(fileMap != null && fileMap.size() > 0){
            Iterator fileIter = fileMap.entrySet().iterator();
            while(fileIter.hasNext()){
                Map.Entry<String, byte[]> fileEntry = (Map.Entry<String, byte[]>) fileIter.next();
                obos.writeBytes("--" + boundaryString + "\r\n");
                obos.writeBytes("Content-Disposition: form-data; name=\"" + fileEntry.getKey()
                        + "\"; filename=\"" + encode(" ") + "\"\r\n");
                obos.writeBytes("\r\n");
                obos.write(fileEntry.getValue());
                obos.writeBytes("\r\n");
            }
        }
        obos.writeBytes("--" + boundaryString + "--" + "\r\n");
        obos.writeBytes("\r\n");
        obos.flush();
        obos.close();
        InputStream ins = null;
        int code = conne.getResponseCode();
        try{
            if(code == 200){
                ins = conne.getInputStream();
            }else{
                ins = conne.getErrorStream();
            }
        }catch (SSLException e){
            e.printStackTrace();
            return new byte[0];
        }
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buff = new byte[4096];
        int len;
        while((len = ins.read(buff)) != -1){
            baos.write(buff, 0, len);
        }
        byte[] bytes = baos.toByteArray();
        ins.close();
        return bytes;
    }

    javadoc">/**
     * 分割线
     *javadoctag"> @author face++
     *javadoctag"> @return
     */
    private static String getBoundary() {
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for(int i = 0; i < 32; ++i) {
            sb.append("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-".charAt(random.nextInt("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_".length())));
        }
        return sb.toString();
    }
    javadoc">/**
     * 设置编码格式
     *javadoctag"> @author face++
     *javadoctag"> @param value 传入的字符串
     *javadoctag"> @return String 
     *javadoctag"> @throws Exception 
     */
    private static String encode(String value) throws Exception{
        return URLEncoder.encode(value, "UTF-8");
    }
    javadoc">/**
     * 文件转换为二进制
     *javadoctag"> @author face++
     *javadoctag"> @param f 文件
     *javadoctag"> @return byte[] 二进制
     */
    public static byte[] getBytesFromFile(File f) {
        if (f == null) {
            return null;
        }
        try {
            FileInputStream stream = new FileInputStream(f);
            ByteArrayOutputStream out = new ByteArrayOutputStream(1000);
            byte[] b = new byte[1000];
            int n;
            while ((n = stream.read(b)) != -1)
                out.write(b, 0, n);
            stream.close();
            out.close();
            return out.toByteArray();
        } catch (IOException e) {
        }
        return null;
    }
}

      得到的Json数据:

{
    "image_id": "t5DgXIusFEBUtDMKQY4fQg==",
    "request_id": "1505356245,91e741a5-2b4c-4c7c-af03-ec6e204546b4",
    "time_used": 446,
    "faces": [
        {
            "attributes": {
                "emotion": {
                    "sadness": 0.057,
                    "neutral": 0.391,
                    "disgust": 70.593,
                    "anger": 0.653,
                    "surprise": 0.174,
                    "fear": 0.011,
                    "happiness": 28.121
                },
                "beauty": {
                    "female_score": 71.794,
                    "male_score": 69.887
                },
                "gender": {
                    "value": "Male"
                },
                "age": {
                    "value": 18
                },
                "mouthstatus": {
                    "close": 0,
                    "surgical_mask_or_respirator": 0,
                    "open": 100,
                    "other_occlusion": 0
                },
                "headpose": {
                    "yaw_angle": 6.347545,
                    "pitch_angle": 0.6853292,
                    "roll_angle": 10.896742
                },
                "smile": {
                    "threshold": 30.1,
                    "value": 27.335
                },
                "ethnicity": {
                    "value": "Asian"
                },
                "eyegaze": {
                    "right_eye_gaze": {
                        "position_x_coordinate": 0.535,
                        "vector_z_component": 0.913,
                        "vector_x_component": 0.087,
                        "vector_y_component": 0.399,
                        "position_y_coordinate": 0.448 },
                    "left_eye_gaze": {
                        "position_x_coordinate": 0.468,
                        "vector_z_component": 0.93,
                        "vector_x_component": -0.028,
                        "vector_y_component": 0.367,
                        "position_y_coordinate": 0.458 }
                }
            },
            "face_rectangle": {
                "width": 165,
                "top": 478,
                "left": 250,
                "height": 165
            },
            "face_token": "4b6ad190af8778df2b96c74e8c84ad41"
        },
        {
            "attributes": {
                "emotion": {
                    "sadness": 21.467,
                    "neutral": 9.193,
                    "disgust": 5.763,
                    "anger": 0.226,
                    "surprise": 3.784,
                    "fear": 14.383,
                    "happiness": 45.183
                },
                "beauty": {
                    "female_score": 56.314,
                    "male_score": 55.251
                },
                "gender": {
                    "value": "Male"
                },
                "age": {
                    "value": 37
                },
                "mouthstatus": {
                    "close": 0,
                    "surgical_mask_or_respirator": 0,
                    "open": 100,
                    "other_occlusion": 0
                },
                "headpose": {
                    "yaw_angle": 0.013483647,
                    "pitch_angle": 2.941674,
                    "roll_angle": -1.834596
                },
                "smile": {
                    "threshold": 30.1,
                    "value": 58.645
                },
                "ethnicity": {
                    "value": "Asian"
                },
                "eyegaze": {
                    "right_eye_gaze": {
                        "position_x_coordinate": 0.482,
                        "vector_z_component": 0.94,
                        "vector_x_component": -0.045,
                        "vector_y_component": 0.337,
                        "position_y_coordinate": 0.364 },
                    "left_eye_gaze": {
                        "position_x_coordinate": 0.537,
                        "vector_z_component": 0.871,
                        "vector_x_component": 0.357,
                        "vector_y_component": 0.337,
                        "position_y_coordinate": 0.354 }
                }
            },
            "face_rectangle": {
                "width": 119,
                "top": 376,
                "left": 847,
                "height": 119
            },
            "face_token": "471c6bda6c3f23dd721870897c63e9a8"
        }
    ]
}

3.5 使用net.sf.json jar解析复杂的json

      用json排版工具得到如下图:

这里写图片描述

      解析方法:

/**
     * 把face++返回的json转换为人脸属性对应的list集合
     * @author Ares
     * @param faceMessage face++返回的json
     * @return List<Attributes>
     */
    public List<Attributes> JsontoList(String faceMessage){
        // 使用 net.sf.json.JSONObject 解析json
        JSONObject jsonObject = JSONObject.fromObject(faceMessage);
        List<Attributes> Attributeslist = new ArrayList<Attributes>();
        try {
            JSONArray facesArray = jsonObject.getJSONArray("faces");
            JSONObject faces = null;

            // 循环解析人脸属性特征的值
            for (int i = 0; i < facesArray.size(); i++) {
                faces = facesArray.getJSONObject(i);

                /**
                 * 人脸属性特征 
                 *   gender      --- 性别 
                 *   age         --- 年龄 
                 *   smiling     --- 笑容分析结果
                 *   headpose    --- 人脸姿势分析结果 
                 *   eyestatus   --- 眼睛状态信息
                 *   emotion     --- 情绪识别结果
                 *   facequality --- 人脸质量判断结果
                 *   ethnicity   --- 人种分析结果
                 *   beauty      ---颜值识别结果 
                 *   mouthstatus --- 嘴部状态信息 
                 *   eyegaze     --- 眼球位置与视线方向信息
                 */
                JSONObject attributes = faces.getJSONObject("attributes");

                JSONObject emotion = attributes.getJSONObject("emotion");
                JSONObject beauty = attributes.getJSONObject("beauty");
                JSONObject gender = attributes.getJSONObject("gender");
                JSONObject age = attributes.getJSONObject("age");
                JSONObject mouthstatus = attributes
                        .getJSONObject("mouthstatus");
                JSONObject eyestatus = attributes.getJSONObject("eyestatus");
                JSONObject smile = attributes.getJSONObject("smile");
                JSONObject ethnicity = attributes.getJSONObject("ethnicity");
                JSONObject eyegaze = attributes.getJSONObject("eyegaze");

                JSONObject right_eye_gaze = eyegaze
                        .getJSONObject("right_eye_gaze");
                JSONObject left_eye_gaze = eyegaze
                        .getJSONObject("left_eye_gaze");

                // 把情绪存储到map中
                Map<Double, String> emotionmap = new HashMap<Double, String>();
                emotionmap.put((Double) emotion.get("anger"), "愤怒");
                emotionmap.put((Double) emotion.get("disgust"), "厌恶");
                emotionmap.put((Double) emotion.get("fear"), "恐惧");
                emotionmap.put((Double) emotion.get("happiness"), "高兴");
                emotionmap.put((Double) emotion.get("neutral"), "平静");
                emotionmap.put((Double) emotion.get("sadness"), "伤心");
                emotionmap.put((Double) emotion.get("surprise"), "惊讶");

                Object[] obj = emotionmap.keySet().toArray();
                Arrays.sort(obj);
                System.out.println(obj[obj.length - 1]);

                System.out.println("年龄:" + age.get("value"));
                System.out.println("性别:" + gender.get("value"));
                System.out.println("笑容值:" + smile.get("value") + " " + "笑容阈值:"
                        + smile.get("threshold"));
                System.out.println("情绪:" + emotionmap.get(obj[obj.length - 1])
                        + " " + "" + obj[obj.length - 1]);
                System.out.println("人种:" + ethnicity.get("value"));
                System.out.println("颜值:" + beauty.get("female_score")
                        + "(0~100越大颜值越高)");
                Attributes ats = new Attributes();
                ats.setAge("年龄:" + age.get("value"));
                ats.setSmiling("笑容值:" + smile.get("value") + " " + "笑容阈值:"
                        + smile.get("threshold"));
                ats.setGender("性别:" + gender.get("value"));
                ats.setEmotion("情绪:" + emotionmap.get(obj[obj.length - 1])
                        + " " + "" + obj[obj.length - 1]);
                ats.setEthnicity("人种:" + ethnicity.get("value"));
                ats.setBeauty("颜值:" + beauty.get("female_score")
                        + "(0~100越大颜值越高)");
                ats.setFace_token("人脸标识face_token:" + faces.get("face_token"));
                Attributeslist.add(ats);

                /**
                 * 获取人脸矩形框的位置,包括以下属性。每个属性的值都是整数 top:矩形框左上角像素点的纵坐标
                 * left:矩形框左上角像素点的横坐标 width:矩形框的宽度 height:矩形框的高度
                 */
                JSONObject face_rectangle = faces
                        .getJSONObject("face_rectangle");
                System.out
                        .println("矩形框左上角像素点的纵坐标:" + face_rectangle.get("top"));
                System.out.println("矩形框左上角像素点的横坐标:"
                        + face_rectangle.get("left"));
                System.out.println("矩形框的宽度:" + face_rectangle.get("width"));
                System.out.println("矩形框的高度:" + face_rectangle.get("height"));

                /**
                 * 人脸的标识
                 */
                System.out.println("人脸标识face_token:" + faces.get("face_token"));
                int j = i + 1;
                System.out.println("--------------------------第" + j
                        + "个人结束----------------------------");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        return Attributeslist;
    }

      解析后得到的数据:

image_id:t5DgXIusFEBUtDMKQY4fQg==
request_id:1505356245,91e741a5-2b4c-4c7c-af03-ec6e204546b4
花费的时间:446毫秒
70.593
年龄:18
性别:Male
笑容值:27.335 笑容阈值:30.1
情绪:厌恶 70.593
人种:Asian
颜值:71.794(0~100越大颜值越高)
矩形框左上角像素点的纵坐标:478
矩形框左上角像素点的横坐标:250
矩形框的宽度:165
矩形框的高度:165
人脸标识face_token:4b6ad190af8778df2b96c74e8c84ad41
--------------------------第1个人结束----------------------------
45.183
年龄:37
性别:Male
笑容值:58.645 笑容阈值:30.1
情绪:高兴 45.183
人种:Asian
颜值:56.314(0~100越大颜值越高)
矩形框左上角像素点的纵坐标:376
矩形框左上角像素点的横坐标:847
矩形框的宽度:119
矩形框的高度:119
人脸标识face_token:471c6bda6c3f23dd721870897c63e9a8
--------------------------第2个人结束----------------------------

3.5 显示人脸识别效果

      展示图片,以及人脸识别分析结果:这里主要是利用了java表达式和jstl标准标签库来显示信息的。具体技术可以访问小编的另一系列博客:

【JSTL】JSP标准标签库

      图片不错吧,每个程序员都有一个澎湃的内心。

这里写图片描述

      前台代码:

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="">
    <meta name="author" content="">
    <title>消息提示</title>
    <link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
    <link href="${pageContext.request.contextPath}/css/font-awesome.min.css" rel="stylesheet">
    <link href="${pageContext.request.contextPath}/css/main.css" rel="stylesheet">
    <link href="${pageContext.request.contextPath}/css/animate.css" rel="stylesheet">  
    <link href="${pageContext.request.contextPath}/css/responsive.css" rel="stylesheet">
</head><!--/head-->

<body>

    <section id="home"> 
    <div id="main-slider" class="carousel slide" data-ride="carousel">

        <div class="carousel-inner">
            <div class="item active">
                <img class="img-responsive" src="../images/${file}" alt="slider">                      
                <div class="carousel-caption">
                    <h2>${message} </h2>
                    <c:forEach items="${AttributesList}" var="attributes" >
                        <h4> ${attributes.age}</h4>
                        <h4> ${attributes.gender}</h4>
                        <h4> ${attributes.smiling}</h4>
                        <h4> ${attributes.emotion}</h4>
                        <h4> ${attributes.ethnicity}</h4>
                        <h4> ${attributes.beauty}</h4>
                        <h4> ${attributes.face_token}</h4>
                        <br />
                    </c:forEach>
                        <h4> ${time_used}</h4>
                    <a href="${pageContext.request.contextPath}/AresFaceIndex.jsp">TEST ANGIN <i class="fa fa-angle-right"></i></a>
                </div>
            </div>

        </div>
        </div>      
    </section>

</body>
</html>

3.6 完成

      到现在为止就完成了人脸识别,效果如下:

这里写图片描述

四、小结

      通过这次系统研究,小编也是在其中学到了很多的东西,比如前提向后台servlet发送请求,后台sevlet接收参数,返回参数等。也用到了复杂Json解析,原来自己经常使用jackson来解析,但是这个的前提是要建立对应的类。从小编的json复杂程度来看,如果用Jacson的话,会建立很多的类的,所以小编就使用了其他的方法。

      相信这一篇博客大家会受益匪浅,另外在下一篇的博客中,小编会向大家带来更精彩的人工智能,敬请期待。


http://www.niftyadmin.cn/n/1146078.html

相关文章

DVD电影可轻松拷贝 合法盗版或能开辟新市场

北京时间9月8日消息&#xff0c;据纽约时报报道&#xff0c;曾经推出Real Player媒体播放器的RealNetworks公司将发布新软件RealDVD。该软件可以从DVD碟片中轻松拷贝电影&#xff0c;虽然该软件中有很多限制用来防止拷贝后的电影进行盗版分发&#xff0c;但好莱坞并未对此表态。…

调查显示:IT行业用人占求职需求30%以上

IT行业一贯崇拜技术。想进入IT行业、尤其是想进入IT名企&#xff0c;大多数人认为应聘者没有过硬的专业技能不成&#xff0c;但现在这个观点已经过时。-权威数据IT用人占求职需求三成中华英才网新发布的8月份行业职位需求显示&#xff0c;当月&#xff0c;计算机软件、互联网电…

【java】 Dubbo访问有时候访问到,有时候访问不到问题

Controller找server的时候有多个&#xff0c;这多个中只有95可以&#xff0c;当错误的时候就会对应的其他service的地方&#xff0c;下面报错的是157行&#xff0c;但是在本地的代码157行是注释&#xff0c;所以出现了这种诡异的情况。 可以看出本地是192.168.21.95:61629&…

【Angular2】angular2 select change 事件实现下拉联动

一、实现要求 还用Angular2实现select下拉框联动的效果&#xff1a; 二、实现过程 2.1 项目结构 由于项目是使用了Angular2&#xff0c;前端工程化&#xff0c;组件化&#xff0c;在项目中&#xff0c;分成了下面的五个部分&#xff1a;css、html、routes、spec、component.ts…

MP4播放器抽检75%不合格 容量不足辐射超标

市工商局昨天公布了20批次MP4播放器检测结果&#xff1a;15批次不合格&#xff0c;不合格率高达75%。不合格MP4的主要问题为容量短斤缺两和辐射超标泄漏。相关部门在上海汇金百货有限公司、上海易买得超市有限公司曲阳店、上海联家超市有限公司古北店均发现有问题MP4在销售。检…

【Angular2】搭建开发环境

一、前言 随着前端工程化的浪潮到来&#xff0c;最近公司的新项目需要使用Angular2作为前端的开发语言。当然小编之前是没有接触的&#xff0c;而且Angular2也是在AngularJs的基础上发展出来的。但是官网说他们相同的地方不多&#xff0c;事实证明确实不多。但是经过小编几个月…

软件服务业高速增长 上半年收入3456.7亿

工业和信息化部软件服务业司司长赵小凡9月8日在厦门透露,上半年我国软件服务业保持高速增长态势,软件和信息服务业累计实现收入3456.7亿元。赵小凡在出席此间召开的第二届亚洲-太平洋地区软件园高峰论坛时表示,软件服务业上半年的累计收入同比增长了30.4%,增速比2007年同期提高…

【Angular2】新建Angular2项目

一、前言 相信大家已经看了小编上一篇博客&#xff0c;写的挺好的&#xff0c;《【Angular2】搭建开发环境》&#xff0c;如果你是一个老手&#xff0c;配置好了&#xff0c;怎么可能不去做一个demo呢&#xff1f;对吧&#xff01;&#xff0c;所以这篇博客&#xff0c;小编趁热…