基於百度AI使用H5實現調用攝像頭進行人臉註冊、人臉搜索功能(Java)

 

人臉註冊、人臉搜索使用百度AI接口。不支持H5活體檢測(需要活體檢測請參考百度AI-H5活體檢測)

前期準備工作

1.http://ai.ai/ 註冊賬戶 實名認證 創建人臉應用 保存APPID、APIKEY、SECRETKEY 三個值備用

2.需要必須的Java經驗(最好是會用SpringBootMaven)

3.https://trackingjs.com/ 瞭解一下trackingjs(進行視頻中的人臉檢測。更多功能自行閱讀文檔)

4.項目源碼地址:https://gitee.com/xshuai/faceRecognition

簡易流程圖

示例圖(先看下效果)

用戶名爲空提示

百度AI人臉註冊需要userid groupid 演示功能 直接寫固定的值 userid是UUID生成的一個字符串。大家根據實際情況更改即可

圖片不包含人臉

確保圖片中包含人臉即可。未做活體檢測。活體檢測請參考百度AI官方文檔的H5活體檢測

人臉註冊成功

人臉搜索

trackingjs提供人臉檢測功能。需要完整面部 缺少下顎也是不行的。搜索是使用百度AI接口。成功搜索返回註冊給的用戶名稱

無需用戶主動拍照。只要攝像頭中包含完整面部即可。同樣也不支持活體檢測

搭建SpringBoot項目

項目地址 https://gitee.com/xshuai/faceRecognition

pom配置相關庫

百度SDK、fastjson、thymeleaf必不可少

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>cn.xsshome</groupId>
  <artifactId>faceRecognition</artifactId>
  <packaging>jar</packaging>

  <name>faceRecognition</name>
  <url>http://maven.apache.org</url>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.4.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <swagger.version>2.7.0</swagger.version>
  </properties>

  <dependencies>
    <!-- fastjson -->
	<dependency>
		<groupId>com.alibaba</groupId>
		<artifactId>fastjson</artifactId>
		<version>1.2.35</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>springloaded</artifactId>
		<version>1.2.6.RELEASE</version>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-devtools</artifactId>
	</dependency>
	<!-- SpringBoot 核心包 -->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter</artifactId>
	</dependency>
	<!-- SpringBoot Web容器 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-actuator</artifactId>
	</dependency>	
	<!-- SpringBoot集成thymeleaf模板 -->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-thymeleaf</artifactId>
	</dependency>	
	<!-- 日誌版本 -->
	<dependency>
		<groupId>log4j</groupId>
		<artifactId>log4j</artifactId>
		<version>1.2.17</version>
	</dependency>
	<!-- 百度AI SDK -->
	<dependency>
		<groupId>com.baidu.aip</groupId>
		<artifactId>java-sdk</artifactId>
		<version>4.10.0</version>
	</dependency>
  </dependencies>
  	<!-- jar -->
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<fork>true</fork>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

application.yml配置

server:
  port: 8888
#只簡單配置了項目啓動端口

FaceManagerController(人臉註冊、搜索)

package cn.xsshome.controller;

import java.util.HashMap;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baidu.aip.face.AipFace;

import cn.xsshome.common.FactoryUtil;
import cn.xsshome.vo.FacePageBean;
import cn.xsshome.vo.FacePageResponse;
import cn.xsshome.vo.response.FaceSerachResponse;
/**
 * 人臉照片註冊方法
 * @author 小帥丶
 *
 */
@Controller
@RequestMapping("/facemanager")
public class FaceManagerController {
	//人臉模塊對象
	AipFace aipFace = FactoryUtil.getAipFace();
	private static Logger log = LoggerFactory.getLogger(FaceManagerController.class);
	/**
	 * 人臉註冊
	 * @param facePageBean 請求的參數對象
	 * @param request  
	 * @param response
	 * @return
	 */
	@PostMapping("/add")
	@ResponseBody
	public String addFace(FacePageBean facePageBean,HttpServletRequest request, HttpServletResponse response){
		log.info("發送過來的參數{}",JSONObject.toJSONString(facePageBean));
		FacePageResponse facePageResponse = new FacePageResponse();
		if(facePageBean.getUser_info().equals("")||null==facePageBean.getUser_info()){
			facePageResponse.setError_code("100");
			facePageResponse.setError_msg("用戶名稱爲空 請填寫後重試");
			return JSON.toJSONString(facePageResponse);
		}else{
			String groupId = "xsdemo";//記得替換成自己的或通過頁面傳遞用戶組id(由數字、字母、下劃線組成),長度限制128B
			String userId = UUID.randomUUID().toString().replace("-", "").toUpperCase();//用戶id(由數字、字母、下劃線組成),長度限制128B
			HashMap<String, String> options = new HashMap<String, String>();
			options.put("user_info","小帥丶");
			org.json.JSONObject resultObject = aipFace.addUser(facePageBean.getImgdata(), "BASE64", groupId, userId, options);
			log.info("註冊返回的數據{}",resultObject.toString(2));
			return resultObject.toString();	
		}
	}
	/**
	 * 人臉搜索
	 * @param facePageBean 請求的參數對象
	 * @param request  
	 * @param response
	 * @return
	 */
	@PostMapping("/search")
	@ResponseBody
	public FacePageResponse searchFace(FacePageBean facePageBean,HttpServletRequest request, HttpServletResponse response){
		FacePageResponse facePageResponse = new FacePageResponse();
		log.info("發送過來的參數{}",JSONObject.toJSONString(facePageBean));
		String groupIdList = "xsdemo";//用戶組id(由數字、字母、下劃線組成),長度限制128B
		org.json.JSONObject resultObject = aipFace.search(facePageBean.getImgdata(), "BASE64", groupIdList, null);
		//使用fastjson處理返回的內容 直接用javabean接收 方便取值
		FaceSerachResponse faceSerachResponse = JSON.parseObject(resultObject.toString(), FaceSerachResponse.class);
		if("0".equals(faceSerachResponse.getError_code())&&"SUCCESS".equals(faceSerachResponse.getError_msg())){
			if(faceSerachResponse.getResult().getUser_list().get(0).getScore()>80f){
				facePageResponse.setError_code(faceSerachResponse.getError_code());
				facePageResponse.setError_msg(faceSerachResponse.getError_msg());
				facePageResponse.setUser_info(faceSerachResponse.getResult().getUser_list().get(0).getUser_info());
			}else{
				facePageResponse.setError_code("555");
				facePageResponse.setError_msg("人臉搜索失敗,請重試或請先註冊");
			}
		}else{
			facePageResponse.setError_code("500");
			facePageResponse.setError_msg(faceSerachResponse.getError_msg());
		}
		log.info("搜索返回的數據{}",resultObject.toString(2));
		return facePageResponse;
	}
}

頁面代碼

人臉註冊頁面

<!DOCTYPE html>
<html  lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="../css/layer.css">
<link rel="stylesheet" href="../css/storage.css" />
<title>人臉註冊</title>
<script type="text/javascript" src="../js/jquery-1.9.1.js"></script>
<script type="text/javascript" src="../js/layer.js"></script>
<style type="text/css">
body {
	background: url('../img/AI3.jpg') no-repeat;
	height: 100%;
	width: 100%;
	overflow: hidden;
	background-size: cover;
}
</style>
</head>
<body>
	<div class="storage">
		<div class="text1">
			<p>人臉註冊</p>
		</div>
		<div class="vid">
			<video id="video" autoplay></video>
		</div>
		<div class="canv">
			<canvas id="canvas"></canvas>
		</div>
		<div>
			<button id="snap" onclick="Shoot()">拍照</button>
			<span class='user_info'>用戶名稱:</span> <input type="text" name="user_info" id="user_info" placeholder="請輸入名稱">
			<button id="download" onclick="download()">上傳</button>
		</div>
	</div>
</body>
<script type="text/javascript" th:inline="javascript">
        /*<![CDATA[*/
        var ctx = /*[[${#httpServletRequest.getScheme() + "://" + #httpServletRequest.getServerName() + ":" + #httpServletRequest.getServerPort() + #httpServletRequest.getContextPath()}]]*/;
    var aVideo = document.getElementById('video');
    var aCanvas = document.getElementById('canvas');
      navigator.getUserMedia = navigator.getUserMedia ||
      navigator.webkitGetUserMedia ||
      navigator.mozGetUserMedia ||
      navigator.msGetUserMedia; //獲取媒體對象(這裏指攝像頭)
      navigator.getUserMedia({
        video: true
    }, gotStream, noStream); //參數1獲取用戶打開權限;參數二是一個回調函數,自動傳入視屏流,成功後調用,並傳一個視頻流對象,參數三打開失敗後調用,傳錯誤信息
    function gotStream(stream) {
       // video.src = URL.createObjectURL(stream); // 老寫法
        aVideo.srcObject = stream;
        aVideo.onerror = function() {
            stream.stop();
        };
        stream.onended = noStream;
        aVideo.onloadedmetadata = function() {
            console.info('攝像頭成功打開!');
        };
    }
    function noStream(err) {
        alert(err);
    }
    function Shoot() {
        var context = canvas.getContext('2d');
        //把當前視頻幀內容渲染到畫布上
        context.drawImage(aVideo, 0, 5, 320,160);
    }
    //將圖片下載到本地
    function download() {
    	var userInfo = $('#user_info').val();
        var dom = document.createElement("a");
        dom.href = this.canvas.toDataURL("image/png");
        dom.download = new Date().getTime() + ".png";
        dom.click();
        //刪除字符串前的提示信息 "data:image/png;base64,"
        var data = aCanvas.toDataURL();
		var b64 = data.substring(22);
		var path = ctx+"/facemanager/add";
		var name = new Date().getTime() + ".png";
		var context = canvas.getContext('2d');
		$.ajax({
			type : 'post',
			dataType : 'json',
			url : path,
			data : {
				imgdata:b64,
				imgname:name,
				user_info:userInfo,
			},
			success : function(result){
			    if(result.error_msg=='SUCCESS'){
			    layer.open({
				  title: '溫馨提示',
				  content: '人臉用戶註冊成功',
				  yes: function(index, layero){
				    layer.close(index); //如果設定了yes回調,需進行手工關閉
				  }
				});
			    }else{
			    layer.open({
				  title: '溫馨提示',
				  content: "註冊失敗:"+result.error_msg,
				  yes: function(index, layero){
       				 //把畫布上的圖清空
       				 context.clearRect(0, 5, 320,160);
				    layer.close(index); //如果設定了yes回調,需進行手工關閉
				  }
				});
			    }
			}
		})
	}
