基于若依的人脸识别(2)——后端实现步骤

发布于:2025-05-28 ⋅ 阅读:(27) ⋅ 点赞:(0)

后端实现步骤

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<>();

    @PostConstruct
    public 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_IDAPI_KEYSECRET_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:活体检测等级,可选值为 NONELOWMEDIUMHIGH
    • 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;
}
  • 功能:在指定用户组中搜索最相似的人脸
  • 流程:
    1. 调用百度 API 进行人脸搜索
    2. 检查返回结果是否成功(error_code=0)
    3. 获取相似度最高的用户信息
    4. 验证相似度得分是否超过阈值(80 分)
    5. 返回匹配的用户 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;
    }
}
  • 功能:将用户人脸图像注册到指定用户组
  • 流程:
    1. 调用百度 API 添加用户人脸
    2. 检查返回结果是否成功
    3. 返回操作结果(成功 / 失败)

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 {

    @Autowired
    private BaiduAiUtils baiduAiUtils;
    
    @Autowired
    private 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 {

    @Autowired
    private 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 Token
            String 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", "人脸注册失败");
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到