1. 程式人生 > >JAVA實現人臉識別,活體檢測之百度API

JAVA實現人臉識別,活體檢測之百度API

-----------------------8/16更新---------------------------

有人問原始碼:

連結:https://pan.baidu.com/s/1WP37IBacu6VZwtNOUDbSYg 密碼:vdzm

在這

--------------------------------------------------

吃水不忘挖井人,挖井人部落格在此:挖井人一挖井人二

然後是官方的使用說明文件:地址

以上,感謝。

首先引入jar:

maven:

    <dependency>
        <groupId>com.baidu.aip</groupId>
        <artifactId>java-sdk</artifactId>
        <version>4.3.2</version>
    </dependency>

然後獲取所需的AppID、APIKey、SecretKey:

進入百度雲,建立應用:

建立完成之後可看見如下:

獲取AppID、APIKey、SecretKey後,匯入一下程式碼:

public class FaceSpot {
	private static final String AppID = "";
	private static final String APIKey = "";
	private static final String SecretKey = "";

	static AipFace client = null;
	static {
		client = new AipFace(AppID, APIKey, SecretKey);
		// 可選:設定網路連線引數
		client.setConnectionTimeoutInMillis(2000);
		client.setSocketTimeoutInMillis(60000);
	}

	public static void main(String[] args) throws IOException {
		 String filePath = "F:/3.jpg";
		 byte[] imgData = FileToByte(new File(filePath));
		 
		 System.out.println(detectFace(imgData,"1"));
//		String filePath1 = "F:/3.jpg";
//		String filePath2 = "F:/7.jpg";
//		byte[] imgData1 = FileUtil.readFileByBytes(filePath1);
//		byte[] imgData2 = FileUtil.readFileByBytes(filePath2);
//		System.out.println(faceverify(imgData1));
	}

