首先要在 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

 package com.krry;

 import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload; /**
* FileUpLoad
* @author krry
*
*/
@WebServlet(name="fileUp",urlPatterns={"/show"})
public class FileUpLoad extends HttpServlet{ private static final long serialVersionUID = 1L; @Override
public void service(HttpServletRequest request,HttpServletResponse response) throws IOException{
//判断是不是文件上传,根据请求包里面的内容是否为二进制提交的上传的文件 true/false
boolean isMultPart = ServletFileUpload.isMultipartContent(request);
if(isMultPart){
//创建文件上传工厂
FileOutputStream out = null;
InputStream in = null;
try {
FileItemFactory factory = new DiskFileItemFactory();
//创建容器文件类,负责处理上传的文件数据
ServletFileUpload upload = new ServletFileUpload(factory);
//解析上传文件,其实就是解析表单传过来的数据
List<FileItem> fileItems = upload.parseRequest(request);
//只需要拿一张图片
in = fileItems.get(0).getInputStream();
//获取源文件名
String Ofilename = fileItems.get(0).getName();
//拿到后缀名
String ext = Ofilename.substring(Ofilename.indexOf("."), Ofilename.length());
//拿到一个目录,绝对地址
String path =request.getSession().getServletContext().getRealPath("/");
//生成一个唯一的名字
String fileName = UUID.randomUUID().toString() + ext;
//定义上传目录
String dirPath = path+"/upload";
File dirFile = new File(dirPath);
//如果此文件夹不存在
if(!dirFile.exists()){
dirFile.mkdirs();//创建此文件夹
}
//配置文件路径
String filePath = path+"/upload/"+fileName;
//输出流
out = new FileOutputStream(filePath);
//边读取边编写 字节流
byte[] b = new byte[1024];
int length = 0;
while((length = in.read(b)) != -1){ //读到字节数组里面去
out.write(b,0,length); //从0开始写,写你读了多少
}
//放在request作用域里
request.setAttribute("imgSrc", filePath);
request.setAttribute("imgSrcPage", "upload/"+fileName);
//请求转发,转发到另一个servlet
request.getRequestDispatcher("showImage").forward(request, response);
} catch (Exception e) { e.printStackTrace();
}finally{
out.close();
in.close();
}
}
} }

人脸识别类:Analysis.java

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

 package com.krry;

 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.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.TreeMap; import javax.net.ssl.SSLException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import net.sf.json.JSONArray;
import net.sf.json.JSONObject; /**
* analysis
* @author krry
* String 转json 需要的jar包:版本不能弄错
* 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
*/
@WebServlet(name="analysis",urlPatterns={"/showImage"})
public class Analysis extends HttpServlet{ private static final long serialVersionUID = 1L; @Override
public void service(HttpServletRequest request,HttpServletResponse response) throws IOException{ //获取上传的图片地址
String imgPath = request.getAttribute("imgSrc").toString();
File file = new File(imgPath);
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", "15N9eBF_ieE-N2nvI7oK_A9anh2meuUS");
map.put("api_secret", "cBnvsIAo8VaOj53lXCWlpuOSd0NrsFif");
map.put("return_landmark", "1");
map.put("return_attributes", "gender,age,smiling,headpose,facequality,blur,eyestatus,emotion,ethnicity,beauty,mouthstatus,eyegaze,skinstatus");
byteMap.put("image_file", buff);
try{
byte[] bacd = post(url, map, byteMap);
String str = new String(bacd); JSONObject json = JSONObject.fromObject(str);
JSONArray faces = json.getJSONArray("faces"); //解析失败
if(str.indexOf("error_message") != -1 || faces.size() == 0){
request.getSession().setAttribute("error", "解析失败,请重新选择");
//重定向到首页
response.sendRedirect("index.jsp");
}else{
//将人脸信息字符串str信息放到作用域
request.setAttribute("face", str);
//请求转发,返回到页面
request.getRequestDispatcher("showImage.jsp").forward(request, response);
}
}catch (Exception e) {
e.printStackTrace();
} } private final static int CONNECT_TIME_OUT = 30000;
private final static int READ_OUT_TIME = 50000;
private static String boundaryString = getBoundary(); 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;
}
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();
}
private static String encode(String value) throws Exception{
return URLEncoder.encode(value, "UTF-8");
} 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 字符串,先转换成 json 格式,json 数组,一个个获取人脸属性

 <%@page import="net.sf.json.JSONObject"%>
