天天看點

基于人臉識别的登入與注冊

主要工作:

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);
	}
}           

來自為知筆記(Wiz)