	/**
	 * 人臉檢測
	 * 
	 * @return
	 * @throws IOException
	 */
	public static String detectFace(File file, String max_face_num) {
		try {
			return detectFace(FileToByte(file), max_face_num);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 人臉檢測
	 * 
	 * @return
	 * @throws IOException
	 */
	public static String detectFace(byte[] arg0, String max_face_num) {
		try {

			HashMap<String, String> options = new HashMap<String, String>();
			options.put("face_field", "age,beauty,expression,faceshape,gender,glasses,race,qualities");
			options.put("max_face_num", "2");
			options.put("face_type", "LIVE");

			// 圖片資料
			String imgStr = Base64Util.encode(arg0);
			String imageType = "BASE64";
			JSONObject res = client.detect(imgStr, imageType, options);
			System.out.println(res.toString(2));
			return res.toString();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
    /**
     * 人臉比對
     * @param file1
     * @param file2
     * @return
     */
	public static String matchFace(File file1, File file2) {
		try {
			return matchFace(FileToByte(file1), FileToByte(file2));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 人臉比對
	 * 
	 * @param arg0
	 *            人臉1
	 * @param arg1
	 *            人臉2
	 * @return
	 */
	public static String matchFace(byte[] arg0, byte[] arg1) {
		String imgStr1 = Base64Util.encode(arg0);
		String imgStr2 = Base64Util.encode(arg1);
		MatchRequest req1 = new MatchRequest(imgStr1, "BASE64");
		MatchRequest req2 = new MatchRequest(imgStr2, "BASE64");
		ArrayList<MatchRequest> requests = new ArrayList<MatchRequest>();
		requests.add(req1);
		requests.add(req2);
		JSONObject res = client.match(requests);
		return res.toString();
	}
    
	/**
	 * 人臉搜尋
	 * @param file
	 * @param groupIdList
	 * @param userId
	 * @return
	 */
	public static String searchFace(File file, String groupIdList, String userId) {
		try {
			return searchFace(FileToByte(file), groupIdList, userId);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 人臉搜尋
	 * 
	 * @param arg0
	 * @param groupIdList
	 * @return
	 */
	public static String searchFace(byte[] arg0, String groupIdList, String userId) {
		String imgStr = Base64Util.encode(arg0);
		String imageType = "BASE64";
		HashMap<String, String> options = new HashMap<String, String>();
		options.put("quality_control", "NORMAL");
		options.put("liveness_control", "LOW");
		if (userId != null) {
			options.put("user_id", userId);
		}
		options.put("max_user_num", "1");
		JSONObject res = client.search(imgStr, imageType, groupIdList, options);
		return res.toString(2);
	}
    /**
     * 增加使用者
     * @param file
     * @param userInfo
     * @param userId
     * @param groupId
     * @return
     */
	public static String addUser(File file, String userInfo, String userId, String groupId) {
		try {
			return addUser(FileToByte(file), userInfo, userId, groupId);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 增加使用者
	 * 
	 * @param arg0
	 * @param userInfo
	 * @param userId
	 * @param groupId
	 * @return
	 */
	public static String addUser(byte[] arg0, String userInfo, String userId, String groupId) {
		String imgStr = Base64Util.encode(arg0);
		String imageType = "BASE64";
		HashMap<String, String> options = new HashMap<String, String>();
		options.put("user_info", userInfo);
		options.put("quality_control", "NORMAL");
		options.put("liveness_control", "LOW");

		JSONObject res = client.addUser(imgStr, imageType, groupId, userId, options);
		return res.toString(2);
	}

	public static String updateUser(File file, String userInfo, String userId, String groupId) {
		try {
			return updateUser(FileToByte(file), userInfo, userId, groupId);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 更新使用者
	 * 
	 * @param arg0
	 * @param userInfo
	 * @param userId
	 * @param groupId
	 * @return
	 */
	public static String updateUser(byte[] arg0, String userInfo, String userId, String groupId) {
		String imgStr = Base64Util.encode(arg0);
		String imageType = "BASE64";
		HashMap<String, String> options = new HashMap<String, String>();
		if (userInfo != null) {
			options.put("user_info", userInfo);
		}
		options.put("quality_control", "NORMAL");
		options.put("liveness_control", "LOW");

		JSONObject res = client.updateUser(imgStr, imageType, groupId, userId, options);
		return res.toString(2);
	}
    /**
     * 刪除使用者人臉資訊
     * @param userId
     * @param groupId
     * @param faceToken
     * @return
     */
	public static String deleteUserFace(String userId, String groupId, String faceToken) {
		HashMap<String, String> options = new HashMap<String, String>();
		// 人臉刪除
		JSONObject res = client.faceDelete(userId, groupId, faceToken, options);
		return res.toString();
	}
    /**
     * 查詢使用者資訊
     * @param userId
     * @param groupId
     * @return
     */
	public static String searchUserInfo(String userId, String groupId) {
		HashMap<String, String> options = new HashMap<String, String>();
		// 使用者資訊查詢
		JSONObject res = client.getUser(userId, groupId, options);
		return res.toString(2);
	}
    /**
     * 獲取使用者人臉列表
     * @param userId
     * @param groupId
     * @return
     */
	public static String getUserFaceList(String userId, String groupId) {
		HashMap<String, String> options = new HashMap<String, String>();
		// 獲取使用者人臉列表
		JSONObject res = client.faceGetlist(userId, groupId, options);
		return res.toString(2);
	}
    /**
     * 獲取一組使用者
     * @param groupId
     * @param returnNum
     * @return
     */
	public static String getGroupUsers(String groupId, String returnNum) {
		HashMap<String, String> options = new HashMap<String, String>();
		options.put("start", "0");
		if (returnNum != null) {
			options.put("length", returnNum);
		}
		// 獲取使用者列表
		JSONObject res = client.getGroupUsers(groupId, options);
		return res.toString(2);
	}
    /**
     * 組使用者複製
     * @param userId
     * @param srcGroupId
     * @param dstGroupId
     * @return
     */
	public static String userCopy(String userId, String srcGroupId, String dstGroupId) {
		HashMap<String, String> options = new HashMap<String, String>();
		options.put("src_group_id", srcGroupId);
		options.put("dst_group_id", dstGroupId);
		// 複製使用者
		JSONObject res = client.userCopy(userId, options);
		return res.toString(2);
	}
    /**
     * 刪除使用者
     * @param userId
     * @param groupId
     * @return
     */
	public static String deleteUser(String userId, String groupId) {
		HashMap<String, String> options = new HashMap<String, String>();
		// 人臉刪除
		JSONObject res = client.deleteUser(groupId, userId, options);
		return res.toString();
	}
    /**
     * 增加組資訊
     * @param groupId
     * @return
     */
	public static String addGroup(String groupId) {
		HashMap<String, String> options = new HashMap<String, String>();
		// 建立使用者組
		JSONObject res = client.groupAdd(groupId, options);
		return res.toString();
	}
    /**
     * 刪除
     * @param groupId
     * @return
     */
	public static String deleteGroup(String groupId) {
		HashMap<String, String> options = new HashMap<String, String>();
		// 建立使用者組
		JSONObject res = client.groupDelete(groupId, options);
		return res.toString();
	}
    /**
     * 獲取組列表
     * @param length
     * @return
     */
	public static String getGroupList(String length) {
		HashMap<String, String> options = new HashMap<String, String>();
		options.put("start", "0");
		options.put("length", length);
		// 組列表查詢
		JSONObject res = client.getGroupList(options);
		return res.toString();
	}
	/**
	 * 活體檢測
	 * @param arg0
	 * @return
	 */
	public static String faceverify(byte[] arg0){
		String imgStr = Base64Util.encode(arg0);
        String imageType = "BASE64";
        FaceVerifyRequest req = new FaceVerifyRequest(imgStr, imageType);
        ArrayList<FaceVerifyRequest> list = new ArrayList<FaceVerifyRequest>();
        list.add(req);
        JSONObject res = client.faceverify(list);
        return res.toString();
	}

	private static byte[] FileToByte(File file) throws IOException {
		// 將資料轉為流
		InputStream content = new FileInputStream(file);
		ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
		byte[] buff = new byte[100];
		int rc = 0;
		while ((rc = content.read(buff, 0, 100)) > 0) {
			swapStream.write(buff, 0, rc);
		}
		// 獲得二進位制陣列
		return swapStream.toByteArray();
	}

}

填入自己的AppID, APIKey, SecretKey;

函式的引數可自行根據官方文件自己改一改,檔案讀取那邊提供一下小帥的FileUtil並且處理好了異常:

public class FileUtil {

    /**
     * 根據檔案路徑讀取byte[] 陣列
     */
    public static byte[] readFileByBytes(String filePath) throws IOException {
        File file = new File(filePath);
        if (!file.exists()) {
            throw new FileNotFoundException(filePath);
        } else {
            ByteArrayOutputStream bos = new ByteArrayOutputStream((int) file.length());
            BufferedInputStream in = null;

            try {
                in = new BufferedInputStream(new FileInputStream(file));
                short bufSize = 1024;
                byte[] buffer = new byte[bufSize];
                int len1;
                while (-1 != (len1 = in.read(buffer, 0, bufSize))) {
                    bos.write(buffer, 0, len1);
                }

                byte[] var7 = bos.toByteArray();
                return var7;
            } finally {
                try {
                    if (in != null) {
                        in.close();
                    }
                } catch (IOException var14) {
                    var14.printStackTrace();
                }

                bos.close();
            }
        }
    }
}

然後就是測試啦,測試的話,隨便百度了一張美女的照片,然後看返回:

{
  "timestamp": 1528422299,
  "result": {
    "face_list": [{
      "expression": {
        "probability": 0.9997190833,
        "type": "smile"
      },
      "face_probability": 1,
      "glasses": {
        "probability": 0.9999995232,
        "type": "none"
      },
      "location": {
        "height": 102,
        "rotation": -2,
        "width": 109,
        "left": 102.9398575,
        "top": 56.39219284
      },
      "age": 19,
      "gender": {
        "probability": 0.9999992847,
        "type": "female"
      },
      "face_shape": {
        "probability": 0.7517765164,
        "type": "heart"
      },
      "face_token": "706eaee3240ef0cc679ab209b1b71e0d",
      "beauty": 69.47167206,
      "race": {
        "probability": 0.9999864101,
        "type": "yellow"
      },
      "angle": {
        "yaw": -2.858289719,
        "roll": -2.302281618,
        "pitch": 9.867022514
      }
    }],
    "face_num": 1
  },
  "cached": 0,
  "error_code": 0,
  "log_id": 3671200838,
  "error_msg": "SUCCESS"
}

嗯,確實是美女,

"beauty": 69.47167206

好,然後通過瀏覽器開啟攝像頭來實時的試下,先上效果圖:

好,大家不用在意這些細節,比如顏值啥的。。

我覺得顏值這項可能是假的,因為我做搞怪的表情時分數反而高一些??????????

上程式碼吧。。

首先是Controller:

@Controller
@RequestMapping(value = "/faceRecognition")
public class faceRecognitionController {

	 /**
	 * 人臉檢測測試頁面
	 * @return
	 * @throws Exception  
	 */
    @RequestMapping(value = "/test.do")
    public ModelAndView queryVoi() throws Exception {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("/artificialIntelligence/faceRecognition/test");
        return modelAndView;
    }
	
    /**
   	 * 請求人臉檢測
   	 * @return
   	 * @throws Exception  
   	 */
	@RequestMapping(value = "/save.do")
	@ResponseBody
	public Map<String, Object> queryService(@RequestParam("the_file") MultipartFile file) {
		Map<String, Object> modelMap = new HashMap<String, Object>();
		try {
			//將資料轉為流
			InputStream content = file.getInputStream();
			ByteArrayOutputStream swapStream = new ByteArrayOutputStream();  
	        byte[] buff = new byte[100];  
	        int rc = 0;  
	        while ((rc = content.read(buff, 0, 100)) > 0) {  
	            swapStream.write(buff, 0, rc);  
	        }  
	        //獲得二進位制陣列
	        byte[] in2b = swapStream.toByteArray(); 
	        //呼叫人臉檢測的方法
	        String  str = FaceSpot.detectFace(in2b,""+1);
	        JSONObject job = new JSONObject(FaceSpot.faceverify(in2b));
			 System.out.println(job.toString());
			 JSONObject testData = job.getJSONObject("result");
			 //System.out.println(testData.get("face_liveness"));
	        
	        JSON json = JSON.parseObject(str);
            FaceV3DetectBean bean = JSON.toJavaObject(json, FaceV3DetectBean.class);
            JSONArray arr = new JSONArray();
            
	     	 for(int i=0;i<bean.getResult().getFace_list().size();i++){
			        JSONObject jsonObject = new JSONObject();
			    	//獲取年齡
			        int ageOne = bean.getResult().getFace_list().get(i).getAge();
			     	//處理年齡
			        String age =String.valueOf(new BigDecimal(ageOne).setScale(0, BigDecimal.ROUND_HALF_UP));
			        jsonObject.put("age", age);
					
					//獲取美醜打分
			        Double beautyOne = (Double) bean.getResult().getFace_list().get(i).getBeauty();
					//處理美醜打分
			     	String beauty =String.valueOf(new BigDecimal(beautyOne).setScale(0, BigDecimal.ROUND_HALF_UP));
			     	jsonObject.put("beauty", beauty);
					
					//獲取性別  male(男)、female(女)
					String gender = (String) bean.getResult().getFace_list().get(i).getGender().getType();
					jsonObject.put("gender", gender);
					
					//獲取是否帶眼睛 0-無眼鏡,1-普通眼鏡,2-墨鏡
					String glasses =  bean.getResult().getFace_list().get(i).getGlasses().getType();
					jsonObject.put("glasses", String.valueOf(glasses));
					
					//獲取是否微笑,0,不笑;1,微笑;2,大笑
					String expression =  bean.getResult().getFace_list().get(i).getExpression().getType();
					jsonObject.put("expression", String.valueOf(expression));
					arr.put(jsonObject);
			 }
			modelMap.put("strjson", arr.toString());
			modelMap.put("face_liveness", testData.get("face_liveness"));
			modelMap.put("success", true);
		} catch (Exception e) {
			e.printStackTrace();
			modelMap.put("success", false);
			modelMap.put("data", e.getMessage());
		}
		return modelMap;
	}
	
	
}

用的是fastjson,自行加jar包。

然後是jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">	
<title>人臉檢測</title>
<script src="js/jquery-2.1.1.js" type="text/javascript" charset="utf-8"></script>
<script>

	//判斷瀏覽器是否支援HTML5 Canvas
	window.onload = function () {
		try {
		//動態建立一個canvas元 ,並獲取他2Dcontext。如果出現異常則表示不支援 document.createElement("canvas").getContext("2d");
		 document.getElementById("support").innerHTML = "瀏覽器支援HTML5 CANVAS";
		}
		catch (e) {
		 document.getElementByIdx("support").innerHTML = "瀏覽器不支援HTML5 CANVAS";
		}
	};
	
	//這段代 主要是獲取攝像頭的視訊流並顯示在Video 籤中
	window.addEventListener("DOMContentLoaded", function () {
		var canvas = document.getElementById("canvas"),
		context = canvas.getContext("2d"),
		video = document.getElementById("video"),
		videoObj = { "video": true },
		errBack = function (error) {
			console.log("Video capture error: ", error.code);
		};
		//拍照按鈕
// 		$("#snap").click(function () {
// 			context.drawImage(video, 0, 0, 330, 250);
// 			})
		//拍照每秒一次
		setInterval(function(){
			context.drawImage(video, 0, 0, 330, 250)
			CatchCode();
		},1000);
		//navigator.getUserMedia這個寫法在Opera中好像是navigator.getUserMedianow
		//更新相容火狐瀏覽器
		if (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia) {
			    navigator.getUserMedia=navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
			    navigator.getUserMedia(videoObj, function (stream) {
				video.srcObject  = stream;
				video.play();
				}, errBack);
		}
	
	}, false);
	
	function dataURItoBlob(base64Data) {
		var byteString;
		if (base64Data.split(',')[0].indexOf('base64') >= 0)
		byteString = atob(base64Data.split(',')[1]);
		else
		byteString = unescape(base64Data.split(',')[1]);
		var mimeString = base64Data.split(',')[0].split(':')[1].split(';')[0];
		var ia = new Uint8Array(byteString.length);
		for (var i = 0; i < byteString.length; i++) {
		ia[i] = byteString.charCodeAt(i);
		}
		return new Blob([ia], {type:mimeString});
	}
	
	//上傳伺服器
	function CatchCode() {
		var canvans = document.getElementById("canvas");
		//獲取瀏覽器頁面的畫布物件
		//以下開始編 資料
		var imageBase64 = canvans.toDataURL();
		var blob = dataURItoBlob(imageBase64);  // 上一步中的函式
		var fd = new FormData(document.forms[0]);
		fd.append("the_file", blob, 'image.png');
		//將影象轉換為base64資料
		$.ajax({
	   		type:"POST",
	   		url:"faceRecognition/save.do",
	   		processData: false,     // 必須
	      	contentType: false,     // 必須
	      	data:fd,
	    	datatype: "json",
	   		success:function(data){
		   		var mes = eval(data);
		   		//alert(mes.success);
		   		//var jsonObj =   $.parseJSON(mes.strjson); 
		   		//alert(jsonObj[0].age);
		   		if (mes.success) {
 		   			//alert(mes.strjson);
		   			var jsonObj =  $.parseJSON(mes.strjson); 
		   			//alert(jsonObj);
		   			var age = jsonObj[0].age;
 		   			
		   			var beauty = jsonObj[0].beauty;
		   			var gendergender = jsonObj[0].gender;
		   			var glasses = jsonObj[0].glasses;
		   			var expression = jsonObj[0].expression
		   			
		   			$("#age").html(age);
		   			$("#beauty").html(beauty);
		   			$("#faceverify").html(mes.face_liveness);
		   			
		   			if(gendergender == 'male'){
		   				$("#gendergender").html("男");
		   			}else{
		   				$("#gendergender").html("女");
		   			}
		   			
		   			if(glasses == 'none'){
		   				$("#glasses").html("未戴眼鏡");
		   			}else if(glasses == 'common'){
		   				$("#glasses").html("戴了普通眼鏡");
		   			}else{
		   				$("#glasses").html("戴了墨鏡");
		   			}
					
		   			if(expression == 'none'){
		   				$("#expression").html("不笑");
		   			}else if(expression == 'smile'){
		   				$("#expression").html("微笑");
		   			}else{
		   				$("#expression").html("大笑");
		   			}
		   		}
	   		},
	   		error: function(){
	    		//請求出錯處理
	    		alert("出情況了");
	    		}         
	  		});
	}
</script>
<style> 
.div-a{ float:left;width:60%;height:60%;border:1px solid #F00} 
.div-b{ float:left;width:39%;height:60%;border:1px solid #000} 
span{ font-size:25px }
</style> 
</head> 
<body> 
	<!-- 左邊區域 -->
	<div class="div-a" id="contentHolder">
			<video id="video" width="100%" height="60%" autoplay></video>
			<canvas style="" hidden="hidden"  id="canvas" width="520" height="250"></canvas>
	</div> 
	<!-- 右邊區域 -->
	<div class="div-b" >
			<!-- 測試按鈕 -->
<!-- 		<input type="button" id="snap" style="width:100px;height:35px;" value="拍 照" /> -->
<!-- 		<input type="button" onclick="CatchCode();" style="width:100px;height:35px;" value="上傳伺服器" /> -->
		
		<h1>人臉檢測實時資料</h1>
		<span>年齡:</span><span id="age"></span><br/>
		<span>顏值:</span><span id="beauty" ></span><br/>
		<span>性別:</span><span id="gendergender"></span><br/>
		<span>是否戴眼鏡:</span><span id="glasses"></span><br/>
		<span>表情:</span><span id="expression"></span><br/>
		<span>活體分數:</span><span id="faceverify"></span><br/>
	</div> 
		
	</body>
</html>

這個貌似只支援火狐??我用其他瀏覽器攝像頭並未開啟,有哪位大神知道程式碼還請告訴在下,謝謝指教。

這邊有個活體指數,我測試了下,貌似還挺準,我首先百度了一張胡歌的照片放在攝像頭上,emmmm.....顏值80,但是活體指數就很低,然後本人上,活體指數一直在0.95之上浮動,還是可靠的。

好,告辭!