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

news2024/11/25 2:49:26

前言

上一篇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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

整理mongodb文档:删

个人博客 整理mongodb文档:删 求关注&#xff0c;哪儿不足&#xff0c;求大佬们指出&#xff0c;哪儿写的不够通俗易懂跟清晰&#xff0c;也求指出 文章概叙 本文主要是介绍了删除数据的几个方法&#xff0c;主要还是在介绍deleteMany、deleteOne以及remove&#xff0c;对于…

IL汇编 ldarg 指令学习

IL汇编代码&#xff0c; .assembly extern mscorlib {} .assembly MathLib {.ver 1 : 0 : 1 : 0 }.module MathLib.dll.namespace MyMath { .class public ansi auto MathClass extends [mscorlib]System.Object{ .method public int32 GetSquare(int32) c…

Linux c++反汇编源码细节解释说明

示例c源码: int main(int argc, char** argv) {auto sk argc;int a 11 << sk;int b 19 argc;volatile int rv a b * 8;rv * sk;return rv; } GUN x86 64bit AT&T 汇编环境下用 g -O1 -Wa,-adhln ./main.cc命令反汇编 反汇编源码: 0000 89F9 movl %ed…

ESP32-CAM ——Blinker平台

ESP32-CAM&#xff0c;点灯云平台Blinker&#xff0c;MQTT协议&#xff0c;APP控制&#xff0c;Wifi视频监控&#xff0c;点灯&#xff0c;控制舵机。 一 环境搭建 两个宝藏网站 点灯科技 (diandeng.tech) 软件下载 - Arduino中文社区 第一次体验Arduino 按照上面教程安装ES…

C++笔记之两个类的实例之间传递参数的各种方法

C笔记之两个类的实例之间传递参数的各种方法 code review! 文章目录 C笔记之两个类的实例之间传递参数的各种方法1.构造函数参数传递2.成员函数参数传递3.友元函数4.友元类5.传递指针或引用6.静态成员变量7.静态成员函数8.全局变量或命名空间9.回调函数和函数指针10.观察者模…

【第五章 flutter学习之flutter进阶组件-上篇】

