3.8 人脸识别登陆Controller

1、效果图

后台获取的数据

{"face_token":"efb5996c1707850f81e884ef190c984b","user_list":[{"score":91.080505371094,"group_id":"group1","user_id":"1","user_info":""}]}

2、注册百度ai

百度ai地址https://login.bce.baidu.com/?redirect=https%3A%2F%2Fconsole.bce.baidu.com%2F%3Ffromai%3D1#/aip/overviewhttps://login.bce.baidu.com/?redirect=https%3A%2F%2Fconsole.bce.baidu.com%2F%3Ffromai%3D1#/aip/overview

2.1 、使用免费百度ai步骤

1、点击人脸识别:跳转到服务

2、其间会有一些验证,创建应用

3、查看人脸库

4、新建组、用户

5、添加人脸照片

3、代码实现逻辑

基于Springboot框架搭建的,前端使用Vue,通过摄像机拍下照片后,请求后端人脸识别登陆服务,后台调用百度API人脸识别接口,进入百度
大脑搜索人脸识别即可获取官网的Secret Key,将前端获取的人脸信息的base64信息和你本地数据库里的人脸信息传到百度人脸识别的接口
进行人脸比对,返回一个json数据,result参数 带别人脸相似度, result可自己定义,从而实现人脸识别登录。

核心代码块

3.1、导入Maven依赖

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

3.2、 创建FaceUtil,获取ApiFace【单例】

package com.ruoyi.common.utils.face.utils;
import com.baidu.aip.face.AipFace;
import com.baidu.aip.util.Base64Util;
/*** 人脸识别工具*/
public class FaceUtil {private static final String APP_ID = "25236971";private static final String APP_KEY = "zLIZGY15wiEQh2utjwAGGW9C";private static final String SECRET_KEY = "Pzi4Ew6eWfZPINBkshlCO22OqADa777I";private static volatile AipFace client = new AipFace(APP_ID, APP_KEY, SECRET_KEY);// 创建单例避免多次获取sdkpublic static AipFace getClient(){client.setConnectionTimeoutInMillis(2000);client.setSocketTimeoutInMillis(60000);return client;}/*** 编码* @param form* @return*/public static String  encodeBase64(byte[] form){return Base64Util.encode(form);}/*** 解码* @param data* @return*/public static byte[] decodeBase64(String data){return Base64Util.decode(data);}
}

3.3 创建FaceResultUtil,统一处理请求

