基于若依的人脸识别(2)——后端实现步骤
后端实现步骤
1. 创建 Spring Boot 项目
添加依赖:
<dependencies><!-- Web & REST --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- MyBatis --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.3.1</version></dependency><!-- MySQL --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!-- 百度AI SDK --><dependency><groupId>com.baidu.aip</groupId><artifactId>java-sdk</artifactId><version>4.16.1</version></dependency><!-- JWT --><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency>
</dependencies>
2. 配置百度 AI 参数
在application.properties
中添加:
baidu.face.appId=APP_ID
baidu.face.apiKey=API_KEY
baidu.face.secretKey=SECRET_KEY
baidu.face.imageType=BASE64
baidu.face.groupId=user_group
3. 创建百度 AI 工具类
package com.example.demo.utils;import com.baidu.aip.face.AipFace;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import java.util.HashMap;@Component
public class BaiduAiUtils {@Value("${baidu.face.appId}")private String APP_ID;@Value("${baidu.face.apiKey}")private String API_KEY;@Value("${baidu.face.secretKey}")private String SECRET_KEY;@Value("${baidu.face.imageType}")private String IMAGE_TYPE;@Value("${baidu.face.groupId}")private String GROUP_ID;private AipFace client;private HashMap<String, Object> options = new HashMap<>();@PostConstructpublic void init() {// 初始化AipFace客户端client = new AipFace(APP_ID, API_KEY, SECRET_KEY);// 设置人脸检测参数options.put("quality_control", "NORMAL"); // 图像质量控制options.put("liveness_control", "LOW"); // 活体检测等级}// 人脸搜索(用于登录)public String faceSearch(String imageBase64) {try {JSONObject res = client.search(imageBase64, IMAGE_TYPE, GROUP_ID, options);if (res.getInt("error_code") == 0) {JSONObject result = res.getJSONObject("result");if (result.has("user_list")) {var userList = result.getJSONArray("user_list");if (userList.length() > 0) {var user = userList.getJSONObject(0);double score = user.getDouble("score");if (score > 80) { // 相似度阈值return user.getString("user_id");}}}}} catch (Exception e) {e.printStackTrace();}return null;}// 人脸注册(用于首次绑定)public boolean faceRegister(String userId, String imageBase64) {try {JSONObject res = client.addUser(imageBase64, IMAGE_TYPE, GROUP_ID, userId, options);return res.getInt("error_code") == 0;} catch (Exception e) {e.printStackTrace();return false;}}
}
1. 类定义与依赖注入
@Component
public class BaiduAiUtils {@Value("${baidu.face.appId}")private String APP_ID;@Value("${baidu.face.apiKey}")private String API_KEY;@Value("${baidu.face.secretKey}")private String SECRET_KEY;@Value("${baidu.face.imageType}")private String IMAGE_TYPE;@Value("${baidu.face.groupId}")private String GROUP_ID;private AipFace client;private HashMap<String, Object> options = new HashMap<>();
@Component
:将此类标记为 Spring 组件,由 Spring 容器管理@Value
:从配置文件读取百度 AI 相关的认证信息和参数AipFace client
:百度人脸识别 API 的客户端options
:API 调用时的可选参数配置
APP_ID
、API_KEY
、SECRET_KEY
- 用途:百度 AI 开放平台的认证凭证,用于身份验证和 API 调用授权。
- 对应配置示例:
baidu.face.appId=你的AppID baidu.face.apiKey=你的API Key baidu.face.secretKey=你的Secret Key
- 说明:这些值需要在 百度 AI 开放平台 注册并创建人脸识别应用后获取。
IMAGE_TYPE
- 用途:指定图片的格式类型,告诉 API 如何解析传入的图像数据。
- 可选值:
BASE64
:图像数据为 Base64 编码字符串(常用)。URL
:图像数据为网络 URL 地址。FACE_TOKEN
:图像数据为人脸标识(face_token)。
- 对应配置示例:
baidu.face.imageType=BASE64
GROUP_ID
- 用途:指定人脸库的用户组 ID,用于在人脸搜索或注册时区分不同用户群体。
- 说明:百度人脸识别 API 允许将用户分组管理(例如按部门、角色等),每个组有唯一的
GROUP_ID
。 - 对应配置示例:
baidu.face.groupId=users_group_001
2. 核心组件
AipFace client
- 类型:百度 AI SDK 提供的人脸识别客户端类。
- 用途:封装了与百度人脸识别 API 的通信逻辑,通过它可以调用具体的 API 接口(如人脸搜索、注册等)。
- 初始化:在
@PostConstruct
注解的init()
方法中完成初始化:java
client = new AipFace(APP_ID, API_KEY, SECRET_KEY);
HashMap<String, Object> options
- 用途:存储调用百度 API 时的可选参数,用于控制 API 的行为(如活体检测等级、图像质量要求等)。
- 初始化与设置:在
init()
方法中预配置了两个常用参数:java
options.put("quality_control", "NORMAL"); // 图像质量控制(NORMAL表示中等质量) options.put("liveness_control", "LOW"); // 活体检测等级(LOW表示低等级检测)
- 常见可选参数:
quality_control
:图像质量控制,可选值为NONE
(不控制)、LOW
(低)、NORMAL
(中)、HIGH
(高)。liveness_control
:活体检测等级,可选值为NONE
、LOW
、MEDIUM
、HIGH
。max_user_num
:人脸搜索时返回的最大用户数。
2. 初始化方法
@PostConstruct
public void init() {// 初始化AipFace客户端client = new AipFace(APP_ID, API_KEY, SECRET_KEY);// 设置人脸检测参数options.put("quality_control", "NORMAL"); // 图像质量控制options.put("liveness_control", "LOW"); // 活体检测等级
}
@PostConstruct
:在 Bean 初始化完成后执行此方法- 初始化百度人脸识别客户端
- 设置两个关键参数:
quality_control
:控制图像质量,防止模糊或光照不佳的图片liveness_control
:活体检测等级,防止照片 / 视频欺骗
3. 人脸搜索方法(用于登录)
public String faceSearch(String imageBase64) {try {JSONObject res = client.search(imageBase64, IMAGE_TYPE, GROUP_ID, options);if (res.getInt("error_code") == 0) {JSONObject result = res.getJSONObject("result");if (result.has("user_list")) {var userList = result.getJSONArray("user_list");if (userList.length() > 0) {var user = userList.getJSONObject(0);double score = user.getDouble("score");if (score > 80) { // 相似度阈值return user.getString("user_id");}}}}} catch (Exception e) {e.printStackTrace();}return null;
}
- 功能:在指定用户组中搜索最相似的人脸
- 流程:
- 调用百度 API 进行人脸搜索
- 检查返回结果是否成功(error_code=0)
- 获取相似度最高的用户信息
- 验证相似度得分是否超过阈值(80 分)
- 返回匹配的用户 ID 或 null
1. 方法签名与参数
public String faceSearch(String imageBase64)
功能:在指定用户组(GROUP_ID
)中搜索与输入人脸最相似的用户。
参数:imageBase64
:待搜索的人脸图像的 Base64 编码字符串。
2. API 调用与结果处理
JSONObject res = client.search(imageBase64, IMAGE_TYPE, GROUP_ID, options);
关键参数:
imageBase64
:人脸图像数据。IMAGE_TYPE
:图像类型(如BASE64
)。GROUP_ID
:用户组 ID,指定在哪个用户组中搜索。options
:可选参数(如活体检测、质量控制)。-
返回值:百度 API 返回的 JSON 结果,包含错误码和匹配结果。
3. 结果解析流程
if (res.getInt("error_code") == 0) { ... }
错误码检查:
error_code == 0
表示 API 调用成功。- 其他错误码(如 110、111)表示认证失败或参数错误。
JSONObject result = res.getJSONObject("result");
if (result.has("user_list")) { ... }
结果结构:
result
:API 返回的结果数据。user_list
:匹配到的用户列表(按相似度降序排列)。
var userList = result.getJSONArray("user_list");
if (userList.length() > 0) { ... }
- 用户列表检查:
- 若列表为空,说明未找到匹配人脸。
var user = userList.getJSONObject(0);
double score = user.getDouble("score");
if (score > 80) { ... }
- 相似度评分:
score
:人脸相似度得分(范围 0-100)。score > 80
:自定义阈值,仅当相似度高于 80 分时才认为匹配成功。
4. 异常处理
catch (Exception e) {e.printStackTrace();
}
return null;
- 异常捕获:
- 捕获网络异常、JSON 解析异常等,并打印堆栈信息。
- 发生异常时返回
null
,表示搜索失败。
百度 API 返回结果示例
API 成功调用时返回的 JSON 结构示例:
{"error_code": 0,"error_msg": "SUCCESS","log_id": 4255671843335,"timestamp": 1695352327,"cached": 0,"result": {"face_token": "6c6a5f5d7a5e5f4b5d3e2c1a0b9c8d","user_list": [{"group_id": "users_group_001","user_id": "user123","user_info": "","score": 92.5 // 相似度得分}]}
}
4. 人脸注册方法(用于首次绑定)
public boolean faceRegister(String userId, String imageBase64) {try {JSONObject res = client.addUser(imageBase64, IMAGE_TYPE, GROUP_ID, userId, options);return res.getInt("error_code") == 0;} catch (Exception e) {e.printStackTrace();return false;}
}
- 功能:将用户人脸图像注册到指定用户组
- 流程:
- 调用百度 API 添加用户人脸
- 检查返回结果是否成功
- 返回操作结果(成功 / 失败)
4. 创建用户服务与控制器
package com.example.demo.service;import com.example.demo.entity.SysUser;
import com.example.demo.utils.BaiduAiUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class FaceLoginService {@Autowiredprivate BaiduAiUtils baiduAiUtils;@Autowiredprivate UserService userService; // 假设已有用户服务// 人脸登录验证public SysUser loginByFace(String imageBase64) {// 1. 调用百度AI人脸搜索String userId = baiduAiUtils.faceSearch(imageBase64);if (userId != null) {// 2. 查询用户信息return userService.getUserById(Long.valueOf(userId));}return null;}// 人脸注册public boolean registerFace(Long userId, String imageBase64) {return baiduAiUtils.faceRegister(userId.toString(), imageBase64);}
}
package com.example.demo.controller;import com.example.demo.entity.SysUser;
import com.example.demo.service.FaceLoginService;
import com.example.demo.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.HashMap;
import java.util.Map;@RestController
@RequestMapping("/api/face")
public class FaceLoginController {@Autowiredprivate FaceLoginService faceLoginService;@PostMapping("/login")public Map<String, Object> faceLogin(@RequestBody Map<String, String> params) {String imageBase64 = params.get("image");SysUser user = faceLoginService.loginByFace(imageBase64);Map<String, Object> result = new HashMap<>();if (user != null) {// 生成JWT TokenString token = JwtUtils.generateToken(user.getId());result.put("code", 200);result.put("message", "登录成功");result.put("token", token);result.put("user", user);} else {result.put("code", 401);result.put("message", "人脸识别失败");}return result;}@PostMapping("/register")public Map<String, Object> faceRegister(@RequestBody Map<String, String> params) {Long userId = Long.valueOf(params.get("userId"));String imageBase64 = params.get("image");boolean success = faceLoginService.registerFace(userId, imageBase64);return success ? Map.of("code", 200, "message", "人脸注册成功") :Map.of("code", 500, "message", "人脸注册失败");}
}