SpringBoot集成百度人脸识别实现登陆注册功能Demo(二)

前言

上一篇SpringBoot集成百度人脸demo中我使用的是调用本机摄像头完成人脸注册,本次demo根据业务需求的不同我采用文件上传的方式实现人脸注册。

效果演示

注册
在这里插入图片描述
后端响应数据:

在这里插入图片描述

登录

在这里插入图片描述
后端响应数据:

在这里插入图片描述

项目结构

在这里插入图片描述

后端代码实现

1、BaiduAiUtils工具类封装

package com.jzj.utils;

import com.baidu.aip.face.AipFace;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.HashMap;

/**
 * 百度AI工具类封装
 *
 * @author 黎明
 * @version 1.0
 * @date 2023/8/5 9:35
 */
@Component
@Slf4j
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 groupId;
    // 声明私有变量client,AipFace是百度人脸识别 API 的 Java 客户端类,用于与人脸识别服务进行通信。
    private AipFace client;
    // 用于存储一些参数配置(图片质量控制、活体检测控制)
    private HashMap<String, String> map = new HashMap<>();

    /*
    私有的构造函数,表明该类是一个单例类,只能通过静态方法获取实例
     */
    private BaiduAiUtils() {
        // 图片质量控制 NONE: 不进行控制 LOW:较低的质量要求 NORMAL: 一般的质量要求 HIGH: 较高的质量要求 默认 NONE
        map.put("quality_control", "NORMAL");
        // 活体检测控制 NONE: 不进行控制 LOW:较低的活体要求(高通过率 低拒绝率) NORMAL: 一般的活体要求(平衡的拒绝率, 通过率) HIGH: 较高的活体要求(高拒绝率 低通过率) 默认NONE
        map.put("liveness_control", "LOW");
    }

    /*
    用于在类初始化时执行client的初始化操作
     */
    @PostConstruct
    public void init() {
        client = new AipFace(APP_ID, API_KEY, SECRET_KEY);
    }

    /**
     * 人脸注册:用户照片存入人脸库中
     */
    public Boolean faceRegister(String userId, String image) {
        JSONObject res = client.addUser(image, IMAGE_TYPE, groupId, userId, map);
        log.info("人脸注册响应数据 :{}", res);
        Integer errorCode = res.getInt("error_code");
        return errorCode == 0 ? true : false;
    }

    /**
     * 人脸更新:更新人脸库中的用户照片
     */
    public Boolean faceUpdate(String userId, String image) {
        JSONObject res = client.updateUser(image, IMAGE_TYPE, groupId, userId, map);
        log.info("人脸更新响应数据 :{}", res);
        Integer errorCode = res.getInt("error_code");
        return errorCode == 0 ? true : false;
    }

    /**
     * 人脸检测:判断上传的图片中是否具有面部信息
     */
    public Boolean faceCheck(String image) {
        JSONObject res = client.detect(image, IMAGE_TYPE, map);
        log.info("人脸检测响应数据 :{}", res);
        if (res.has("error_code") && res.getInt("error_code") == 0) {
            JSONObject resultObject = res.getJSONObject("result");
            Integer faceNum = resultObject.getInt("face_num");
            return faceNum == 1 ? true : false;
        } else {
            return false;
        }
    }

    /**
     * 1.搜索人脸库中相似的人脸并返回数据
     * <p>
     * 2.判断人脸匹配得分(score)大于80分则认为是同一个人
     */
    public String faceSearch(String image) {
        JSONObject res = client.search(image, IMAGE_TYPE, groupId, map);
        log.info("人脸搜索响应数据 :{}", res);
        if (res.has("error_code") && res.getInt("error_code") == 0) {
            JSONObject result = res.getJSONObject("result");
            JSONArray userList = result.getJSONArray("user_list");
            if (userList.length() > 0) {
                JSONObject user = userList.getJSONObject(0);
                double score = user.getDouble("score");
                if (score > 80) {
                    return user.getString("user_id");
                }
            }
        }
        return null;
    }

}

2、FaceServiceImpl

package com.jzj.service.impl;

import com.jzj.service.FaceService;
import com.jzj.utils.BaiduAiUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * FaceService实现类
 *
 * @author 黎明
 * @version 1.0
 * @date 2023/8/5 9:53
 */
@Service
@Slf4j
public class FaceServiceImpl implements FaceService {
    // 注入BaiduAiUtils
    @Autowired
    private BaiduAiUtils baiduAiUtils;