package com.ruoyi.common.utils.face.utils;
import com.ruoyi.common.utils.face.BizException;
import com.ruoyi.common.utils.face.constant.ErrorEnum;
import com.ruoyi.common.utils.face.constant.FaceConstant;
import com.ruoyi.common.utils.face.dto.FaceResult;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** 结果工具封装*/
public class FaceResultUtil {private static final Logger logger = LoggerFactory.getLogger("百度API接口请求结果解析");public static FaceResult isSuccess(JSONObject res){FaceResult result = parseJsonObject(res);if (!result.isSuccess()){// 对错误进行分类ErrorEnum errorEnum = ErrorEnum.getInstance(result.getErrorCode());if (errorEnum == null){throw new BizException("百度接口请求失败" + result.getErrorMsg());}else {throw new BizException(errorEnum.getCnDesc());}}return result;}/*** 解析JsonObject* @return*/private static FaceResult parseJsonObject(JSONObject res){FaceResult faceResult = FaceResult.builder().build();try {String logId = res.has(FaceConstant.LOG_ID) ? res.get(FaceConstant.LOG_ID).toString() : "0";int errorCode = res.has(FaceConstant.ERROR_CODE) ? res.getInt(FaceConstant.ERROR_CODE) : -1;String errorMsg = res.has(FaceConstant.ERROR_MSG) ? res.getString(FaceConstant.ERROR_MSG) : "";int cached = res.has(FaceConstant.CACHED) ? res.getInt(FaceConstant.CACHED) : 0;long timestamp = res.has(FaceConstant.TIMESTAMP) ? res.getLong(FaceConstant.TIMESTAMP) : 0;Object dataString = res.has(FaceConstant.RESULT) ? res.get(FaceConstant.RESULT) : "";com.alibaba.fastjson.JSONObject data = null;if (dataString != null) {data = com.alibaba.fastjson.JSONObject.parseObject(dataString.toString());}faceResult.setLogId(logId);faceResult.setErrorCode(errorCode);faceResult.setErrorMsg(errorMsg);faceResult.setCached(cached);faceResult.setTimestamp(timestamp);faceResult.setData(data);}catch (Exception e){logger.error("JSONObject解析失败", e);}return faceResult;}
}

3.4 创建FaceResult

package com.ruoyi.common.utils.face.dto;import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;/***请求百度API接口结果*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class FaceResult implements Serializable {private String logId;private String errorMsg;private int cached;private int errorCode;private long timestamp;private JSONObject data;public boolean isSuccess(){return 0 == this.errorCode ? true : false;}
}

3.5 创建ImageU

package com.ruoyi.common.utils.face.dto;
import com.ruoyi.common.utils.face.constant.ImageTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;/*** 图像对象*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ImageU implements Serializable {private ImageTypeEnum imageTypeEnum;private String data;
}

3.6 创建FaceUserDTO

package com.ruoyi.common.utils.face.dto;import com.ruoyi.common.utils.face.constant.FaceConstant;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class FaceUserDTO<T> implements Serializable {private String userId;private String groupId = FaceConstant.DEFAULT_GROUP_ID;private String faceToken;private T user;
}

3.7 创建FaceManage[关键类](重点)

package com.ruoyi.common.utils.face;import com.alibaba.fastjson.JSON;
import com.baidu.aip.face.FaceVerifyRequest;
import com.baidu.aip.face.MatchRequest;import com.ruoyi.common.utils.face.constant.ActionTypeEnum;
import com.ruoyi.common.utils.face.constant.FaceConstant;
import com.ruoyi.common.utils.face.constant.LivenessControlEnum;
import com.ruoyi.common.utils.face.constant.QualityControlEnum;
import com.ruoyi.common.utils.face.dto.FaceResult;
import com.ruoyi.common.utils.face.dto.FaceUserDTO;
import com.ruoyi.common.utils.face.dto.ImageU;
import com.ruoyi.common.utils.face.utils.FaceResultUtil;
import com.ruoyi.common.utils.face.utils.FaceUtil;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.util.ArrayList;
import java.util.HashMap;
import java.util.Objects;/***  人脸识别相关服务*/
public class FaceManage {private static final Logger logger = LoggerFactory.getLogger(FaceManage.class);/*** 人脸注册*/public static void faceRegister(FaceUserDTO userDTO, ImageU imageU){// 传入可选参数调用接口HashMap<String, String> options = new HashMap<String, String>();// 用户资料options.put("user_info", JSON.toJSONString(userDTO));// 图片质量options.put("quality_control", QualityControlEnum.LOW.name());// 活体检测控制options.put("liveness_control", LivenessControlEnum.NONE.name());// 操作方式options.put("action_type", ActionTypeEnum.REPLACE.name());String image = imageU.getData();String imageType = imageU.getImageTypeEnum().name();String groupId = userDTO.getGroupId();String userId = userDTO.getUserId();// 人脸注册JSONObject res = FaceUtil.getClient().addUser(image, imageType, groupId, userId, options);FaceResultUtil.isSuccess(res);logger.info("人脸注册成功");}/*** 人脸更新*/public static void faceUpdate(FaceUserDTO userDTO, ImageU imageU) {HashMap<String, String> options = new HashMap<String, String>();// 用户资料options.put("user_info", JSON.toJSONString(userDTO));// 图片质量options.put("quality_control", QualityControlEnum.LOW.name());// 活体检测控制options.put("liveness_control", LivenessControlEnum.NONE.name());// 操作方式options.put("action_type", ActionTypeEnum.REPLACE.name());String image = imageU.getData();String imageType = imageU.getImageTypeEnum().name();String groupId = userDTO.getGroupId();String userId = userDTO.getUserId();// 人脸更新JSONObject res = FaceUtil.getClient().updateUser(image, imageType, groupId, userId, options);FaceResultUtil.isSuccess(res);logger.info("人脸更新成功 {}", res.toString(2));}/*** 人脸删除*/public static void faceDelete(String userId, String groupId, String faceToken) {// 传入可选参数调用接口HashMap<String, String> options = new HashMap<String, String>();// 人脸删除JSONObject res = FaceUtil.getClient().faceDelete(userId, groupId, faceToken, options);FaceResultUtil.isSuccess(res);logger.info("人脸删除成功 {}", res.toString(2));}/*** 用户信息查询*/public static FaceUserDTO<String> findUser(String userId, String groupId) {HashMap<String, String> options = new HashMap<>();// 用户信息查询JSONObject res  = FaceUtil.getClient().getUser(userId, groupId, options);FaceResult result = FaceResultUtil.isSuccess(res);return JSON.parseObject(result.getData().toJSONString(), FaceUserDTO.class);}/*** 获取用户人脸列表* @throws Exception*/public static FaceResult faceGetList(String userId, String groupId){HashMap<String, String> options = new HashMap<String, String>();// 获取用户人脸列表JSONObject res = FaceUtil.getClient().faceGetlist(userId, groupId, options);return FaceResultUtil.isSuccess(res);}/*** 获取用户列表*/public static FaceResult listUserByGroupId(String groupId) {HashMap<String, String> options = new HashMap<String, String>();options.put("start", "0");options.put("length", "50");// 获取用户列表JSONObject res = FaceUtil.getClient().getGroupUsers(groupId, options);return FaceResultUtil.isSuccess(res);}/*** 删除用户*/public static void deleteUser(String userId, String groupId) {HashMap<String, String> options = new HashMap<String, String>();// 删除用户JSONObject res = FaceUtil.getClient().deleteUser(groupId, userId, options);FaceResultUtil.isSuccess(res);logger.info("用户删除成功 {}", res.toString(2));}/*** 创建用户组*/public static void addGroup(String groupId) {HashMap<String, String> options = new HashMap<String, String>();// 创建用户组JSONObject res = FaceUtil.getClient().groupAdd(groupId, options);FaceResultUtil.isSuccess(res);logger.info("创建用户组 {}", res.toString(2));}/*** 删除用户组*/public static void deleteGroup(String groupId){HashMap<String, String> options = new HashMap<String, String>();// 删除用户组JSONObject res = FaceUtil.getClient().groupDelete(groupId, options);FaceResultUtil.isSuccess(res);logger.info("删除用户组 {}", res.toString(2));}/*** 组列表查询*/public static FaceResult listGroup() {HashMap<String, String> options = new HashMap<String, String>();options.put("start", "0");options.put("length", "50");// 组列表查询JSONObject res = FaceUtil.getClient().getGroupList(options);return FaceResultUtil.isSuccess(res);}/*** 身份验证(没权限使用)*/public static FaceResult personVerify(String idCardNumber, String realName, ImageU imageU){HashMap<String, String> options = new HashMap<String, String>();options.put("quality_control", QualityControlEnum.LOW.name());options.put("liveness_control", LivenessControlEnum.NONE.name());// 身份验证JSONObject res = FaceUtil.getClient().personVerify(imageU.getData(), imageU.getImageTypeEnum().name(), idCardNumber, realName, options);return FaceResultUtil.isSuccess(res);}/*** 人脸对比*/public static int faceMatchScore(ImageU imageU1, ImageU imageU2){MatchRequest req1 = new MatchRequest(imageU1.getData(), imageU1.getImageTypeEnum().name());MatchRequest req2 = new MatchRequest(imageU2.getData(), imageU2.getImageTypeEnum().name());ArrayList<MatchRequest> requests = new ArrayList<MatchRequest>();requests.add(req1);requests.add(req2);JSONObject res = FaceUtil.getClient().match(requests);FaceResult result = FaceResultUtil.isSuccess(res);// 对结果进行特殊处理Integer score = result.getData().getInteger(FaceConstant.SCORE);return score == null ? 0 : score;}/*** 人脸是否对比成功* @param imageU1* @param imageU2* @param score   匹配分数* @return*/public static boolean isfaceMatch(ImageU imageU1, ImageU imageU2, Integer score){int defaultScore = FaceConstant.MATCH_SCORE;if (Objects.nonNull(score)){defaultScore = score;}return faceMatchScore(imageU1, imageU2) > defaultScore ? true : false;}/*** 人脸检测*/public static FaceResult faceDetect(ImageU imageU) {HashMap<String, String> options = new HashMap<String, String>();options.put("face_field", "age");options.put("max_face_num", "2");options.put("face_type", "LIVE");// 人脸检测JSONObject res = FaceUtil.getClient().detect(imageU.getData(), imageU.getImageTypeEnum().name(), options);return FaceResultUtil.isSuccess(res);}/*** 人脸搜索*/public static FaceResult faceSearch(String groupIds, ImageU imageU) {HashMap<String, String> options = new HashMap<String, String>();options.put("max_face_num", "1");options.put("max_user_num", "1");options.put("quality_control", QualityControlEnum.LOW.name());options.put("liveness_control", LivenessControlEnum.NONE.name());// 人脸搜索JSONObject res = FaceUtil.getClient().search(imageU.getData(), imageU.getImageTypeEnum().name(), groupIds, options);return FaceResultUtil.isSuccess(res);}/*** 活体检测*/public static FaceResult faceverify(ImageU imageU) {FaceVerifyRequest req = new FaceVerifyRequest(imageU.getData(), imageU.getImageTypeEnum().name());ArrayList<FaceVerifyRequest> list = new ArrayList<FaceVerifyRequest>();list.add(req);JSONObject res = FaceUtil.getClient().faceverify(list);return FaceResultUtil.isSuccess(res);}
}

3.8、测试

package com.ruoyi.common.utils.face;import com.alibaba.fastjson.JSON;
import com.example.common.face.FaceManage;
import com.example.common.face.constant.FaceConstant;
import com.example.common.face.constant.ImageTypeEnum;
import com.example.common.face.dto.FaceResult;
import com.example.common.face.dto.FaceUserDTO;
import com.example.common.face.dto.ImageU;
import com.example.common.face.utils.FaceUtil;
import com.example.common.utils.FilesUtil;
import org.apache.commons.io.IOUtils;
import org.junit.Test;import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.HashMap;/*** User: lanxinghua* Date: 2019/8/29 20:17* Desc: 人脸识别测试*/
public class FaceIdentificationTest {/*** 人脸注册,导入数据100张人脸图片*/@Testpublic void test00() throws Exception{FaceUserDTO<String> userDTO = new FaceUserDTO<>();userDTO.setGroupId("group2");String filePath = "/Users/cxx/Downloads/entryPhoto/";File[] files = FilesUtil.listFile(filePath);int j = 0;for (File file : files) {int id = 7000 + j;j++;userDTO.setUserId(String.valueOf(id));InputStream is = new FileInputStream(new File(filePath + file.getName()));byte[] bytes = IOUtils.toByteArray(is);String data = FaceUtil.encodeBase64(bytes);ImageU imageU = ImageU.builder().data(data).imageTypeEnum(ImageTypeEnum.BASE64).build();userDTO.setUser("用户信息 group1 - " + id);try {FaceManage.faceRegister(userDTO, imageU);}catch (Exception e){System.out.println("注册失败 msg:" + e.getMessage());continue;}}}/*** 人脸注册*/@Testpublic void test01() {FaceUserDTO<String> userDTO = new FaceUserDTO<>();userDTO.setGroupId("group1");userDTO.setUserId("6031");String image = "https://download.2dfire.com/mis/permanent/img2.jpg";ImageU imageU = ImageU.builder().data(image).imageTypeEnum(ImageTypeEnum.URL).build();userDTO.setUser("用户信息1");FaceManage.faceRegister(userDTO, imageU);}/*** 人脸更新*/@Testpublic void test02() {FaceUserDTO<String> userDTO = new FaceUserDTO();userDTO.setGroupId("group1");userDTO.setUserId("6031");String image = "https://download.2dfire.com/mis/permanent/img2.jpg";ImageU imageU = ImageU.builder().data(image).imageTypeEnum(ImageTypeEnum.URL).build();userDTO.setUser("用户信息1");// 人脸更新FaceManage.faceUpdate(userDTO, imageU);}/*** 人脸删除接口*/@Testpublic void test03() {String userId = "6030";String groupId = "group1";String faceToken = "5a1a8c17c40ea41264e8830017134972";FaceManage.faceDelete(userId, groupId, faceToken);}/*** 用户信息查询*/@Testpublic void test04() {HashMap<String, String> options = new HashMap<>();String userId = "6030";String groupId = "group1";// 用户信息查询FaceUserDTO<String> userDTO = FaceManage.findUser(userId, groupId);System.out.println("用户信息:" + JSON.toJSONString(userDTO));}/*** 获取用户人脸列表*/@Testpublic void test05() {String userId = "6030";String groupId = "group1";// 获取用户人脸列表FaceResult result = FaceManage.faceGetList(userId, groupId);String data = result.getData().getString(FaceConstant.FACE_LIST);System.out.println("人脸列表"+data);}/*** 获取用户列表*/@Testpublic void test06() {String groupId = "group1";FaceResult result = FaceManage.listUserByGroupId(groupId);// 获取用户列表String userIds = result.getData().getString(FaceConstant.USER_ID_LIST);System.out.println("userIds" + userIds);}/*** 删除用户*/@Testpublic void test07() {HashMap<String, String> options = new HashMap<String, String>();String groupId = "group1";String userId = "6031";// 删除用户FaceManage.deleteUser(userId, groupId);}/*** 创建用户组*/@Testpublic void test08() {String groupId = "group2";FaceManage.addGroup(groupId);}/*** 删除用户组*/@Testpublic void test09() {String groupId = "group2";FaceManage.deleteGroup(groupId);}/*** 组列表查询*/@Testpublic void test10() {FaceResult result = FaceManage.listGroup();String groupIds = result.getData().getString(FaceConstant.GROUP_ID_LIST);System.out.println(groupIds);}/*** 身份验证(没权限使用)*/@Testpublic void test11() {String image = "https://download.2dfire.com/mis/permanent/img1.jpg";ImageU imageU = ImageU.builder().data(image).imageTypeEnum(ImageTypeEnum.URL).build();String idCardNumber = "235151251";String name = "陈星星";FaceManage.personVerify(idCardNumber, name, imageU);}/*** 人脸对比*/@Testpublic void test12() {String image1 = "https://download.2dfire.com/mis/permanent/img1.jpg";String image2 = "https://download.2dfire.com/mis/permanent/img2.jpg";ImageU imageU1 = ImageU.builder().data(image1).imageTypeEnum(ImageTypeEnum.URL).build();ImageU imageU2 = ImageU.builder().data(image2).imageTypeEnum(ImageTypeEnum.URL).build();boolean match = FaceManage.isfaceMatch(imageU2, imageU1, 80);int matchScore = FaceManage.faceMatchScore(imageU2, imageU1);System.out.println("是否匹配:" + match);System.out.println("匹配等分:" + matchScore);}/*** 人脸检测*/@Testpublic void test13() {String image = "https://download.2dfire.com/mis/permanent/img1.jpg";ImageU imageU = ImageU.builder().data(image).imageTypeEnum(ImageTypeEnum.URL).build();FaceResult result = FaceManage.faceDetect(imageU);String data = result.getData().getString(FaceConstant.FACE_LIST);System.out.println(data);}/*** 人脸搜索*/@Testpublic void test14() {String image = "https://download.2dfire.com/mis/permanent/img1.jpg";ImageU imageU = ImageU.builder().data(image).imageTypeEnum(ImageTypeEnum.URL).build();String groupIds = "group1,group2";FaceResult result = FaceManage.faceSearch(groupIds, imageU);String users = result.getData().getString(FaceConstant.USER_LIST);System.out.println(users);}/*** 活体检测*/@Testpublic void test15() {String image = "https://download.2dfire.com/mis/permanent/img1.jpg";ImageU imageU = ImageU.builder().data(image).imageTypeEnum(ImageTypeEnum.URL).build();FaceResult result = FaceManage.faceverify(imageU);String users = result.getData().toJSONString();System.out.println(users);}
}

3.9人脸识别登陆Controller

