基於人臉識別的登錄與注冊


主要工作:
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);
	}
}






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM