一、实现思路
????????根据前端落地页拍摄的面部头像进行登录,拿到图片第一步去后端请求校验,看抓取的照片是否有人脸,如果有,再进行第二步人脸比对,如果比对有结果,且相似度大于设置的分值,则认为比对成功,跳转到自己的系统。
二、服务端接口:
? ? ? ? 1.人脸注册 既然要人脸登录,肯定系统中要存在登录人的人脸数据信息,如果没有,直接就无法登录。
? ?所以首先要人脸注册。
? ? ? ? 2.人脸检测 如果上传的人脸照片没有头像信息,则无不对必要,直接登陆失败。
? ? ? ? 3.人脸搜索 前端抓取的人脸和人脸库数据对比,获取比对结果
三、百度云配置获取相关参数
? 1.注册并登录到百度云
????????
2.选择人工智能-人脸识别功能
?
3.创建应用
?
?
4.拿到要连接的参数
?四、导入百度云AI的依赖
<dependency>
<groupId>com.baidu.aip</groupId>
<artifactId>java-sdk</artifactId>
<version>4.8.0</version>
</dependency>
五、服务端接口开发
1. 工具类? 这里只写了人脸注册,人脸检测,人脸搜索的工具类 业务直接调用即可
?
package com.dong.boot.utils;
import com.baidu.aip.face.AipFace;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.HashMap;
public class FaceRecognitionUtil {
private final static String APPID="24838072";
private final static String APIKEY ="l3tBYskoFx4sK3hK1yRqGijs";
private final static String SECRETKEY ="Q6f6UZVM5zb0TvHc1RSTaN3gOehpoUaH";
private final static String QUALITYCONTROL ="NORMAL";
private final static String LIVENESSCONTROL ="LOW";
private final static String IMAGETYPE="BASE64";
private final static String GROUPID="faceFirst";
private AipFace initAipFace(){
//1创建和百度云AI的连接
return new AipFace(APPID,APIKEY,SECRETKEY);
}
/**
* @description 人脸注册
* @params
* @returns
* @author Yadong Xu
* @date 2021/9/12
*
*/
public boolean faceRegister(String userId,String encode){
AipFace aipFace = initAipFace();
//人脸识别相关的配置
HashMap<String,String> params = new HashMap<>();
params.put("quality_control",QUALITYCONTROL);//图片质量控制NONE: 不进行控制LOW:较低的质量要求NORMAL: 一般的质量要求HIGH: 较高的质量要求默认 NONE 若图片质量不满足要求,则返回结果中会提示质量检测失败
params.put("liveness_control",LIVENESSCONTROL);//活体检测控制NONE: 不进行控制LOW:较低的活体要求(高通过率 低攻击拒绝率)NORMAL: 一般的活体要求(平衡的攻击拒绝率, 通过率)HIGH: 较高的活体要求(高攻击拒绝率 低通过率)默认NONE若活体检测结果不满足要求,则返回结果中会提示活体检测失败
//准备注册到人脸库的图片 百度云接收两种格式的图片 一个是url地址 一个是base64的字符串
// encode 人脸数据字符串 BASE64类型 照片组 faceFirst userId 20210912001 自定义的 params设置注册时的参数
JSONObject jsonObject = aipFace.addUser(encode, IMAGETYPE, GROUPID, userId, params);
//人脸注册的返回信息:{"result":{"face_token":"c175093d999f61bd6053853764eaa167",
// "location":{"top":353.46,"left":130.81,"rotation":-24,"width":507,"height":499}},
// "log_id":12555552010,"error_msg":"SUCCESS","cached":0,"error_code":0,"timestamp":1631450788}
if ((Integer) jsonObject.get("error_code") == 0){
return true;
}
return false;
}
/**
* @description 人脸校验
* @params
* @returns
* @author Yadong Xu
* @date 2021/9/12
*
*/
public boolean faceCheck(String encode) {
AipFace aipFace = initAipFace();
JSONObject res = aipFace.detect(encode, IMAGETYPE, null);
//人脸校验的返回信息{"result":{"face_num":1,"face_list":[{"angle":{"roll":-26.42,"pitch":1.82,"yaw":8.25},
// "face_token":"c175093d999f61bd6053853764eaa167","location":{"top":353.46,"left":130.81,"rotation":-24,"width":507,"height":499},
// "face_probability":1}]},"log_id":1012535998455,"error_msg":"SUCCESS","cached":0,"error_code":0,"timestamp":1631451053}
if ((Integer) res.get("error_code") == 0){
return true;
}
return false;
}
/**
* @description 人脸搜索
* @params
* @returns
* @author Yadong Xu
* @date 2021/9/12
*
*/
public String faceSearch(String encode){
AipFace aipFace = initAipFace();
JSONObject search = aipFace.search(encode, IMAGETYPE, GROUPID, null);
//人脸搜索返回的信息{"result":{"face_token":"c175093d999f61bd6053853764eaa167",
// "user_list":[{"score":100,"group_id":"faceFirst","user_id":"20210912003","user_info":""}]},
// "log_id":4575751012575,"error_msg":"SUCCESS","cached":0,"error_code":0,"timestamp":1631451384}
JSONArray array = (JSONArray) search.get("user_list");
JSONObject user = (JSONObject) array.get(0);
Double score = (Double) user.get("score");
if (score>80){
return user.getString("user_id");
}
return null;
}
}
?2.controller层调用
package com.dong.boot.controller.face;
import com.baidu.aip.util.Base64Util;
import com.dong.boot.model.RespBean;
import com.dong.boot.utils.FaceRecognitionUtil;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
@RestController
public class FaceRecognitionController {
@PostMapping("/face/register")
public RespBean register(@RequestParam("file") MultipartFile file,@RequestParam("userId")String userId){
//把图片保存到本地
try {
file.transferTo(new File("D:\\img\\"+file.getOriginalFilename()));
String encode = Base64Util.encode(file.getBytes());
if (FaceRecognitionUtil.faceRegister(userId,encode)){
return RespBean.ok("文件注册成功");
}
} catch (IOException e) {
e.printStackTrace();
return RespBean.ok("文件注册失败");
}
return RespBean.ok("文件注册失败");
}
@PostMapping("/face/search")
public RespBean search(@RequestParam("file") MultipartFile file){
try {
String encode = Base64Util.encode(file.getBytes());
String userId = FaceRecognitionUtil.faceSearch(encode);
if (StringUtils.isNotBlack(userId)){
return RespBean.error("人脸对比成功",userService.selectUserById(userId));
}
return RespBean.error("人脸对比失败");
} catch (IOException e) {
e.printStackTrace();
}
return RespBean.error("人脸对比失败");
}
@PostMapping("/face/check")
public RespBean check(@RequestParam("file") MultipartFile file){
try {
String encode = Base64Util.encode(file.getBytes());
boolean check = FaceRecognitionUtil.faceCheck(encode);
if (!check){
return RespBean.error("人脸检测失败");
}
return RespBean.ok("人脸检测成功");
} catch (IOException e) {
e.printStackTrace();
}
return RespBean.ok("人脸检测失败");
}
}
3.SpringSecurity会对所有请求路径拦截,所有要设置白名单放行
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/login","/verify","/face/**");
}
|