    /**
     * 人脸登录
     *
     * @param imagebast64 图片base64编码
     * @return userId
     */
    @Override
    public String loginByFace(StringBuffer imagebast64) {
        // 处理base64编码内容
        String image = imagebast64.substring(imagebast64.indexOf(",") + 1, imagebast64.length());
        return baiduAiUtils.faceSearch(image);
    }

    /**
     * 人脸注册
     *
     * @param userId      用户Id
     * @param imagebast64 图片base64编码
     * @return ”“
     */
    @Override
    public Boolean registerFace(String userId, StringBuffer imagebast64) {
        // 处理base64编码内容
        String image = imagebast64.substring(imagebast64.indexOf(",") + 1, imagebast64.length());
        log.info("处理后的图片base64编码:{}",image);
        return baiduAiUtils.faceRegister(userId, image);
    }
}

3、FaceController

package com.jzj.controller;

import com.alibaba.fastjson.JSON;
import com.jzj.common.Result;
import com.jzj.service.FaceService;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.UUID;

/**
 * controller控制层
 *
 * @author 黎明
 * @version 1.0
 * @date 2023/8/5 10:01
 */
@RestController
@RequestMapping("/face")
@Slf4j
public class FaceController {
    // 注入FaceService
    @Autowired
    private FaceService faceService;

    /**
     * 人脸登录
     * @param request 图片base64编码
     * @return userId
     */
    @RequestMapping("/login")
    public Result searchface(@RequestBody String request) {
        StringBuffer image = new StringBuffer(request);
        String userId = faceService.loginByFace(image);

        /*
        判断人脸库中是否有改用户
         */
        if (StringUtils.hasText(userId)){
            // !null且不为空,返回用户ID,和状态码:0
            return Result.ok(userId);
        }
        return Result.err(userId);
    }

    /**
     * 人脸注册
     * @param request 图片base64编码
     * @return res
     */
    @PostMapping("/register")
    public Result registerFace(@RequestBody String request) {
        StringBuffer image = new StringBuffer(request);
        String userId = UUID.randomUUID().toString().substring(0, 4);
        Boolean registerFace = faceService.registerFace(userId, image);

        /*
        判断是否注册成功
         */
        if (registerFace){
            // 注册成功,返回用户ID、状态码:0
            return Result.ok(userId);
        }
        // 注册失败,返回用户ID、状态码:1
        return Result.err(userId);
    }
}

前端代码实现

1、register

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户注册</title>
    <script type="application/javascript" src="js/axios_0.18.0_axios.min.js"></script>
</head>
<body>
<h1>Register</h1>
<input type="file" id="fileInput">
<button id="registerBtn">注册</button>

<script>
    // 获取注册按钮元素,并为其添加点击事件监听器
    document.getElementById("registerBtn").addEventListener("click", function () {
        // 获取文件选择框元素和选择的文件
        var fileInput = document.getElementById("fileInput");
        var file = fileInput.files[0];

        // 验证图片格式
        if (file) {
            var allowedFormats = ['image/png', 'image/jpeg', 'image/jpg', 'image/bmp'];
            if (allowedFormats.includes(file.type)) {
                // 创建一个 FileReader 对象,用于读取文件的内容
                var reader = new FileReader();

                // 文件读取完成后的处理逻辑
                reader.onloadend = function () {
                    // 从读取的结果中提取图像数据的 Base64 编码部分,使用正则表达式去除前缀部分
                    const imageBase64 = reader.result
                    // 发送POST请求
                    axios.post('/face/register', {
                        imagebast64: imageBase64
                    }).then(function (response) {
                        // 请求成功处理逻辑
                        console.log("响应数据:", response.data);
                        console.log("用户userId:", response.data.userId);
                        console.log("用户注册状态码:", response.data.code);
                        if (response.data.code === 0) {
                            alert("注册成功! UserId: " + response.data.userId);
                            // 跳转到index页面
                            window.location.href = "https://www.baidu.com";
                        } else {
                            alert("注册失败!");
                        }
                    }).catch(function (error) {
                        // 请求失败处理逻辑
                        console.error("错误注册信息: ", error);
                    });
                };
                // 读取文件内容,并将其保存在 reader.result 中
                reader.readAsDataURL(file);
            } else {
                // 文件格式不符合要求,显示错误提示
                alert("只能上传PNG、JPG、JPEG和BMP格式的图片!");
            }
        }
    });
</script>
</body>
</html>

2、login

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>人脸识别登录</title>
  <script type="application/javascript" src="js/axios_0.18.0_axios.min.js"></script>