文章目录 一、列表组件1.常规列表2.动态列表 二、FridView组件三、Stack层叠组件四、AspectRatio Card CircleAvatar组件五、按钮组件六、Stack组件七、Wrap组件八、StatefulWidget有状态组件总结 一、列表组件 1.常规列表 children: const <Widget>[ListTile(leading: …

喀麦隆ECTN(BESC)申请流程

据CAMEROON喀麦隆法令&#xff0c;所有发货至喀麦隆的货物都必须申请ECTN(BESC)电子货物跟踪单。如果没有申请&#xff0c;将被视为触犯喀麦隆的条例&#xff0c;并在目的港受到严厉惩罚。ECTN是英语ELECTRONIC CARGO TRACKING NOTE的简称&#xff1b;BESC是法语BORDEREAU ELEC…

开关电源控制--bode图相角裕量的选择

什么是相角裕量 在Bode图中&#xff0c;相角裕量是指系统的相位裕量&#xff0c;用于评估系统的稳定性和频率响应特性。 Bode图是一种常用的频率响应图&#xff0c;将系统的增益和相位随频率变化的情况绘制出来。在Bode图中&#xff0c;相角裕量表示系统的相位与-180度&#…

ensp与虚拟机搭建测试环境

1.虚拟机配置 ①首先确定VMnet8 IP地址&#xff0c;若要修改IP地址&#xff0c;保证在启动Ensp前操作 ②尽量保证NAT模式 2.ensp配置 (1)拓扑结构 (2)Cloud配置 ①首先点击 绑定信息 UDP → 增加 ②然后点击 绑定信息 VMware ... → 增加 ③最后在 端口映射设置上点击双向通…

编译工具:CMake(二)| 最简单的实例[构建、解析、外部构建]

编译工具&#xff1a;CMake&#xff08;二&#xff09;| 最简单的实例[构建、解析、外部构建] 编写代码与文件构建工程解析PROJECT 指令的语法是&#xff1a;SET 指令的语法是&#xff1a;MESSAGE 指令的语法是&#xff1a;ADD_EXECUTABLE 指令${} 指令 外部构建 # 前言 按照程…

github 无语的问题,Host does not existfatal: Could not read from remote repository.

Unable to open connection: Host does not existfatal: Could not read from remote repository. image.png image.png image.png Please make sure you have the correct access rights and the repository exists. 如果github desktop和git pull 和git clone全部都出问题了&…

ebay儿童书包产品CPC认证

儿童书包是一种能够盛放书本或者文具的包。现在的书包五花八门&#xff0c;以普通的布料或者是帆布等制成&#xff0c;有背带&#xff0c;包内一般分栏。一般分三种&#xff0c;背在身后的&#xff0c;挎在肩上的&#xff0c;轮式&#xff08;可以拖行&#xff09;的。 一、美国…

探索未来:直播实时美颜SDK在增强现实(AR)直播中的前景

在AR直播中&#xff0c;观众可以与虚拟元素实时互动&#xff0c;为用户带来更加丰富、沉浸式的体验。那么&#xff0c;直播美颜SDK在AR中有哪些应用呢&#xff1f;下文小编将于大家一同探讨美颜SDK与AR有哪些关联。 一、AR直播与直播实时美颜SDK的结合 增强现实技术在直播中…

使用C#的窗体显示与隐藏动画效果方案 - 开源研究系列文章

今天继续研究C#的WinForm的显示动画效果。 上次我们实现了无边框窗体的显示动画效果(见博文&#xff1a;基于C#的无边框窗体动画效果的完美解决方案 - 开源研究系列文章 )&#xff0c;这次介绍的是未在任务栏托盘中窗体的显示隐藏动画效果的实现代码。 1、 项目目录&#xff1b…

(03)Unity HTC VRTK 基于 URP 开发记录

1.简介 本篇主要内容为&#xff1a;URP如何与VRTK结合、URP需要注意的地方、VRTK的功能进行阐述。 因项目本身要求要渲染出比较好的画质&#xff0c;所以抛弃了Unity默认渲染管线Built-in&#xff0c;使用URP进行渲染&#xff0c;当然也可以选HDRP&#xff0c;但考虑到后期项目…

STM32 4G学习(二)

特性参数 ATK-IDM750C是正点原子开发的一款高性能4G Cat1 DTU产品&#xff0c;支持移动4G、联通4G和电信4G手机卡。 它以高速率、低延迟和无线数传作为核心功能&#xff0c;可快速解决应用场景下的无线数传方案。 它支持TCP/UDP/HTTP/MQTT/DNS/RNDIS/NTP协议&#xff0c;支持…

第八篇: K8S Prometheus Operator实现Ceph集群企业微信机器人告警

Prometheus Operator实现Ceph集群企业微信告警 实现方案 我们的k8s集群与ceph集群是部署在不同的服务器上&#xff0c;因此实现方案如下&#xff1a; (1) ceph集群开启mgr内置的exporter服务&#xff0c;用于获取ceph集群的metrics (2) k8s集群通过 Service Endponit Ser…

Nacos源码 (2) 核心模块

返回目录 整体架构 服务管理&#xff1a;实现服务CRUD&#xff0c;域名CRUD&#xff0c;服务健康状态检查&#xff0c;服务权重管理等功能配置管理&#xff1a;实现配置管CRUD&#xff0c;版本管理&#xff0c;灰度管理&#xff0c;监听管理&#xff0c;推送轨迹&#xff0c;聚…

计算机组成原理-笔记-第一章

目录 一、第一章——计算机系统概述&#xff08;硬件软件&#xff09; 1、计算机发展 &#xff08;1&#xff09;小结 2、硬件的基本组成&#xff08;冯诺依曼机&#xff09; &#xff08;1&#xff09;冯诺依曼机——运算器为中心 &#xff08;2&#xff09;现代计算器结…

微服务 云原生:搭建 Harbor 私有镜像仓库

Harbor官网 写在文前&#xff1a; 本文中用到机器均为虚拟机 CentOS-7-x86_64-Minimal-2009 镜像。 基础设施要求 虚拟机配置达到最低要求即可&#xff0c;本次系统中使用 docker 24.0.4、docker-compose 1.29.2。docker 及 docker-compose 的安装可以参考上篇文章 微服务 &am…