基于人脸识别的登录与注册

主要工作:
1、使用P ostman工具模拟浏览器发送请求,调用api的人脸检测和人脸搜索
2、根据api文档, 封装工具类为jar包,工具类中实现创建图像集合,寻找图片,检测人脸等操作,通过 静态代码块实现 从properties配置文件中读取api的key和秘钥以及人脸集合名称
3、导入了 fastjson,用于将返回的json字符串转换为json对象
4、通过 servlet实现登录注册,通过js 调用摄像头,分别根据登录注册按钮使用ajxs执行相应操作
一、技术介绍
1、人脸识别
  1. face_token:当对一张图片进行人脸检测时,会将检测到的人脸记录下来,包括人脸在图片中的位置,用一个系统标识face_token来表示。
    1. 对同一张图片进行多次人脸检测,对同一个人脸会得到不同的face_token。
  2. 人脸集合 faceSet:人脸集合(FaceSet)是用来存储检测到人脸的存储对象。一个FaceSet内face_token是不重复的。
  3. 人脸搜索:采集用户新的人脸,在多个已知身份用户的人脸集合中进行搜索,找出新的人脸属于哪一个已知身份用户。人脸搜索需要调用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);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值