</head>
<body>
<h1>Login</h1>
<video id="video" width="320" height="240" autoplay></video>
<button id="loginBtn">登录</button>

<script>
  // 获取视频流
  navigator.mediaDevices.getUserMedia({ video: true, audio: false })
          .then(function(stream) {
            var video = document.getElementById("video");
            video.srcObject = stream;
          })
          .catch(function(error) {
            console.error("访问视频流出错: ", error);
          });

  // 登录事件监听
  document.getElementById("loginBtn").addEventListener("click", function() {
    var video = document.getElementById("video");
    var canvas = document.createElement('canvas');
    canvas.width = video.videoWidth;
    canvas.height = video.videoHeight;
    var context = canvas.getContext('2d');
    context.drawImage(video, 0, 0, canvas.width, canvas.height);
    var imageBase64 = canvas.toDataURL("image/jpeg");

    axios.post("/face/login", {
      imagebast64: imageBase64
    }).then(function(response) {
              var res = response.data;
              if (res.code === 0) {
                alert("登录成功! UserId: " + res.userId);
                // 跳转到index页面
                window.location.href = "welcome.html";
              } else {
                alert("登录失败!");
              }
            })
            .catch(function(error) {
              console.error("登录错误: ", error);
            });
  });
</script>
</body>
</html>

详细代码已放到gitee仓库需要的源码请自取,链接https://gitee.com/bitliming/baidu_face.git

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/63780.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++学习】STL容器——list

目录 一、list的介绍及使用 1.1 list的介绍 1.2 list的使用 1.2.1 list的构造 1.2.2 list iterator的使用 1.2.3 list capacity 1.2.4 list element access 1.2.5 list modifiers 1.2.6 list 迭代器失效 二、list的模拟实现 2.1 模拟实现list 三、list和vector的对比…

8月1日上课内容 第一章web基础与http协议

dns与域名 网络是基于tcp/ip协议进行通信和连接的 应用层--传输层---网络层----数据链路层-----物理层 ip地址&#xff0c;我们每一台主机都有一个唯一的地址标识(固定的ip地址)&#xff0c;区分用户和计算机通信。 ip地址:32位二进制数组成的&#xff0c;不方便记忆 192.168.…

SpringMVC -- REST风格开发,RESTful快速开发、RESTful注解开发

&#x1f40c;个人主页&#xff1a; &#x1f40c; 叶落闲庭 &#x1f4a8;我的专栏&#xff1a;&#x1f4a8; c语言 数据结构 javaweb 石可破也&#xff0c;而不可夺坚&#xff1b;丹可磨也&#xff0c;而不可夺赤。 REST 一、REST简介1.1REST风格简介 二、RESTful入门案例2.…

绘制曲线python

文章目录 import matplotlib.pyplot as plt# 提供的数据 x= [1,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2,2.1,2.2,2.3,2.4,2.5,2.6,2.7,2.8,2.9,3,3.1,3.2,3.3,3.4,3.5,3.6,3.7,3.8,3.9,4,4.1,4.2,4.3,4.4,4.5,4.6,4.7,4.8,4.9,5,5.1,5.2,5.3,5.4,5.5,5.6,5.7,5.8,5.9,6,6.1,6.2…

门面模式(C++)

定义 为子系统中的一组接口提供一个一致(稳定) 的界面&#xff0c;Facade模式定义了一个高层接口&#xff0c;这个接口使得这一子系统更加容易使用(复用)。 应用场景 上述A方案的问题在于组件的客户和组件中各种复杂的子系统有了过多的耦合&#xff0c;随着外部客户程序和各子…

代码随想录算法训练营day55

文章目录 Day55 判断子序列题目思路代码 不同的子序列题目思路代码 Day55 判断子序列 392. 判断子序列 - 力扣&#xff08;LeetCode&#xff09; 题目 给定字符串 s 和 t &#xff0c;判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些&#xff08;也可以…

java文件

一.File类 二.扫描指定目录&#xff0c;并找到名称中包含指定字符的所有普通文件&#xff08;不包含目录&#xff09;&#xff0c;并且后续询问用户是否要删除该文件 我的代码: import java.io.File; import java.io.IOException; import java.util.Scanner;public class Tes…

Excel功能总结

1&#xff09;每一张表格上都打印表头 “页面布局”-->“打印标题”-->页面设置“工作表”页-->打印标题“顶端标题行” 如&#xff1a;固定第1~2行&#xff0c;设置成“$1:$2” 2&#xff09;将页面内容打印在一页【缩印】 1.选好需要打印的区域&#xff0c;“页面布…