</script>
</html>

人臉搜索頁面

trackerTask.stop();爲防止人臉搜索接口調用中 多次提交問題。

<!DOCTYPE html>
<html  lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="utf-8">
  <title>人臉識別</title>
  <link rel="stylesheet" href="../css/layer.css">
  <link rel="stylesheet" href="../css/demo.css">
  <script type="text/javascript" src="../js/jquery-1.9.1.js"></script>
  <script type="text/javascript" src="../js/layer.js"></script>
  <script src="../js/tracking-min.js"></script>
  <script src="../js/face-min.js"></script>
  <script src="../js/dat.gui.min.js"></script>
  <script src="../js/stats.min.js"></script>
</head>
<body>
	<div>
		<p align="center">請確保面部完整,未檢測到請靠近攝像頭</p>
	</div>
  <div class="demo-frame">
    <div class="demo-container">
    	<div id="face1">
    		 <video id="video" width="640" height="480" preload autoplay loop muted></video> 
    		 <canvas id="canvas" width="640" height="480"></canvas>
    	</div>
      </div>
  </div>
     <div id="face2">
     	   <canvas id="canvas1"></canvas>
     </div>
  <script  type="text/javascript" th:inline="javascript">
        /*<![CDATA[*/
     var ctx = /*[[${#httpServletRequest.getScheme() + "://" + #httpServletRequest.getServerName() + ":" + #httpServletRequest.getServerPort() + #httpServletRequest.getContextPath()}]]*/     
    window.onload = function() {
      var video = document.getElementById('video');
      var canvas = document.getElementById('canvas');
      var canvas1 = document.getElementById('canvas1');
      var context = canvas.getContext('2d');
      var tracker = new tracking.ObjectTracker('face');
      tracker.setInitialScale(4);
      tracker.setStepSize(2);
      tracker.setEdgesDensity(0.1);
      tracking.track('#video', tracker, { camera: true });
      tracker.on('track', function(event) {
        if(event.data.length===0){
            console.info('無人臉');
        	context.clearRect(0, 0, canvas.width, canvas.height);
        }else{
          event.data.forEach(function(rect) {
          context.strokeStyle = '#a64ceb';
          context.strokeRect(rect.x, rect.y, rect.width, rect.height);
          context.font = '11px Helvetica';
          context.fillStyle = "#fff";
          context.fillText('x: ' + rect.x + 'px', rect.x + rect.width + 5, rect.y + 11);
          context.fillText('y: ' + rect.y + 'px', rect.x + rect.width + 5, rect.y + 22);
          Shoot();
        });
        }
      });
      var gui = new dat.GUI();
      gui.add(tracker, 'edgesDensity', 0.1, 0.5).step(0.01);
      gui.add(tracker, 'initialScale', 1.0, 10.0).step(0.1);
      gui.add(tracker, 'stepSize', 1, 5).step(0.1);

	  function Shoot() {
	  	var trackerTask = tracking.track(video, tracker);
		var context = canvas1.getContext('2d');
		//把當前視頻幀內容渲染到畫布上
		context.drawImage(video, 0, 5, 320, 140);
		var dom = document.createElement("a");
		dom.href = this.canvas.toDataURL("image/png");
		dom.download = new Date().getTime() + ".png";
		dom.click();
		//刪除字符串前的提示信息 "data:image/png;base64,"
		var data = canvas1.toDataURL();
		var b64 = data.substring(22);
		var path = ctx+"/facemanager/search";
		$.ajax({
			type : 'post',
			dataType : 'json',
			url : path,
			data : {
				imgdata:b64
			},
			success : function(result){
			if(result.error_code=='0'){
				trackerTask.stop();
				layer.open({
				  title: '溫馨提示',
				  content: '歡迎 '+result.user_info,
				  yes: function(index, layero){
				    trackerTask.run();
				    layer.close(index); //如果設定了yes回調,需進行手工關閉
				  }
				});  
			}else{
				trackerTask.stop();
				layer.open({
				  title: '溫馨提示',
				  content: result.error_msg,
				  yes: function(index, layero){
				    trackerTask.run();
				    layer.close(index); //如果設定了yes回調,需進行手工關閉
				  }
				});
			 }
			}
		})
		}
	};
</script>
</body>
</html>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章