<%@page import="net.sf.json.JSONArray"%>
<%@ page language="java" import="java.io.File" pageEncoding="utf-8"%>
<%@page import="java.math.BigDecimal"%>
<%@ page import="java.util.*" %>
<% String path = request.getContextPath();
int port = request.getServerPort();
String basePath = null;
if(port==80){
basePath = request.getScheme()+"://"+request.getServerName()+path;
}else{
basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path;
}
pageContext.setAttribute("basePath", basePath); Object str = request.getAttribute("face");
JSONObject json = JSONObject.fromObject(str);
JSONArray faces = json.getJSONArray("faces");
StringBuffer strBuff = new StringBuffer();
//识别出人脸的个数
int length = faces.size(); //识别出多少个人脸,就是循环多少次
for(int i = 0;i < length;i++){ JSONObject face = faces.getJSONObject(i); //拿到第i+1个人脸部信息
JSONObject attribute = face.getJSONObject("attributes");//拿到脸部属性 //年龄
JSONObject age = attribute.getJSONObject("age");
int ageValue = age.getInt("value"); //性别
JSONObject gender = attribute.getJSONObject("gender");
String sex = gender.getString("value");
if(sex.equals("Male")) sex = "男";
else sex = "女"; //人种
JSONObject ethnicity = attribute.getJSONObject("ethnicity");
String races = ethnicity.getString("value");
if(races.equals("Asian")) races = "亚洲人";
else if(races.equals("White")) races = "白人";
else races = "黑人"; //微笑程度
JSONObject smile = attribute.getJSONObject("smile");
String smileRange = String.format("%.2f",smile.getDouble("value")); //表情
JSONObject emotion = attribute.getJSONObject("emotion");
Map<String,Double> mapp = new TreeMap<String,Double>();
//装配表情信息到map
double sadness = emotion.getDouble("sadness");
mapp.put("伤心", sadness);
double neutral = emotion.getDouble("neutral");
mapp.put("平静", neutral);
double disgust = emotion.getDouble("disgust");
mapp.put("厌恶", disgust);
double anger = emotion.getDouble("anger");
mapp.put("愤怒", anger);
double happiness = emotion.getDouble("happiness");
mapp.put("高兴", happiness);
double surprise = emotion.getDouble("surprise");
mapp.put("惊讶", surprise);
double fear = emotion.getDouble("fear");
mapp.put("恐惧", fear); //利用list取最大值
List<Double> listmap = new ArrayList<Double>();
for(String key:mapp.keySet()){
listmap.add(mapp.get(key));
}
//取到最大值
double valueMax = Collections.max(listmap);
//根据map的value获取map的key
String emotionMax = "";
for (Map.Entry<String, Double> entry : mapp.entrySet()) {
if(valueMax == entry.getValue()){
emotionMax = entry.getKey();
}
} //颜值分数
JSONObject beauty = attribute.getJSONObject("beauty");
String beautys = "";
if(sex.equals("男")) beautys = String.format("%.2f",beauty.getDouble("male_score"));
else beautys = String.format("%.2f",beauty.getDouble("female_score")); //面部状态
JSONObject skinstatus = attribute.getJSONObject("skinstatus");
Map<String,String> mapSkin = new TreeMap<String,String>();
//装配信息到map
double health = skinstatus.getDouble("health");
mapSkin.put("健康指数", String.format("%.2f",health));
double stain = skinstatus.getDouble("stain");
mapSkin.put("色斑指数", String.format("%.2f",stain));
double acne = skinstatus.getDouble("acne");
mapSkin.put("青春痘指数", String.format("%.2f",acne));
double dark_circle = skinstatus.getDouble("dark_circle");
mapSkin.put("黑眼圈指数", String.format("%.2f",dark_circle)); strBuff.append("<br>");
strBuff.append("<span>年龄:").append(ageValue).append("岁</span>");
strBuff.append("<span>性别:").append(sex).append("</span>");
strBuff.append("<br>").append("<br>");
strBuff.append("<span>人种:").append(races+"</span>");
strBuff.append("<span>微笑程度:").append(smileRange+"%</span>");
strBuff.append("<br>").append("<br>");
strBuff.append("<span>表情:").append(emotionMax+"</span>");
strBuff.append("<span>颜值分数:").append(beautys+"</span>");
strBuff.append("<br>").append("<br>");
int counts = 0;
for(String key:mapSkin.keySet()){
counts++;
strBuff.append("<span>"+key+":").append(mapSkin.get(key)+"</span>");
if(counts % 2 == 0) strBuff.append("<br>").append("<br>");
} strBuff.append("<br>"); } %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head> <title> Java开发人脸特征识别系统 --krry</title> <meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page"> <style type="text/css">
*{padding:0px;margin:0px;}
body{background: #FFF;background:url("images/78788.jpg");background-size:cover;}
.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;}
.aa{position: absolute;left: 48px;top: 31px;}
.a_btn:hover{background:red;color:#fff;transition:.6s;}
.clear{clear:both;}
.title{margin-top: 25px;font-size:48px;font-family:"幼圆";color: #ff7272;text-shadow: 1px 1px 3px #ff3737;text-align:center;line-height:45px;}
.content{margin:0 auto;width:900px;}
.content .img{float:left;margin-top:30px;}
.content .img img{border-radius:10px;}
.content .describe{margin-top:30px;width:500px;color:#000;font-family:"幼圆";font-size:18px;float:right;}
.content .describe span{width: 190px;display: inline-block;}
</style> </head> <body>
<div class="aa"><a class="a_btn" href="${basePath}">返回</a></div>
<div class="title">人脸识别结果</div>
<div class="content">
<div class = "img">
<img style="float:left" width="350" src="${imgSrcPage}" />
</div>
<div style="float:right" class="describe"><%=strBuff.toString() %></div>
<div class="clear"></div>
</div>
</body>
</html>

首页:

 <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

 <%

     Object ermsg = request.getSession().getAttribute("error");
StringBuffer strBuff = new StringBuffer();
if(ermsg != null){
//清除作用域
request.getSession().removeAttribute("error");
strBuff.append("loading('"+ermsg+"',4)");
}
%> <!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<meta name="keywords" content="关键词,关键词">
<meta name="description" content="">
<link rel="stylesheet" type="text/css" href="css/sg.css" />
<link rel="stylesheet" type="text/css" href="css/sg/css/animate.css" />
<link rel="stylesheet" type="text/css" href="css/sg/css/sg.css" /> <title> Java开发人脸特征识别系统 --krry</title>
<style type="text/css">
*{padding:0px;margin:0px;}
body{background:url("images/5.jpg");background-size:cover;font-size:18px;font-family:"微软雅黑";color:#666;}
img{border:none;}
h1{font-size:24px;}
.title{margin-top: 30px;font-size:48px;font-family:"幼圆";color: #ff7272;text-shadow: 1px 1px 3px #ff3737;text-align:center;line-height:45px;}
.box{margin:100px auto;text-align:center;}
.box .b_btn{width:100px;height:40px;background:#fff;transition:.6s;font-size:16px;font-family:"微软雅黑";display:block;margin:54px auto;text-align:center;
cursor:pointer;line-height:40px;text-decoration:none;color:#F60;border:1px;border-radius:12px}
.box .b_btn:hover{background:red;color:#fff;transition:.6s;}
.busbu{top:0;background:rgba(0, 0, 0, 0.2);display:none;width:100%;height:100%;position:absolute;z-index:1000;}
</style>
</head> <body>
<!--action 提交的路径 method:post(打包传输) get(明文传输) enctype(采用二进制)-->
<form action="show" method="post" enctype="multipart/form-data">
<div class="box">
<div class="title">人脸特征识别系统 --krry</div>
<input type="file" id="fileChoice" accept="image/jpeg,image/png" style="display:none" name="files"/>
<a class="b_btn" href="javascript:void(0);" onclick="choice()">选择照片</a>
<input type="button" value="提交解析" class="b_btn" id="but"/>
<input type="submit" class="sub_btn" style="display:none;"/>
</div>
</form>
<div class="busbu"></div>
<script src="js/jquery-1.11.3.min.js"></script>
<script src="js/sg.js"></script>
<script src="js/sgutil.js"></script>
<script type="text/javascript" src="css/sg/tz_util.js"></script>
<script type="text/javascript" src="css/sg/sg.js"></script>
<script type="text/javascript">
<%=strBuff.toString() %>
//选择照片
function choice(){
//js 弱类型 快速定位
var choose = document.getElementById("fileChoice");
choose.click();
}
$("#but").click(function(){
if($("#fileChoice").val()){//如果选择了照片
$(".sub_btn").click();
$(".busbu").show();
loading("正在解析",900);//再展示
}else{
$.tmDialog.alert({open:"top",content:"请先选择一张照片",title:"Krry温馨提醒"});
}
}); </script>
</body> </html>

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

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

java 开发 face++ 人脸特征识别系统的更多相关文章

  1. 分享:Java 开发精美艺术二维码

    博客地址:https://ainyi.com/58 Java 开发精美艺术二维码 看到网络上各种各样的二维码层出不穷,好像很炫酷的样子,一时兴起,我也要制作这种炫酷二维码效果 例如: 根据以往例子 根 ...

  2. Java开发前期准备工作

    配置Java开发环境变量 在"系统变量"中设置3项属性,JAVA_HOME, PATH, CLASSPATH. 变量设置参数如下: 变量名:JAVA_HOME 变量值:C:\Pro ...

  3. Win7 32位系统下Java开发环境的安装及配置

    目录: Java JDK安装. Java JDK系统环境的配置. 配置常见问题的解决. Java JDK的安装 Java Jdk(Java Development Kit)Java开发不可缺少的环境, ...

  4. Java开发笔记(八十一)如何使用系统自带的注解

    之前介绍继承的时候,提到对于子类而言,父类的普通方法可以重写也可以不重写,但是父类的抽象方法是必须重写的,如果不重写,编译器就直接在子类名称那里显示红叉报错.例如,以前演示抽象类用法之时,曾经把Chi ...

  5. Nodejs开发人脸识别系统-教你实现高大上的人工智能

    Nodejs开发人脸识别系统-教你实现高大上的人工智能   一.缘起缘生 前段时间有个H5很火,上传个头像就可以显示自己穿军装的样子,无意中看到了一篇帖子叫 全民刷军装背后的AI技术及简单实现 ,里面 ...

  6. Ubuntu系统Java开发环境的搭建

    操作系统:Linux x64 / Ubuntu 14.04 Java JDK版本:jdk-8u65-linux-x64.tar.gz 声明:转载请注明出处及本文链接 本文原文地址:Ubuntu系统Ja ...

  7. 基于java开发的在线题库系统tamguo

    简介 探果网(简称tamguo)是基于java开发的在线题库系统,包括 在线访问 后台运营 会员中心 书籍中心 管理员账号:system 密码:123456 因为线上数据和测试数据没有做到隔离,作者已 ...

  8. Windows系统下JAVA开发环境搭建

    首先我们需要下载JDK(JAVA Development Kit),JDK是整个java开发的核心,它包含了JAVA的运行环境,JAVA工具和JAVA基础的类库. 下载地址:http://www.or ...

  9. SSM开发基于Java EE在线图书销售系统

           SSM(Spring+Spring MVC+MyBatis)开发基于Java EE在线图书销售系统  网站成功建立和运行很大部分取决于网站开发前的规划,因此为了在网站建立过程中避免一些不 ...

随机推荐

  1. [记录]MySQL读写分离(Atlas和MySQL-proxy)

    MySQL读写分离(Atlas和MySQL-proxy) 一.阿里云使用Atlas从外网访问MySQL(RDS) (同样的方式修改配置文件可以实现代理也可以实现读写分离,具体看使用场景) 1.在跳板机 ...

  2. Linux常用命令详解(二) -- 查找常用命令

    locate:    作用:在后台数据库中按文件名搜索,搜索速度更快    命令格式:locate 文件名    选项或参数:            -l    num(要显示的行数)         ...

  3. PHP常见面试题总结

    1.include 和 require 都能把另外一个文件包含到当前文件中 他们有什么区别?include 和 include_once 又有什么区别? 二者区别只有一个,那就是对包含文件的需求程度 ...

  4. Visual Studio 2017 Enterprise 发布 15.4 版本,离线安装包百度网盘下载。

    Visual Studio 2017 于2017年10月13日发布 15.4 版本.该版本包含多项生产力改进,支持 .NET Standard 2.0 ,并且可以开启 Xamarin Live Pla ...

  5. yaf框架加载全局公共函数

    在Boostrap里面建一个方法(按规则命名的函数都会被自动执行) public function _initCommonFunctions(){ Yaf_Loader::import(Yaf_App ...

  6. 麻省理工18年春软件构造课程阅读02“Java基础”

    本文内容来自MIT_6.031_sp18: Software Construction课程的Readings部分,采用CC BY-SA 4.0协议. 由于我们学校(哈工大)大二软件构造课程的大部分素材 ...

  7. hdu1425 哈希技术

    常用的技巧,把每个数字分别对应数组的下标,如果存在小于零的数字,就统一加一个数使得都能映射到一个下标上去. AC代码: #include<cstdio> #include<cstri ...

  8. 【BZOJ1834】 网络扩容

    Time Limit: 1000 ms   Memory Limit: 128 MB Description 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费 ...

  9. 关联规则—频繁项集Apriori算法

    频繁模式和对应的关联或相关规则在一定程度上刻画了属性条件与类标号之间的有趣联系,因此将关联规则挖掘用于分类也会产生比较好的效果.关联规则就是在给定训练项集上频繁出现的项集与项集之间的一种紧密的联系.其 ...

  10. 项目实战14—ELK 企业内部搜索引擎

    一.els.elk 的介绍 1.els,elk els:ElasticSearch,Logstash,Kibana,Beats elk:ElasticSearch,Logstash,Kibana ① ...