主要工作:
1、使用P
ostman工具模拟浏览器发送请求,调用api的人脸检测和人脸搜索
2、根据api文档,
封装工具类为jar包,工具类中实现创建图像集合,寻找图片,检测人脸等操作,通过 静态代码块实现
从properties配置文件中读取api的key和秘钥以及人脸集合名称
3、导入了
fastjson,用于将返回的json字符串转换为json对象
4、通过
servlet实现登录注册,通过js
调用摄像头,分别根据登录注册按钮使用ajxs执行相应操作
一、技术介绍
1、人脸识别
- face_token:当对一张图片进行人脸检测时,会将检测到的人脸记录下来,包括人脸在图片中的位置,用一个系统标识face_token来表示。
- 对同一张图片进行多次人脸检测,对同一个人脸会得到不同的face_token。
- 人脸集合 faceSet:人脸集合(FaceSet)是用来存储检测到人脸的存储对象。一个FaceSet内face_token是不重复的。
- 人脸搜索:采集用户新的人脸,在多个已知身份用户的人脸集合中进行搜索,找出新的人脸属于哪一个已知身份用户。人脸搜索需要调用Search API。
2、接口介绍
使用了旷世公司的
face plus plus提供的接口
https://www.faceplusplus.com/
postman工具可以模拟浏览器发送请求,提交数据
人脸检测
人脸搜索
二、具体实现
1、根据API接口封装的工具类的使用
工具类
package com.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.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
import java.util.logging.Logger;
import javax.net.ssl.SSLException;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
public class FaceUtil {
/**
* 根据传入图片进行人脸检测
* @param file 传入的人脸照片
* @return 返回人脸照片的facetoken,如果为空说明图片不符合要求
* @throws Exception
*/
public static String detect(File file) throws Exception {
byte[] buff = HTTPUtil.getBytesFromFile(file);
String url = "https://api-cn.faceplusplus.com/facepp/v3/detect";
HashMap<String, byte[]> byteMap = new HashMap<>();
byteMap.put("image_file", buff);
byte[] bacd = HTTPUtil.post(url, HTTPUtil.map, byteMap);
String str = new String(bacd);
if(str.indexOf("error_message")!=-1) {
return null;
}
JSONObject obj = JSONObject.parseObject(str);
int faceNum=obj.getIntValue("face_num");
if(faceNum==1) {
//获取facetoken
JSONObject face=(JSONObject) ((JSONArray)obj.get("faces")).get(0);
String faceToken=face.getString("face_token");
return faceToken;
}
return null;
}
/**
* 查询指定的照片是否在人脸集合faceset中存在
* @param faceToken
* @return
* @throws Exception
*/
public static boolean search(String faceToken) throws Exception {
String url = "https://api-cn.faceplusplus.com/facepp/v3/search";
HTTPUtil.map.put("face_token", faceToken);
byte[] bacd = HTTPUtil.post(url, HTTPUtil.map, null);
String str = new String(bacd);
if(str.indexOf("error_message")==-1) {//请求没有错误
JSONObject json = JSONObject.parseObject(str);
JSONObject thresholds=(JSONObject) json.get("thresholds");
Double le5=thresholds.getDouble("1e-5");
JSONArray results=(JSONArray) json.get("results");
if(results!=null && results.size()>=1) {
Double confidence=((JSONObject)results.get(0)).getDouble("confidence");
if(confidence>le5) {
return true;
}
}
}
return false;
}
/**
* 添加人脸到faceset中
* @param face_tokens 要添加的人脸
* @return
* @throws Exception
*/
public static boolean addFace(String face_tokens) throws Exception {
if(!getDetail()) {//先获取人脸集合,没有集合就创建一个
System.out.println("没有获取到指定人脸集合");
boolean res=createFaceSet();
if(!res) {
System.out.println("创建人脸集合出问题了!");
return false;
}
System.out.println("创建人脸集合成功!");
}
String url = "https://api-cn.faceplusplus.com/facepp/v3/faceset/addface";
HTTPUtil.map.put("face_tokens", face_tokens);
byte[] bacd = HTTPUtil.post(url, HTTPUtil.map, null);
String str = new String(bacd);
if(str.indexOf("error_message")!=-1) {
return false;
}
return true;
}
/**
* 创建一个人脸的集合 FaceSet,用于存储人脸标识 face_token。
* @return
* @throws Exception
*/
public static boolean createFaceSet() throws Exception {
String url = "https://api-cn.faceplusplus.com/facepp/v3/faceset/create";
byte[] bacd = HTTPUtil.post(url, HTTPUtil.map, null);
String str = new String(bacd);
System.out.println(str);
if(str.indexOf("error_message")!=-1) {
return false;
}
System.out.println("创建人脸集合:"+str);
return true;
}
/**
* 获取一个faceset
* @return
* @throws Exception
*/
public static boolean getDetail() throws Exception {
String url = "https://api-cn.faceplusplus.com/facepp/v3/faceset/getdetail";
byte[] bacd = HTTPUtil.post(url, HTTPUtil.map, null);
String str = new String(bacd);
if(str.indexOf("error_message")!=-1) {
return false;
}
return true;
}
}
2、测试类
package com.face.test;
import java.io.File;
import com.util.FaceUtil;
public class TestFace {
public static void main(String[] args) {
//获取到要检测的图片
File file=new File("F:\\相册\\微信图片_20201217215617.jpg");
try {
String faceToken=FaceUtil.detect(file);
System.out.println("face_token:"+faceToken);//人脸的检测
//添加一个人脸到集合中
boolean addFlag=FaceUtil.addFace(faceToken);//人脸的添加
System.out.println("添加成功:"+addFlag);
boolean flag=FaceUtil.search(faceToken);//人脸的搜索
System.out.println("人脸搜索的结果:"+flag);
//获取人脸的集合
flag=FaceUtil.getDetail();
//如果没有该集合,就创建 一个
if(!flag) {
flag=FaceUtil.createFaceSet();
System.out.println("如果没有outer_id为JohnFaceSet的人脸集合,则创建一个新的!");
}
System.out.println("outer_id为JohnFaceSet的人脸集合:"+flag);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
3、登录功能的实现
步骤分析
servlet:
- 概念: Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编 写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web 内容。
- servlet任务
- 1)读取客户端(浏览器)发送的数据----(接受请求)
- 2) 处理数据并生成结果----(处理请求)
- 3)发送HTTP响应到客户端(浏览器)----(给出响应)
package com.face.servlet;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.util.FaceUtil;
import com.wln.util.ImageUtils;
@WebServlet("/faceController")
//首字母要小写
public class FaceController extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* 1、接收用户的请求request
* 2、处理请求
* 3、返回数据给客户端response
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//登录的步骤
//1、获取客户上传的图片-上传到指定的文件夹(upimg)
File file=ImageUtils.uploadImg(request, "imgData", "upimg");
boolean res=false;
//2、判断是否包含人脸信息:detect
try {
String faceToken=FaceUtil.detect(file);
if(faceToken!=null) {
//2.1包含人脸
//在faceset中查找是否有相似度高的人脸信息search
res=FaceUtil.search(faceToken);
//有:登录成功res=true;
//没有:登录失败res=false;
}else {
//2.2不包含:登录失败
}
//删除照片
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
//删除照片
file.delete();
//数据的返回 response返回数据给客户端
PrintWriter pw=response.getWriter();
String msg="{\"success\":"+res+"}";
pw.write(msg);
pw.close();
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
4、注册功能的实现
package com.face.servlet;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.util.FaceUtil;
import com.wln.util.ImageUtils;
@WebServlet("/faceController")
//首字母要小写
public class FaceController extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* 1、接收用户的请求request
* 2、处理请求
* 3、返回数据给客户端response
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//登录的步骤
//1、获取客户上传的图片-上传到指定的文件夹(upimg)
File file=ImageUtils.uploadImg(request, "imgData", "upimg");
boolean res=false;
boolean delFlag=true;
//2、判断是否包含人脸信息:detect
try {
String faceToken=FaceUtil.detect(file);
if(faceToken!=null) {
//2.1包含人脸
//在faceset中查找是否有相似度高的人脸信息search
res=FaceUtil.search(faceToken);
//有:登录成功res=true;
//没有:登录失败res=false;
//判定用户请求的类型
String type=request.getParameter("type");
if("register".equals(type)) {
if(res) {
//有,则已经注册过
res=false;
//删除照片
}else {
//没有,可以注册,添加facetoken到faceset中
res=FaceUtil.addFace(faceToken);
//保留照片
delFlag=false;
}
}
}else {
//2.2不包含:登录失败
}
//删除照片
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
//删除照片
if(delFlag) {
file.delete();
}
//数据的返回 response返回数据给客户端
PrintWriter pw=response.getWriter();
String msg="{\"success\":"+res+"}";
pw.write(msg);
pw.close();
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}