• java 开发 face++ 人脸特征识别系统


    首先要在 face++ 注册一个账号,并且创建一个应用,拿到 api key 和 api secret;

    下载 java 接入工具,一个 jar 包:https://github.com/FacePlusPlus/facepp-java-sdk

    请求返回的数据是 json 格式,需要导入 json 解析包:

    commons-beanutils-1.8.3.jar
    commons-lang-2.5.jar
    commons-collections-3.2.2.jar
    ezmorph-1.0.6.jar
    json-lib-2.3-jdk15.jar

    图片上传类:FileUpLoad.java

     1 package com.krry;
     2 
     3 import java.io.File;
     4 import java.io.FileOutputStream;
     5 import java.io.IOException;
     6 import java.io.InputStream;
     7 import java.util.List;
     8 import java.util.UUID;
     9 import javax.servlet.annotation.WebServlet;
    10 import javax.servlet.http.HttpServlet;
    11 import javax.servlet.http.HttpServletRequest;
    12 import javax.servlet.http.HttpServletResponse;
    13 
    14 import org.apache.commons.fileupload.FileItem;
    15 import org.apache.commons.fileupload.FileItemFactory;
    16 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    17 import org.apache.commons.fileupload.servlet.ServletFileUpload;
    18 
    19 /**
    20  *  FileUpLoad
    21  * @author krry
    22  *
    23  */
    24 @WebServlet(name="fileUp",urlPatterns={"/show"})
    25 public class FileUpLoad extends HttpServlet{
    26     
    27     private static final long serialVersionUID = 1L;
    28 
    29     @Override
    30     public void service(HttpServletRequest request,HttpServletResponse response) throws IOException{
    31         //判断是不是文件上传,根据请求包里面的内容是否为二进制提交的上传的文件 true/false
    32         boolean isMultPart = ServletFileUpload.isMultipartContent(request);
    33         if(isMultPart){
    34             //创建文件上传工厂
    35             FileOutputStream out = null;
    36             InputStream in = null;
    37             try {
    38                  FileItemFactory factory = new DiskFileItemFactory();
    39                  //创建容器文件类,负责处理上传的文件数据
    40                 ServletFileUpload upload = new ServletFileUpload(factory);
    41                  //解析上传文件,其实就是解析表单传过来的数据
    42                 List<FileItem> fileItems = upload.parseRequest(request);
    43                 //只需要拿一张图片
    44                 in = fileItems.get(0).getInputStream();
    45                 //获取源文件名
    46                 String Ofilename = fileItems.get(0).getName();
    47                 //拿到后缀名
    48                 String ext = Ofilename.substring(Ofilename.indexOf("."), Ofilename.length());
    49                 //拿到一个目录,绝对地址
    50                 String path =request.getSession().getServletContext().getRealPath("/");
    51                 //生成一个唯一的名字
    52                 String fileName = UUID.randomUUID().toString() + ext;
    53                 //定义上传目录
    54                 String dirPath = path+"/upload";
    55                 File dirFile = new File(dirPath);
    56                 //如果此文件夹不存在
    57                 if(!dirFile.exists()){
    58                     dirFile.mkdirs();//创建此文件夹
    59                 }
    60                 //配置文件路径
    61                 String filePath = path+"/upload/"+fileName;
    62                 //输出流
    63                 out = new FileOutputStream(filePath);
    64                 //边读取边编写 字节流
    65                 byte[] b = new byte[1024];
    66                 int length = 0;
    67                 while((length = in.read(b)) != -1){  //读到字节数组里面去
    68                     out.write(b,0,length);   //从0开始写,写你读了多少
    69                 }
    70                 //放在request作用域里
    71                 request.setAttribute("imgSrc", filePath);
    72                 request.setAttribute("imgSrcPage", "upload/"+fileName);
    73                 //请求转发,转发到另一个servlet
    74                 request.getRequestDispatcher("showImage").forward(request, response);
    75             } catch (Exception e) {
    76                 
    77                 e.printStackTrace();
    78             }finally{
    79                 out.close();
    80                 in.close();
    81             }
    82         }
    83     }
    84 
    85 }

    人脸识别类:Analysis.java

    这里返回一个 json 字符串,放到作用域,在前台获取

      1 package com.krry;
      2 
      3 import java.io.ByteArrayOutputStream;
      4 import java.io.DataOutputStream;
      5 import java.io.File;
      6 import java.io.FileInputStream;
      7 import java.io.IOException;
      8 import java.io.InputStream;
      9 import java.net.HttpURLConnection;
     10 import java.net.URL;
     11 import java.net.URLEncoder;
     12 import java.util.ArrayList;
     13 import java.util.Collections;
     14 import java.util.HashMap;
     15 import java.util.Iterator;
     16 import java.util.List;
     17 import java.util.Map;
     18 import java.util.Random;
     19 import java.util.TreeMap;
     20 
     21 import javax.net.ssl.SSLException;
     22 import javax.servlet.annotation.WebServlet;
     23 import javax.servlet.http.HttpServlet;
     24 import javax.servlet.http.HttpServletRequest;
     25 import javax.servlet.http.HttpServletResponse;
     26 
     27 import net.sf.json.JSONArray;
     28 import net.sf.json.JSONObject;
     29 
     30 /**
     31  *  analysis
     32  * @author krry
     33  * String 转json 需要的jar包:版本不能弄错
     34  * commons-beanutils-1.8.3.jar 
     35     commons-lang-2.5.jar
     36     commons-collections-3.2.2.jar
     37     ezmorph-1.0.6.jar 
     38     json-lib-2.3-jdk15.jar 
     39  */
     40 @WebServlet(name="analysis",urlPatterns={"/showImage"})
     41 public class Analysis extends HttpServlet{
     42     
     43     private static final long serialVersionUID = 1L;
     44     
     45     @Override
     46     public void service(HttpServletRequest request,HttpServletResponse response) throws IOException{
     47         
     48         //获取上传的图片地址
     49         String imgPath = request.getAttribute("imgSrc").toString();
     50         File file = new File(imgPath);
     51         byte[] buff = getBytesFromFile(file);
     52         String url = "https://api-cn.faceplusplus.com/facepp/v3/detect";
     53         HashMap<String, String> map = new HashMap<String, String>();
     54         HashMap<String, byte[]> byteMap = new HashMap<String, byte[]>();
     55         map.put("api_key", "15N9eBF_ieE-N2nvI7oK_A9anh2meuUS");
     56         map.put("api_secret", "cBnvsIAo8VaOj53lXCWlpuOSd0NrsFif");
     57         map.put("return_landmark", "1");
     58         map.put("return_attributes", "gender,age,smiling,headpose,facequality,blur,eyestatus,emotion,ethnicity,beauty,mouthstatus,eyegaze,skinstatus");
     59         byteMap.put("image_file", buff);
     60         try{
     61             byte[] bacd = post(url, map, byteMap);
     62             String str = new String(bacd);
     63             
     64             JSONObject json = JSONObject.fromObject(str);
     65             JSONArray faces = json.getJSONArray("faces");
     66             
     67             //解析失败
     68             if(str.indexOf("error_message") != -1 || faces.size() == 0){
     69                 request.getSession().setAttribute("error", "解析失败,请重新选择");
     70                 //重定向到首页
     71                 response.sendRedirect("index.jsp");
     72             }else{
     73                 //将人脸信息字符串str信息放到作用域
     74                 request.setAttribute("face", str);
     75                 //请求转发,返回到页面
     76                 request.getRequestDispatcher("showImage.jsp").forward(request, response);
     77             }
     78         }catch (Exception e) {
     79             e.printStackTrace();
     80         }
     81         
     82     }
     83     
     84     
     85     private final static int CONNECT_TIME_OUT = 30000;
     86     private final static int READ_OUT_TIME = 50000;
     87     private static String boundaryString = getBoundary();
     88     
     89     protected static byte[] post(String url, HashMap<String, String> map, HashMap<String, byte[]> fileMap) throws Exception {
     90         HttpURLConnection conne;
     91         URL url1 = new URL(url);
     92         conne = (HttpURLConnection) url1.openConnection();
     93         conne.setDoOutput(true);
     94         conne.setUseCaches(false);
     95         conne.setRequestMethod("POST");
     96         conne.setConnectTimeout(CONNECT_TIME_OUT);
     97         conne.setReadTimeout(READ_OUT_TIME);
     98         conne.setRequestProperty("accept", "*/*");
     99         conne.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundaryString);
    100         conne.setRequestProperty("connection", "Keep-Alive");
    101         conne.setRequestProperty("user-agent", "Mozilla/4.0 (compatible;MSIE 6.0;Windows NT 5.1;SV1)");
    102         DataOutputStream obos = new DataOutputStream(conne.getOutputStream());
    103         Iterator iter = map.entrySet().iterator();
    104         while(iter.hasNext()){
    105             Map.Entry<String, String> entry = (Map.Entry) iter.next();
    106             String key = entry.getKey();
    107             String value = entry.getValue();
    108             obos.writeBytes("--" + boundaryString + "
    ");
    109             obos.writeBytes("Content-Disposition: form-data; name="" + key
    110                     + ""
    ");
    111             obos.writeBytes("
    ");
    112             obos.writeBytes(value + "
    ");
    113         }
    114         if(fileMap != null && fileMap.size() > 0){
    115             Iterator fileIter = fileMap.entrySet().iterator();
    116             while(fileIter.hasNext()){
    117                 Map.Entry<String, byte[]> fileEntry = (Map.Entry<String, byte[]>) fileIter.next();
    118                 obos.writeBytes("--" + boundaryString + "
    ");
    119                 obos.writeBytes("Content-Disposition: form-data; name="" + fileEntry.getKey()
    120                         + ""; filename="" + encode(" ") + ""
    ");
    121                 obos.writeBytes("
    ");
    122                 obos.write(fileEntry.getValue());
    123                 obos.writeBytes("
    ");
    124             }
    125         }
    126         obos.writeBytes("--" + boundaryString + "--" + "
    ");
    127         obos.writeBytes("
    ");
    128         obos.flush();
    129         obos.close();
    130         InputStream ins = null;
    131         int code = conne.getResponseCode();
    132         try{
    133             if(code == 200){
    134                 ins = conne.getInputStream();
    135             }else{
    136                 ins = conne.getErrorStream();
    137             }
    138         }catch (SSLException e){
    139             e.printStackTrace();
    140             return new byte[0];
    141         }
    142         ByteArrayOutputStream baos = new ByteArrayOutputStream();
    143         byte[] buff = new byte[4096];
    144         int len;
    145         while((len = ins.read(buff)) != -1){
    146             baos.write(buff, 0, len);
    147         }
    148         byte[] bytes = baos.toByteArray();
    149         ins.close();
    150         return bytes;
    151     }
    152     private static String getBoundary() {
    153         StringBuilder sb = new StringBuilder();
    154         Random random = new Random();
    155         for(int i = 0; i < 32; ++i) {
    156             sb.append("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-".charAt(random.nextInt("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_".length())));
    157         }
    158         return sb.toString();
    159     }
    160     private static String encode(String value) throws Exception{
    161         return URLEncoder.encode(value, "UTF-8");
    162     }
    163     
    164     public static byte[] getBytesFromFile(File f) {
    165         if (f == null) {
    166             return null;
    167         }
    168         try {
    169             FileInputStream stream = new FileInputStream(f);
    170             ByteArrayOutputStream out = new ByteArrayOutputStream(1000);
    171             byte[] b = new byte[1000];
    172             int n;
    173             while ((n = stream.read(b)) != -1)
    174                 out.write(b, 0, n);
    175             stream.close();
    176             out.close();
    177             return out.toByteArray();
    178         } catch (IOException e) {
    179         }
    180         return null;
    181     }
    182     
    183 
    184 }

    解析 json 字符串,先转换成 json 格式,json 数组,一个个获取人脸属性

      1 <%@page import="net.sf.json.JSONObject"%>
      2 <%@page import="net.sf.json.JSONArray"%>
      3 <%@ page language="java" import="java.io.File" pageEncoding="utf-8"%>
      4 <%@page import="java.math.BigDecimal"%>
      5 <%@ page import="java.util.*" %>
      6 <%
      7 
      8     String path = request.getContextPath();
      9     int port = request.getServerPort();
     10     String basePath = null; 
     11     if(port==80){
     12         basePath = request.getScheme()+"://"+request.getServerName()+path;
     13     }else{
     14         basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path;
     15     }
     16     pageContext.setAttribute("basePath", basePath);
     17     
     18     
     19     Object str = request.getAttribute("face");
     20     JSONObject json = JSONObject.fromObject(str);
     21     JSONArray faces = json.getJSONArray("faces");
     22     StringBuffer strBuff = new StringBuffer();
     23     //识别出人脸的个数
     24     int length = faces.size();
     25     
     26     //识别出多少个人脸,就是循环多少次
     27     for(int i = 0;i < length;i++){
     28     
     29         JSONObject face = faces.getJSONObject(i);  //拿到第i+1个人脸部信息
     30         JSONObject attribute = face.getJSONObject("attributes");//拿到脸部属性
     31         
     32         //年龄
     33         JSONObject age = attribute.getJSONObject("age");
     34         int ageValue = age.getInt("value");
     35         
     36         //性别
     37         JSONObject gender = attribute.getJSONObject("gender");
     38         String sex = gender.getString("value");
     39         if(sex.equals("Male")) sex = "";
     40         else sex = "";
     41         
     42         //人种
     43         JSONObject ethnicity = attribute.getJSONObject("ethnicity");
     44         String races = ethnicity.getString("value");
     45         if(races.equals("Asian")) races = "亚洲人";
     46         else if(races.equals("White")) races = "白人";
     47         else races = "黑人";
     48         
     49         //微笑程度
     50         JSONObject smile = attribute.getJSONObject("smile");
     51         String smileRange = String.format("%.2f",smile.getDouble("value"));
     52         
     53         //表情
     54         JSONObject emotion = attribute.getJSONObject("emotion");
     55         Map<String,Double> mapp = new TreeMap<String,Double>();
     56         //装配表情信息到map
     57         double sadness = emotion.getDouble("sadness");
     58         mapp.put("伤心", sadness);
     59         double neutral = emotion.getDouble("neutral");
     60         mapp.put("平静", neutral);
     61         double disgust = emotion.getDouble("disgust");
     62         mapp.put("厌恶", disgust);
     63         double anger = emotion.getDouble("anger");
     64         mapp.put("愤怒", anger);
     65         double happiness = emotion.getDouble("happiness");
     66         mapp.put("高兴", happiness);
     67         double surprise = emotion.getDouble("surprise");
     68         mapp.put("惊讶", surprise);
     69         double fear = emotion.getDouble("fear");
     70         mapp.put("恐惧", fear);
     71         
     72         //利用list取最大值
     73         List<Double> listmap = new ArrayList<Double>();
     74         for(String key:mapp.keySet()){
     75             listmap.add(mapp.get(key));
     76         }
     77         //取到最大值
     78         double valueMax = Collections.max(listmap);
     79         //根据map的value获取map的key  
     80         String emotionMax = "";  
     81         for (Map.Entry<String, Double> entry : mapp.entrySet()) {  
     82             if(valueMax == entry.getValue()){  
     83                 emotionMax = entry.getKey();  
     84             }
     85         }
     86         
     87         //颜值分数
     88         JSONObject beauty = attribute.getJSONObject("beauty");
     89         String beautys = "";
     90         if(sex.equals("")) beautys = String.format("%.2f",beauty.getDouble("male_score"));
     91         else beautys = String.format("%.2f",beauty.getDouble("female_score"));
     92         
     93         //面部状态
     94         JSONObject skinstatus = attribute.getJSONObject("skinstatus");
     95         Map<String,String> mapSkin = new TreeMap<String,String>();
     96         //装配信息到map
     97         double health = skinstatus.getDouble("health");
     98         mapSkin.put("健康指数", String.format("%.2f",health));
     99         double stain = skinstatus.getDouble("stain");
    100         mapSkin.put("色斑指数", String.format("%.2f",stain));
    101         double acne = skinstatus.getDouble("acne");
    102         mapSkin.put("青春痘指数", String.format("%.2f",acne));
    103         double dark_circle = skinstatus.getDouble("dark_circle");
    104         mapSkin.put("黑眼圈指数", String.format("%.2f",dark_circle));
    105         
    106         strBuff.append("<br>");
    107         strBuff.append("<span>年龄:").append(ageValue).append("岁</span>");
    108         strBuff.append("<span>性别:").append(sex).append("</span>");
    109         strBuff.append("<br>").append("<br>");
    110         strBuff.append("<span>人种:").append(races+"</span>");
    111         strBuff.append("<span>微笑程度:").append(smileRange+"%</span>");
    112         strBuff.append("<br>").append("<br>");
    113         strBuff.append("<span>表情:").append(emotionMax+"</span>");
    114         strBuff.append("<span>颜值分数:").append(beautys+"</span>");
    115         strBuff.append("<br>").append("<br>");
    116         int counts = 0;
    117         for(String key:mapSkin.keySet()){
    118             counts++;
    119             strBuff.append("<span>"+key+"").append(mapSkin.get(key)+"</span>");
    120             if(counts % 2 == 0) strBuff.append("<br>").append("<br>");
    121         }
    122              
    123         strBuff.append("<br>");
    124              
    125     }
    126       
    127       
    128 
    129 %>
    130 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    131 <html>
    132   <head>
    133     
    134     <title> Java开发人脸特征识别系统  --krry</title>
    135     
    136     <meta http-equiv="pragma" content="no-cache">
    137     <meta http-equiv="cache-control" content="no-cache">
    138     <meta http-equiv="expires" content="0">    
    139     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    140     <meta http-equiv="description" content="This is my page">
    141 
    142     <style type="text/css">
    143          *{padding:0px;margin:0px;}
    144          body{background: #FFF;background:url("images/78788.jpg");background-size:cover;}
    145          .a_btn{text-decoration:none;font-family:"幼圆";background:#fff;transition:.6s;color:#f60;cursor:pointer;width:100px;height:40px;border-radius:10px;display: inline-block;text-align:center;line-height:40px;}
    146         .aa{position: absolute;left: 48px;top: 31px;}
    147         .a_btn:hover{background:red;color:#fff;transition:.6s;}
    148          .clear{clear:both;}
    149          .title{margin-top: 25px;font-size:48px;font-family:"幼圆";color: #ff7272;text-shadow: 1px 1px 3px #ff3737;text-align:center;line-height:45px;}
    150          .content{margin:0 auto;width:900px;}
    151           .content .img{float:left;margin-top:30px;}
    152           .content .img img{border-radius:10px;}
    153          .content .describe{margin-top:30px;width:500px;color:#000;font-family:"幼圆";font-size:18px;float:right;}
    154          .content .describe span{width: 190px;display: inline-block;}
    155     </style>
    156 
    157   </head>
    158   
    159   <body>
    160           <div class="aa"><a class="a_btn" href="${basePath}">返回</a></div>
    161           <div class="title">人脸识别结果</div>
    162           <div class="content">
    163             <div class = "img">
    164                <img style="float:left" width="350" src="${imgSrcPage}" />
    165             </div>
    166             <div style="float:right" class="describe"><%=strBuff.toString() %></div>
    167             <div class="clear"></div>
    168         </div>
    169   </body>
    170 </html>

    首页:

     1 <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
     2 
     3 <%
     4 
     5     Object ermsg = request.getSession().getAttribute("error");
     6     StringBuffer strBuff = new StringBuffer();
     7     if(ermsg != null){
     8         //清除作用域
     9         request.getSession().removeAttribute("error");
    10         strBuff.append("loading('"+ermsg+"',4)");
    11     }
    12 %>
    13 
    14 <!doctype html>
    15 <html>
    16     <head>
    17        <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
    18        <meta name="keywords" content="关键词,关键词">
    19        <meta name="description" content="">
    20        <link rel="stylesheet" type="text/css" href="css/sg.css" />
    21        <link rel="stylesheet" type="text/css" href="css/sg/css/animate.css" />
    22        <link rel="stylesheet" type="text/css" href="css/sg/css/sg.css" />
    23        
    24        <title> Java开发人脸特征识别系统  --krry</title>
    25        <style type="text/css">
    26            *{padding:0px;margin:0px;}
    27            body{background:url("images/5.jpg");background-size:cover;font-size:18px;font-family:"微软雅黑";color:#666;}
    28            img{border:none;}
    29            h1{font-size:24px;}
    30            .title{margin-top: 30px;font-size:48px;font-family:"幼圆";color: #ff7272;text-shadow: 1px 1px 3px #ff3737;text-align:center;line-height:45px;}
    31            .box{margin:100px auto;text-align:center;}
    32            .box .b_btn{width:100px;height:40px;background:#fff;transition:.6s;font-size:16px;font-family:"微软雅黑";display:block;margin:54px auto;text-align:center;
    33                        cursor:pointer;line-height:40px;text-decoration:none;color:#F60;border:1px;border-radius:12px}
    34               .box .b_btn:hover{background:red;color:#fff;transition:.6s;}
    35               .busbu{top:0;background:rgba(0, 0, 0, 0.2);display:none;width:100%;height:100%;position:absolute;z-index:1000;}
    36        </style>
    37     </head>
    38 
    39 <body>
    40    <!--action  提交的路径  method:post(打包传输) get(明文传输) enctype(采用二进制)-->
    41    <form action="show" method="post" enctype="multipart/form-data">
    42    <div class="box">
    43        <div class="title">人脸特征识别系统 --krry</div>
    44        <input type="file" id="fileChoice" accept="image/jpeg,image/png" style="display:none" name="files"/>
    45        <a class="b_btn" href="javascript:void(0);" onclick="choice()">选择照片</a>
    46        <input type="button" value="提交解析" class="b_btn" id="but"/>
    47        <input type="submit" class="sub_btn" style="display:none;"/> 
    48    </div>
    49    </form>
    50    <div class="busbu"></div>
    51      <script src="js/jquery-1.11.3.min.js"></script>
    52     <script src="js/sg.js"></script>
    53     <script src="js/sgutil.js"></script>
    54     <script type="text/javascript" src="css/sg/tz_util.js"></script>
    55     <script type="text/javascript" src="css/sg/sg.js"></script>
    56     <script type="text/javascript">
    57     <%=strBuff.toString() %>
    58     //选择照片
    59     function choice(){
    60        //js 弱类型  快速定位
    61        var choose = document.getElementById("fileChoice");
    62        choose.click();
    63     }
    64     $("#but").click(function(){
    65         if($("#fileChoice").val()){//如果选择了照片
    66             $(".sub_btn").click();
    67             $(".busbu").show();
    68             loading("正在解析",900);//再展示
    69         }else{
    70             $.tmDialog.alert({open:"top",content:"请先选择一张照片",title:"Krry温馨提醒"});
    71         }
    72     });
    73       
    74 </script>
    75 </body>
    76 
    77 </html>

    需要注意的点,json 字符串的转换和解析,获取 json 中人脸属性的方法 

    git:https://github.com/Krryxa/face

  • 相关阅读:
    第四周技术博客发表 线性表
    《我是一只IT小小鸟》读后感
    java9最新发布
    MD5进行解密操作
    MD5进行加密操作
    定时器的编写
    mybatis查询修改同时操作
    java8的版本对组合式异步编程
    linux中安装gcc
    linux不能上网问题
  • 原文地址:https://www.cnblogs.com/ainyi/p/8584513.html
Copyright © 2020-2023  润新知