  /*** 人脸登录*/@PostMapping( "/facelogin")@ResponseBodypublic AjaxResult facelogin(@RequestParam("file") String file,@RequestParam("groupId") String groupId) throws Exception {/*** base64转为multipartFile*/MultipartFile multipartFile = Base64DecodeMultipartFile.base64Convert(file);//很长if (multipartFile.isEmpty()) {throw new BizException("上传文件不能为空");}String groupIds = "group1";String data = FaceUtil.encodeBase64(multipartFile.getBytes());ImageU imageU = ImageU.builder().data(data).imageTypeEnum(ImageTypeEnum.BASE64).build();FaceResult result = FaceManage.faceSearch(groupIds, imageU);String users = result.getData().getString(FaceConstant.USER_LIST);if (StringUtils.isEmpty(users)){return AjaxResult.error("用户不存在");}JSONArray array = JSONObject.parseArray(users);JSONObject object = JSONObject.parseObject(array.get(0).toString());Integer score = object.getInteger(FaceConstant.SCORE);if (score == null){return AjaxResult.error("登录失败");}if (score >= FaceConstant.MATCH_SCORE){System.out.println(result.getData().toString());Long user_id = object.getLong("user_id");SysUser sysUser = sysUserService.selectUserById(user_id);/* 认证用户方法,可以自己写  */AjaxResult ajax = loginService.login(0,sysUser.getUserName());return ajax;}return AjaxResult.error("用户不存在");}

3.10 枚举,用到的一些辅助类

package com.ruoyi.common.utils.face;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;
import java.io.*;
import java.util.UUID;/*** base64转为multipartFile工具类* base64Convert*/public class Base64DecodeMultipartFile implements MultipartFile {private final byte[] imgContent;private final String header;public Base64DecodeMultipartFile(byte[] imgContent, String header) {this.imgContent = imgContent;this.header = header.split(";")[0];}@Overridepublic String getName() {return System.currentTimeMillis() + Math.random() + "." + header.split("/")[1];}@Overridepublic String getOriginalFilename() {return System.currentTimeMillis() + (int) Math.random() * 10000 + "." + header.split("/")[1];}@Overridepublic String getContentType() {return header.split(":")[1];}@Overridepublic boolean isEmpty() {return imgContent == null || imgContent.length == 0;}@Overridepublic long getSize() {return imgContent.length;}@Overridepublic byte[] getBytes() throws IOException {return imgContent;}@Overridepublic InputStream getInputStream() throws IOException {return new ByteArrayInputStream(imgContent);}@Overridepublic void transferTo(File dest) throws IOException, IllegalStateException {new FileOutputStream(dest).write(imgContent);}/*** base64转multipartFile** @param base64* @return*/public static MultipartFile base64Convert(String base64) {String[] baseStrs = base64.split(",");BASE64Decoder decoder = new BASE64Decoder();byte[] b = new byte[0];try {b = decoder.decodeBuffer(baseStrs[1]);} catch (IOException e) {e.printStackTrace();}for (int i = 0; i < b.length; ++i) {if (b[i] < 0) {b[i] += 256;}}return new Base64DecodeMultipartFile(b, baseStrs[0]);}
}
package com.ruoyi.common.utils.face;
/*** 自定义异常**/
public class BizException extends RuntimeException {private static final long serialVersionUID = 1L;private String msg;private int code = 500;public BizException(String msg) {super(msg);this.msg = msg;}public BizException(String msg, Throwable e) {super(msg, e);this.msg = msg;}public BizException(String msg, int code) {super(msg);this.msg = msg;this.code = code;}public BizException(String msg, int code, Throwable e) {super(msg, e);this.msg = msg;this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public int getCode() {return code;}public void setCode(int code) {this.code = code;}}
package com.ruoyi.common.utils.face.constant;/*** 操作方式*/
public enum ActionTypeEnum {APPEND("重复注册"),REPLACE("会用新图替换");ActionTypeEnum(String desc){this.desc = desc;}private String desc;public String getDesc() {return desc;}public void setDesc(String desc) {this.desc = desc;}
}
package com.ruoyi.common.utils.face.constant;/***  百度接口错误码,还需要加CODE看官方文档*/
public enum ErrorEnum {ERROR_ENUM_1(1, "Unknown error", "服务器内部错误,请再次请求"),ERROR_ENUM_13(13, "Get service token failed", "获取token失败"),ERROR_ENUM_222202(222202, "pic not has face", "图片中没有人脸"),ERROR_ENUM_222203(222203, "image check fail", "无法解析人脸"),ERROR_ENUM_222207(222207, "match user is not found", "未找到匹配的用户"),ERROR_ENUM_222209(222209, "face token not exist", "face token不存在"),ERROR_ENUM_222301(222301, "get face fail", "获取人脸图片失败"),ERROR_ENUM_223102(223102, "user is already exist", "该用户已存在"),ERROR_ENUM_223106(223106, "face is not exist", "该人脸不存在"),ERROR_ENUM_223113(223113, "face is covered", "人脸模糊"),ERROR_ENUM_223114(223114, "face is fuzzy", "人脸模糊"),ERROR_ENUM_223115(223115, "face light is not good", "人脸光照不好"),ERROR_ENUM_223116(223116, "incomplete face", "人脸不完整");ErrorEnum(int errorCode, String desc, String cnDesc){this.errorCode = errorCode;this.desc = desc;this.cnDesc = cnDesc;}private int errorCode;private String desc;private String cnDesc;public static ErrorEnum getInstance(int errorCode){for (ErrorEnum value : ErrorEnum.values()) {if (value.errorCode == errorCode){return value;}}return null;}public int getErrorCode() {return errorCode;}public void setErrorCode(int errorCode) {this.errorCode = errorCode;}public String getDesc() {return desc;}public void setDesc(String desc) {this.desc = desc;}public String getCnDesc() {return cnDesc;}public void setCnDesc(String cnDesc) {this.cnDesc = cnDesc;}
}
package com.ruoyi.common.utils.face.constant;public class FaceConstant {/*** 默认组别*/public static final String DEFAULT_GROUP_ID = "60030";/*** 匹配分数*/public static final int MATCH_SCORE = 80;public static final String RESULT = "result";public static final String LOG_ID = "log_id";public static final String ERROR_MSG = "error_msg";public static final String CACHED = "cached";public static final String ERROR_CODE = "error_code";public static final String TIMESTAMP = "timestamp";public static final String SCORE = "score";public static final String FACE_LIST = "face_list";public static final String FACE_TOKEN = "face_token";public static final String USER_ID_LIST = "user_id_list";public static final String GROUP_ID_LIST = "group_id_list";public static final String USER_LIST = "user_list";
}
package com.ruoyi.common.utils.face.constant;
/*** 图片类型*/
public enum  ImageTypeEnum {BASE64("BASE64", 2),URL("URL", 0),FACE_TOKEN("FACE_TOKEN", 0);ImageTypeEnum(String key, int size){this.key = key;this.size = size;}/*** key*/private String key;/*** 大小 单位:M*/private int size;public String getKey() {return key;}public void setKey(String key) {this.key = key;}public int getSize() {return size;}public void setSize(int size) {this.size = size;}
}
package com.ruoyi.common.utils.face.constant;/***  活体检测控制*/
public enum  LivenessControlEnum {NONE("不进行控制"),LOW("较低的活体要求(高通过率 低攻击拒绝率)"),NORMAL("一般的活体要求(平衡的攻击拒绝率, 通过率)"),HIGH("较高的活体要求");LivenessControlEnum(String desc){this.desc = desc;}private String desc;public String getDesc() {return desc;}public void setDesc(String desc) {this.desc = desc;}
}
package com.ruoyi.common.utils.face.constant;/***  图片质量控制*/
public enum QualityControlEnum {NONE("不进行控制"),LOW("较低的质量要求"),NORMAL("一般的质量要求"),HIGH("较高的质量要求");QualityControlEnum(String desc){this.desc = desc;}private String desc;public String getDesc() {return desc;}public void setDesc(String desc) {this.desc = desc;}
}

4、前端实现

<template><div class="login"><el-formref="loginForm":model="loginForm":rules="loginRules"class="login-form"><h3 class="title">管理系统</h3><el-tabs v-model="activeName" type="card" @tab-click="handleClick"><el-tab-pane label="账户登录" name="first"><el-form-item prop="username"><el-inputv-model="loginForm.username"type="text"auto-complete="off"placeholder="账号"><svg-iconslot="prefix"icon-class="user"class="el-input__icon input-icon"/></el-input></el-form-item><el-form-item prop="password"><el-inputv-model="loginForm.password"type="password"auto-complete="off"placeholder="密码"@keyup.enter.native="handleLogin"><svg-iconslot="prefix"icon-class="password"class="el-input__icon input-icon"/></el-input></el-form-item><el-form-item prop="code" v-if="captchaOnOff"><el-inputv-model="loginForm.code"auto-complete="off"placeholder="验证码"style="width: 63%"@keyup.enter.native="handleLogin"><svg-iconslot="prefix"icon-class="validCode"class="el-input__icon input-icon"/></el-input><div class="login-code"><img :src="codeUrl" @click="getCode" class="login-code-img" /></div></el-form-item><el-checkboxv-model="loginForm.rememberMe"style="margin: 0px 0px 25px 0px">记住密码</el-checkbox><el-form-item style="width: 100%"><el-button:loading="loading"size="medium"type="primary"style="width: 100%"@click.native.prevent="handleLogin"><span v-if="!loading">登 录</span><span v-else>登 录 中...</span></el-button><div style="float: right" v-if="register"><router-link class="link-type" :to="'/register'">立即注册</router-link></div></el-form-item></el-tab-pane><el-tab-pane label="人脸识别" name="second"><div class="testTrackingWrapper"><videoid="video"width="340"height="300"preloadautoplayloopmuted></video><canvas id="canvas" width="550" height="400"></canvas><div class="buttonWrapper"><button type="button" @click="submitPhoto">上传</button><button type="button" name="button" @click="openCamera">拍照</button></div></div></el-tab-pane></el-tabs></el-form><!--  底部  --><div class="el-login-footer"><span>Copyright © 2018-2021 nexauto All Rights Reserved.</span></div><img :src="data:image" /></div>
</template><script>
import { getCodeImg } from "@/api/login";
import Cookies from "js-cookie";
import { encrypt, decrypt } from "@/utils/jsencrypt";
require("../assets/js/tracking-min");
require("../assets/js/face-min.js");
require("../assets/js/dat.gui.min.js");
require("../assets/js/stats.min");
export default {name: "Login",data() {return {// open: false, //控制摄像头开关// video: null,image: "",activeName: "first",codeUrl: "",cookiePassword: "",loginForm: {username: "admin",password: "admin123",rememberMe: false,code: "",uuid: "",},loginRules: {username: [{ required: true, trigger: "blur", message: "请输入您的账号" },],password: [{ required: true, trigger: "blur", message: "请输入您的密码" },],code: [{ required: true, trigger: "change", message: "请输入验证码" }],},loading: false,// 验证码开关captchaOnOff: true,// 注册开关register: false,redirect: undefined,};},watch: {$route: {handler: function (route) {this.redirect = route.query && route.query.redirect;},immediate: true,},},created() {this.getCode();this.getCookie();},methods: {//选项卡点击事件handleClick(tab, event) {console.log(tab, event);if (tab.name == "first") {this.stopNavigator();} else {this.openCamera();}},getCode() {getCodeImg().then((res) => {this.captchaOnOff =res.captchaOnOff === undefined ? true : res.captchaOnOff;if (this.captchaOnOff) {this.codeUrl = "data:image/gif;base64," + res.img;this.loginForm.uuid = res.uuid;}});},getCookie() {const username = Cookies.get("username");const password = Cookies.get("password");const rememberMe = Cookies.get("rememberMe");this.loginForm = {username: username === undefined ? this.loginForm.username : username,password:password === undefined ? this.loginForm.password : decrypt(password),rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),};},handleLogin() {this.$refs.loginForm.validate((valid) => {if (valid) {this.loading = true;if (this.loginForm.rememberMe) {Cookies.set("username", this.loginForm.username, { expires: 30 });Cookies.set("password", encrypt(this.loginForm.password), {expires: 30,});Cookies.set("rememberMe", this.loginForm.rememberMe, {expires: 30,});} else {Cookies.remove("username");Cookies.remove("password");Cookies.remove("rememberMe");}this.$store.dispatch("Login", this.loginForm).then(() => {this.$router.push({ path: this.redirect || "/" }).catch(() => {});}).catch(() => {this.loading = false;if (this.captchaOnOff) {this.getCode();}});}});},//打开摄像头openCamera() {var _this = this;var video = document.getElementById("video");var canvas = document.getElementById("canvas");var context = canvas.getContext("2d");var tracker = new tracking.ObjectTracker("face");tracker.setInitialScale(4);tracker.setStepSize(2);tracker.setEdgesDensity(0.1);this.trackerTask = tracking.track("#video", tracker, { camera: true });tracker.on("track", function (event) {context.clearRect(0, 0, canvas.width, canvas.height);event.data.forEach(function (rect) {context.font = "11px Helvetica";context.fillText("已识别到人脸,请点击拍照", 100, 40);context.strokeStyle = "#a64ceb";context.strokeRect(rect.x, rect.y, rect.width, rect.height);});});},//提交submitPhoto() {let _this = this;let canvas = document.getElementById("canvas");let context = canvas.getContext("2d");let video = document.getElementById("video");context.drawImage(video, 0, 0, 500, 400);let formData=new FormData();let base64File=canvas.toDataURL(); formData.append("file",base64File);formData.append("groupId","group1");this.$store.dispatch("Facelogin", formData).then(() => {this.stopNavigator();this.$router.push({ path: this.redirect || "/" }).catch(() => {});}).catch(() => {this.loading = false;this.getCode();});},//关闭摄像头stopNavigator() {if (video && video !== null) {video.srcObject.getTracks()[0].stop();// this.open = true; //切换成打开摄像头}},},beforeDestroy() {this.stopNavigator();},
};
</script><style rel="stylesheet/scss" lang="scss">
.login {display: flex;justify-content: center;align-items: center;height: 100%;background-image: url("../assets/images/login-background.jpg");background-size: cover;
}
.title {margin: 0px auto 30px auto;text-align: center;color: #707070;
}.login-form {border-radius: 6px;background: #ffffff;width: 400px;padding: 25px 25px 5px 25px;.el-input {height: 38px;input {height: 38px;}}.input-icon {height: 39px;width: 14px;margin-left: 2px;}
}
.login-tip {font-size: 13px;text-align: center;color: #bfbfbf;
}
.login-code {width: 33%;height: 38px;float: right;img {cursor: pointer;vertical-align: middle;}
}
.el-login-footer {height: 40px;line-height: 40px;position: fixed;bottom: 0;width: 100%;text-align: center;color: #fff;font-family: Arial;font-size: 12px;letter-spacing: 1px;
}
.login-code-img {height: 38px;
}.testTrackingWrapper {height: 300px;width: 200px;position: relative;
}
video,
canvas {position: absolute;left: 0;right: 0;top: 0;
}
.buttonWrapper {position: absolute;left: 0;right: 0;bottom: 7%;
}
</style>

写的不好的地方,可以纠正,如出问题,鄙人可以交流学习:

百度AI实现Web端人脸识别登陆-Springboot-Vue/element-ui相关推荐

  1. 基于百度AI开发平台实现人脸识别登陆-Springboot

    一.效果图 后台获取的数据: 我们去百度智能云人脸库查看,正是这个用户 项目源码已经上传到github,整个项目是springboot项目,下载下来就可以体验了.本工程对百度人脸识别接口进行了封装,理 ...

  2. 基于百度AI开放平台的人脸识别

    文章目录 前言 人脸识别流程图 一.注册账号 二.创建应用 三.下载SDK文件 四.创建工具类 五.创建用于人脸识别的网页 1.引入css文件 2.创建注册按钮 3.创建模态框,用于捕捉人脸 4.引入 ...

  3. React native 接入百度AI活体检测、人脸识别 iOS版本

    前期准备工作参考:React native 接入百度AI活体检测.人脸识别 Android版本 iOS配置 1.将FaceSDK里面的文件导入到iOS项目 添加完之后是这样的 2.选择链接C++标准库 ...

  4. java 百度账号注册界面_基于百度AI开放平台的人脸识别的注册登录(1)

    百度ai开放平台首页 2.选择产品服务,人脸与人体识别,人脸识别选项.打开后如图所示 人脸识别 3.点击立即使用 3.jpg 4.点击创捷应用 创建应用 这一页大家按自己需求填写即可 5.创建完成后点 ...

  5. 微信小程序 |基于百度AI从零实现人脸识别小程序

    写在前面 针对互联网上已有的人脸识别小程序项目,很多只是基于手动拍照,然后上传到SDK进行识别.这一过程完全脱离实际场景!无法直接使用! 本文项目是基于微信摄像头中的实时视频帧数据,通过实时动态识别小 ...

  6. 基于百度AI开放平台的人脸识别及语音合成

    基于百度AI的人脸识别及语音合成课题 课题需求 (1)人脸识别 在Web界面上传人的照片,后台使用Java技术接收图片,然后对图片进行解码,调用云平台接口识别人脸特征,接收平台返回的人员年龄.性别.颜 ...

  7. 基于百度AI+jquery-webcam+servlet实现人脸识别登录,兼容各主流浏览器

    1.注册百度AI账号,获取到AI开发资格 详情参见个人博客:你的第一个人脸识别demo(http://www.cnblogs.com/guo-eric/p/8109411.html) 2.环境准备 首 ...

  8. 百度AI图像处理(V3版本)—人脸识别(人脸对比)调用教程(基于Python3-附Demo)

    首先来看一下识别的效果:这里需要完整代码以及SDK的请点击此处下载:百度人脸识别-人脸对比 首先需要注册百度账号并且创建对应的应用,这里具体方法如图: 访问:http://ai.baidu.com/  ...

  9. 百度AI开放平台集成人脸识别,离线采集有动作活体版本sdk

    前言 Android项目Android studio环境: 1.工程build.gradle版本号:3.2.1 2.app目录下的build.gradle配置:compileSdkVersion 28 ...

最新文章

  1. Oracle系统简介
  2. 基于TF-IDF编码进行文本聚类分析:文档成对相似性计算、层次聚类(链接矩阵、树形图dendrogram绘制、聚类标签)
  3. 第十一回:琴房外度曲生慕意 书店里软语救阿四[林大帅作品集]
  4. TortoiseGit安装过程
  5. 爬虫(十二):scrapy中spiders的用法
  6. [译] LINUX内核内存屏障
  7. python之Character string
  8. oracle12c备份和恢复,oracle12C使用RMAN备份和恢复
  9. 计算机系统常见故障分析与排除,电脑常见网络故障分析与排除方法
  10. 麦本本笔记本怎么U盘重装Win10系统教学?
  11. 实践“鱼塘养鱼论”,不断养鱼和捕鱼
  12. 16MHz贴片晶振智能电子产品的好帮手
  13. 解决加载libqxcb.so失败以及Linux库搜索顺序
  14. 阿里腾讯暑期实习面试被刷的经历
  15. LaTex 插入图片技巧
  16. MobileNetV1实战:使用MobileNetV1实现植物幼苗分类
  17. Arduino ESP8266固件bin升级四种方法
  18. 使用IDEA 的DBMS 链接达梦数据库
  19. NDI网络设备接口技术简介(2021版)
  20. xp系统更改计算机名BIOS设置,电脑安装XP系统的前Bios设置

热门文章

  1. Python爬取图片并命名
  2. BNUOJ 53073 【找规律】
  3. ZigBee协议栈安装失败解决方法
  4. 13项目管理--相关方管理
  5. Latex中调整多行公式行距(间距)的方法
  6. 三元运算符 php_使用PHP三元运算符
  7. 二分查找例题(二)洛谷P1163
  8. HG30-IIB型数字多功能校准仪
  9. HCIA的基础知识(1)
  10. CFileDialog 参数及返回值