数据结构 | 利用二叉堆实现优先级队列

目录 一、二叉堆的操作 二、二叉堆的实现 2.1 结构属性 2.2 堆的有序性 2.3 堆操作 队列有一个重要的变体&#xff0c;叫作优先级队列。和队列一样&#xff0c;优先级队列从头部移除元素&#xff0c;不过元素的逻辑顺序是由优先级决定的。优先级最高的元素在最前&#xff…

全志D1-H (MQ-Pro)驱动 OV5640 摄像头

内核配置 运行 m kernel_menuconfig 勾选下列驱动 Device Drivers ---><*> Multimedia support --->[*] V4L platform devices ---><*> Video Multiplexer[*] SUNXI platform devices ---><*> sunxi video input (camera csi/mipi…

C++11 新特性 ---- 模板的优化

C11 模板机制:① 函数模板② 类模板模板的使用&#xff1a;① 范围&#xff1a;模板的声明或定义只能在全局或类范围进行&#xff0c;不可以在局部范围&#xff08;如函数&#xff09;② 目的&#xff1a;为了能够编写与类型无关的代码函数模板&#xff1a;- 格式&#xff1a;t…

软件工程:帕金森定律

在软件开发中&#xff0c;你是否遇到过这种情况&#xff1a; 团队要开发一个简单的购物车应用&#xff0c;项目预期时间是2周工期。负责开发的工程师默认利用完整的2周时间来完成任务。在第一周&#xff0c;工程师会认为任务很轻松&#xff0c;有充足的时间来完成任务&#xff…

SPM(Swift Package Manager)开发及常见事项

SPM怎么使用的不再赘述&#xff0c;其优点是Cocoapods这样的远古产物难以望其项背的&#xff0c;而且最重要的是可二进制化、对xcproj项目无侵入&#xff0c;除了网络之外简直就是为团队开发的项目库依赖最好的管理工具&#xff0c;是时候抛弃繁杂低下的cocoapods了。 一&…

Camunda 7.x 系列【2】开源工作流引擎框架

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Spring Boot 版本 2.7.9 本系列Camunda 版本 7.19.0 源码地址&#xff1a;https://gitee.com/pearl-organization/camunda-study-demo 文章目录 1. 前言2. 开源工作流引擎框架2.1 jBPM2.2 Activ…

Python识别抖音Tiktok、巨量引擎滑块验证码识别

由于最近比较忙&#xff0c;所以本周搞了一个相对简单的验证码&#xff0c;就是抖音Tiktok的滑块验证码&#xff0c;这也是接到客户的一个需求。这种验证码通常在电脑端登录抖音、巨量引擎的的时候出现。 首先看一下最终的效果&#xff1a; 验证码识别过程 1、利用爬虫采集图…

jenkins的cicd操作

cicd概念 持续集成&#xff08; Continuous Integration&#xff09; 持续频繁的&#xff08;每天多次&#xff09;将本地代码“集成”到主干分支&#xff0c;并保证主干分支可用 持续交付&#xff08;Continuous Delivery&#xff09; 是持续集成的下一步&#xff0c;持续…

【ArcGIS Pro二次开发】(57):地图系列

在ArcGIS Pro中&#xff0c;有一个地图系列&#xff0c;可以在一个布局中导出多个地图。 在SDK中为ArcGIS.Desktop.layout.MapSeries类和映射系列导出选项&#xff0c;可以以支持多页导出。 MapSeries类提供了一个静态CreateSpatialMapSeries方法&#xff0c;该方法使用指定的…

【0807作业】使用消息队列实现AB进程对话+使用共享内存实现A进程打印字符串,B进程逆置字符串,打印结果为【正序 逆序 正序 逆序】

作业一&#xff1a;使用消息队列实现AB进程对话 ① 打开两个终端&#xff0c;要求实现AB进程对话 A进程先发送一句话给B进程&#xff0c;B进程接收后打印B进程再回复一句话给A进程&#xff0c;A进程接收后打印重复1.2步骤&#xff0c;当收到quit后&#xff0c;要结束AB进程 ② …

K8s中的PV和PVC和监控

1.PV和PVC PV&#xff1a;持久化存储&#xff0c;对存储资源进行抽象&#xff0c;对外提供可以调用的地方&#xff08;类似&#xff1a;生产者&#xff09; PVC&#xff1a;用于调用&#xff0c;不需要关心内部实现细节&#xff08;类似&#xff1a;消费者&#xff09; 2.实…