web人脸登录
1,需要腾讯人脸第三方
腾讯人脸第三方申请步骤
2,相关表结构设计
create database faceDB;use faceDB;
-- 人脸表
create table face(
fid int primary key auto_increment COMMENT '主键',
face_base longtext COMMENT '图片数据 base_64编码',
create_time datetime COMMENT '插入时间',
vef_num int COMMENT '验证次数',
face_name varchar(100) COMMENT '人脸名称',
remark varchar(200) COMMENT '人脸备注',
face_status int COMMENT '人脸是否可用,(0==可用,1,不可用)',
update_extend1 varchar(300) COMMENT '扩展字段1',
update_extend2 varchar(300) COMMENT '扩展字段2',
update_extend3 varchar(300) COMMENT '扩展字段3'
);
-- 验证日志表
create table face_vef_log(
lid int primary key auto_increment COMMENT '主键',
vef_time datetime COMMENT '验证时间',
vef_code int COMMENT '返回code',
vef_msg varchar(200) COMMENT '返回的消息',
login_name varchar(100) COMMENT '验证人'
);
3,相关配置
tencentcloudapi:# 你的 secretIdsecretId: 你腾讯云的secretId# 你的 secretKeysecretKey: 你腾讯云的secretKey# 请求官方地址 不变endpoint: iai.tencentcloudapi.com#地域 可不变region: ap-shanghai
package com.face.config;import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.face.utils.JwtUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;/*** @author tanyongpeng* <p>des</p>**/
@Component
@Slf4j
public class FaceConfig implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String face_token = request.getHeader("face_token");Map<String,Object> infoMap = new HashMap<>();try{//token验证DecodedJWT tokenInfo = JwtUtils.getTokenInfo(face_token);//添加返回信息infoMap.put("msg","验证成功");return true;}catch (SignatureVerificationException e){e.printStackTrace();infoMap.put("msg","无效签名");}catch (TokenExpiredException e){infoMap.put("msg","token已过期");}catch (AlgorithmMismatchException e){infoMap.put("msg","算法不一致");}catch (Exception e){infoMap.put("msg","无效签名");}ObjectMapper objectMapper = new ObjectMapper();String mapInfoJson = objectMapper.writeValueAsString(infoMap);response.setContentType("application/json;charset=UTF-8");response.setCharacterEncoding("UTF-8");PrintWriter writer = response.getWriter();writer.write(mapInfoJson);return false;}
}
package com.face.server;import com.face.bean.result.FaceResult;
import com.face.utils.TimeUtils;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.iai.v20180301.IaiClient;
import com.tencentcloudapi.iai.v20180301.models.CompareFaceRequest;
import com.tencentcloudapi.iai.v20180301.models.CompareFaceResponse;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import java.util.HashMap;
import java.util.Map;/*** @author tanyongpeng* <p>调用腾讯接口</p>**/
@Component
@Data
@Slf4j
public class FaceContrastServer {@Value("${tencentcloudapi.secretId}")private String secretId;@Value("${tencentcloudapi.secretKey}")private String secretKey;@Value("${tencentcloudapi.endpoint}")private String endpoint;@Value("${tencentcloudapi.region}")private String region;//第一张是数据库图片,第二张是登录时验证图片public FaceResult faceContrast(String imageA, String imageB){FaceResult faceResult = new FaceResult();try{Credential cred = new Credential(secretId, secretKey);HttpProfile httpProfile = new HttpProfile();httpProfile.setEndpoint(endpoint);ClientProfile clientProfile = new ClientProfile();clientProfile.setHttpProfile(httpProfile);IaiClient client = new IaiClient(cred, region, clientProfile);CompareFaceRequest req = new CompareFaceRequest();req.setImageA(imageA);req.setImageB(imageB);CompareFaceResponse resp = client.CompareFace(req);faceResult.setScore(resp.getScore());faceResult.setCode(FaceResult.SUCCESS_CODE);} catch (TencentCloudSDKException e) {faceResult.setCode(FaceResult.FACE_ERROR);faceResult.setMsg(e.getMessage());}return faceResult;}
}
4,人脸注册,登录后端代码
package com.face.service.impl;import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import com.face.bean.Face;
import com.face.bean.result.FaceResult;
import com.face.mapper.FaceMapper;
import com.face.server.FaceContrastServer;
import com.face.service.FaceService;
import com.face.utils.JwtUtils;
import com.face.utils.TimeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/**
* @author typsusan
* @description 针对表【face】的数据库操作Service实现
* @createDate 2022-07-17 03:33:50
*/
@Service
public class FaceServiceImpl extends ServiceImpl<FaceMapper, Face>implements FaceService {@AutowiredFaceContrastServer faceContrastServer;@Overridepublic FaceResult vef(String imageBase) {imageBase = JSONUtil.parseObj(imageBase).getStr("imageBase");List<Face> faceList = lambdaQuery().orderByDesc(Face::getVefNum).list();FaceResult faceState = null;// 如果人脸库为空,则第一次登录为录入人脸if (faceList.size() == 0){return initFace(imageBase);}else {int faceLength = faceList.size();for (Face face : faceList) {FaceResult faceResult = faceContrastServer.faceContrast(face.getFaceBase(), imageBase);// 是否比对成功if (faceResult.getCode() == FaceResult.SUCCESS_CODE ){// 相似度是否大于80if (faceResult.getScore() > FaceResult.SATISFY_SCORE){if (face.getFaceStatus() == 0){// 成功lambdaUpdate().set(Face::getVefNum,face.getVefNum()+1).eq(Face::getFid,face.getFid()).update();faceResult.setMsg(TimeUtils.timeQuantum()+"好,"+face.getFaceName());faceResult.setName(face.getFaceName());Map<String,String> map = new HashMap<>();map.put("score",String.valueOf(faceResult.getScore()));map.put("faceName",faceResult.getName());faceResult.setToken(JwtUtils.genereteToken(map));return faceResult;}else {// 失败 人脸被禁用lambdaUpdate().set(Face::getVefNum,face.getVefNum()+1).eq(Face::getFid,face.getFid()).update();faceResult.setMsg(face.getFaceName()+",当前人脸被禁用");faceResult.setName(face.getFaceName());faceResult.setCode(FaceResult.FORBIDDEN_FACE);faceState = faceResult;// 就算上一张人脸被禁用还得往下执行// 可能当前用户存在多张人脸,if (faceLength == 1){return faceResult;}faceLength --;}}else {// 人脸库没有检测到人脸if (faceLength == 1){// 判断当前人脸是否被禁用,如被禁用,提示被禁用// 禁用优先级大于 没有检测到人脸return faceState != null?faceState:FaceResult.error(FaceResult.NOT_FOUND_FACE,"人脸库不存在该人脸",faceResult.getScore());}faceLength --;}}else {// 接口返回异常return faceResult;}}}// 空异常return FaceResult.error(FaceResult.NULL_ERROR,"空指针异常");}public FaceResult initFace(String imageBase){FaceResult faceResult = new FaceResult();Face face = new Face();face.setFaceBase(imageBase);face.setCreateTime(new Date());face.setVefNum(0);face.setFaceName("admin");face.setFaceStatus(0);boolean save = save(face);faceResult.setCode(FaceResult.INIT_FACE);faceResult.setMsg("人脸初始化"+(save?"成功":"失败")+","+(save?"请验证登录":"请稍后再试"));faceResult.setName(face.getFaceName());return faceResult;}
}
5,前端代码
/*** 获取 浏览器 拍照的权限*/
/*** 获取浏览器权限* @param option*/
function getCamera(option) {option.thisCancas = document.getElementById(option.canvasId);option.thisContext = option.thisCancas.getContext("2d");option.thisVideo = document.getElementById(option.videoId);option.thisVideo.style.display = "block";// 获取媒体属性,旧版本浏览器可能不支持mediaDevices,我们首先设置一个空对象if (navigator.mediaDevices === undefined) {navigator.mediaDevices = {};}// 一些浏览器实现了部分mediaDevices,我们不能只分配一个对象// 使用getUserMedia,因为它会覆盖现有的属性。// 这里,如果缺少getUserMedia属性,就添加它。if (navigator.mediaDevices.getUserMedia === undefined) {navigator.mediaDevices.getUserMedia = function (constraints) {// 首先获取现存的getUserMedia(如果存在)var getUserMedia =navigator.webkitGetUserMedia ||navigator.mozGetUserMedia ||navigator.getUserMedia;// 有些浏览器不支持,会返回错误信息// 保持接口一致if (!getUserMedia) {//不存在则报错return Promise.reject(new Error("getUserMedia is not implemented in this browser"));}// 否则,使用Promise将调用包装到旧的navigator.getUserMediareturn new Promise(function (resolve, reject) {getUserMedia.call(navigator, constraints, resolve, reject);});};}var constraints = {audio: false,video: {width: option.videoWidth,height: option.videoHeight,transform: "scaleX(-1)",},};navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {// 旧的浏览器可能没有srcObjectif ("srcObject" in option.thisVideo) {option.thisVideo.srcObject = stream;} else {// 避免在新的浏览器中使用它,因为它正在被弃用。option.thisVideo.src = window.URL.createObjectURL(stream);}option.thisVideo.onloadedmetadata = function (e) {option.thisVideo.play();};}).catch((err) => {console.log(err);});return option
}/*** 绘制图片* 返回格式为base64* @param option*/
function draw(option){option.thisContext.drawImage(option.thisVideo,0,0,option.videoWidth,option.videoHeight);return option.thisCancas.toDataURL("image/png");
}export default {getCamera,draw
}
<template><div><div class="login"></div><!--登录中间块--><div class="login-mid"><div class="login-mid-top"><div class="shadow-top-left"></div><div class="shadow-top-right"></div></div><div class="login-mid-mid"><!--捕获人脸区域--><div class="videoCamera-canvasCamera"><videoid="videoCamera":width="videoWidth":height="videoHeight"autoplay></video><canvasstyle="display: none"id="canvasCamera":width="videoWidth":height="videoHeight"></canvas><!--人脸特效区域--><div v-if="faceImgState" class="face-special-effects-2"></div><div v-else class="face-special-effects"></div></div><!--按钮区域--><div class="face-btn"><button @click="faceVef()">{{faceImgState?'正在识别中...':'开始识别'}}</button></div><!--消息区域--><div class="msg"><div class="server-msg">{{msg}}</div><div class="welcome">Welcome to face recognition</div></div></div><div class="login-mid-bot"><div class="shadow-bot-left"></div><div class="shadow-bot-right"></div></div></div></div></template>
<script>
import $camera from '../../camera/index.js'
export default {data() {return {videoWidth: 200,videoHeight: 200,msg:'',faceImgState:false,faceOption:{}};},mounted() {//调用摄像头this.faceOption = $camera.getCamera({videoWidth: 200,videoHeight: 200,thisCancas: null,thisContext: null,thisVideo: null,canvasId:'canvasCamera',videoId:'videoCamera'});//this.getCompetence();},methods: {// 调用后台接口faceVef(){// 开始绘制图片let imageBase = $camera.draw(this.faceOption)if (this.faceImgState){return}this.faceImgState = trueif (imageBase === '' || imageBase === null || imageBase === undefined){this.$message.error("图片数据为空")}else {this.$http.post("/face/vef",{imageBase}).then(res =>{console.log(res)this.faceImgState = false// 跳转首页if (res.data.code === 200){// 关闭摄像头this.faceOption.thisVideo.srcObject.getTracks()[0].stop();localStorage.setItem("face_token",res.data.token);localStorage.setItem("username",res.data.name);this.$message.success(res.data.msg)this.$router.push("/home")}if (res.data.code === 201){this.$message.success(res.data.msg)}},onerror =>{this.faceImgState = false})}}},
};
</script>
<style>
@import "./index.css";
</style>
6,实现实例
参考:项目后端地址face-easy
参考:项目前端地址face-ui
相关文章:
web人脸登录
1,需要腾讯人脸第三方 腾讯人脸第三方申请步骤 2,相关表结构设计 create database faceDB;use faceDB; -- 人脸表 create table face( fid int primary key auto_increment COMMENT 主键, face_base longtext COMMENT 图片数据 base_64编码, create_tim…...
C++数字
目录 一、什么是数字 二、定义数字 三、数学运算 四、随机数 一、什么是数字 通常,当我们需要用到数字时,我们会使用原始的数据类型,如 int、short、long、float 和 double 等等。这些用于数字的数据类型,其可能的值和数值范围…...
【python】用plotly绘制正二十面体
文章目录顶点棱实现正二十面体plotly 的 Python 软件包是一个开源的代码库,它基于 plot.js,而后者基于 d3.js。我们实际使用的则是一个对 plotly 进行封装的库,名叫 cufflinks,能让你更方便地使用 plotly 和 Pandas 数据表协同工作…...
[Datawhale][CS224W]图机器学习(五)
这里写目录标题一、Deepwalk1.1 预备知识1.2 Deepwalk介绍1.3 Embedding1.4 word2Vec 词向量,词嵌入1.5 random Walk随机游走1.6 DeepWalk 核心代码Random WalkWord2vecDeepWalk应用1.7 DeepWalk优缺点二、Node2Vec2.1 图嵌入2.2 Node2Vec优化目标顶点序列采样策略2…...
Windows部署Jar包的三种方式
文章目录1、cmd命令启动2、bat脚本启动2.1 启动jar包2.2 关闭服务3、使用WinSW3.1 重命名3.2 xml配置3.3 安装服务3.4 卸载服务3.5 启动和停止服务1、cmd命令启动 这种方式比较简单,但是窗口关闭后服务也就被杀死了,命令如下 java -jar xxx.jar2、bat脚…...
【图像分类】卷积神经网络之AlexNet网络模型结构详解
写在前面: 首先感谢兄弟们的关注和订阅,让我有创作的动力,在创作过程我会尽最大能力,保证作品的质量,如果有问题,可以私信我,让我们携手共进,共创辉煌。 1. 前言 LeNet5网络模型提出之后,卷积神经网络在很长一段时间都没有长足的发展,主要有以下两个原因: 1.1 训…...
学习动漫插画的网络班排行榜
很多小伙伴不知道动漫插画培训机构哪个好,找不到靠谱的插画班,今天给大家整理了国内动漫插画培训机构排名! 一:动漫插画培训机构排名 1、轻微课(五颗星) 主打课程有日系插画、游戏原画、古风插画、动漫漫画…...
SpringCloud第五讲 Nacos注册中心-服务注册到Nacos
1.引入依赖: 在父工程中添加spring-cloud-alibaba的管理依赖 <!-- Nacos的管理依赖--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version…...
IP地理位置定位技术原理是什么
IP地理位置定位技术的原理是基于IP地址的网络通信原理和基础上的。它利用IP地址所包含的一些信息,如网络前缀和地址段,以及ISP的IP地址归属地数据库,来推测IP地址所对应的地理位置。具体来说,IP地址是由32位二进制数字组成的&…...
j-vxe-table 下拉搜索选择框数据加载过多导致前端崩溃问题
Jeeg-boot j-vxe-table 下拉搜索选择框数据加载过多导致前端崩溃问题 最近用到了Jeeg-boot j-vxe-table的组件,这组件时真J8难用,还好多BUG,想用个slot插槽也用不了,好像官方写了个基础就没怎么管了。😑 问题…...
Java国际化ResourceBundle详解
在Java开发中,ResourceBundle是一种方便地管理本地化资源的机制。它可以使得程序能够根据当前系统环境的语言和国家/地区来自动加载相应的本地化资源文件,从而避免了硬编码和减少了重复的代码。以下是使用ResourceBundle的基本步骤: 1. 准备…...
一文高端Android性能优化-总结篇
以下从几个方面来总结一下Android的性能优化:1:界面卡顿优化2:内存优化3:App启动优化界面卡顿优化Android的界面为每秒60帧,即必须在16ms内完成1帧的绘制,如果某个方法耗时过程,导致16ms内无法完…...
深入讲解CFS组调度!(上)
注:本文缩写说明 一、CFS组调度简介 1.1. 存在的原因 总结来说是希望不同分组的任务在高负载下能分配可控比例的CPU资源。为什么会有这个需求呢,比如多用户计算机系统每个用户的所有任务划分到一个分组中,A用户90个相同任务,而B…...
大数据实操项目分享:餐饮智能推荐服务在线实习项目
项目背景:在“互联网"背景下,餐饮企业的经营方式发生了很大的变革:团购和020拓宽了销售 渠道,电子点餐、店内WIFI等信息技术提升了服务水平,大数据、私人定制更好地满足了细分市场的需求等。但是与此同时…...
代码随想录day38
动态规划五部曲 确定dp数组以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组 509. 斐波那契数 https://leetcode.cn/problems/fibonacci-number/ class Solution {public int fib(int n) {if(n0) return 0;if(n<3) return 1;int[] dp new int[n]…...
《计算机网络:自顶向下方法》实验5:TCP
Q1 包含HTTP POST消息的TCP报文段的序号是多少?注意:为了发现POST 命令, 你需要在wireshark底部的报文内容域窗口中去查找,查找数据中包含 “POST”的段。 如图所示,由报文中的POST 和 HTTP/1.1可知,其包含HTTP POST消息; TCP报文段的序号可见TCP报文: Sequence Number:…...
【踩坑指南】Stable Diffusion 服务器端部署笔记
文章目录下载github文件配置环境ckpt文件权重下载生成图像NSFW检查(瑟图过滤)下载github文件 https://github.com/CompVis/stable-diffusion 这个网址,下载压缩包解压,也可以用git clone下载 配置环境 这一步坑最多,…...
[qiankun]-多页签缓存
[qiankun]-多页签缓存环境功能需求多页签缓存方案方案1.主服务进行html替换方案2.微服务vnode 替换方案3.每个微服务都不卸载微服务加载方式的选择微服务的路由路径选择微服务的缓存工具微服务的容器使用tab作为微服务的挂载容器使用微服务路由作为微服务的挂载容器场景描述微服…...
2|电子技术|数字电子技术基础|雨课堂习题|考前回顾
A/DD/A转化横向与阵列 相乘,竖向为或阵列 相加!功率放大电路克服交越失真,是在乙类的基础上增加两个二极管,使微导通,使三极管导通时间大于半个周期,小于一个周期,构成甲乙类工作状态。选择填空…...
vue+echarts:圆形柱状图设置角度和最大值
第020个点击查看专栏目录本示例是显示圆形的柱状图,angleAxis设置一个max, angleAxis上startAngle:90 , 将0点设置为最顶点。 文章目录示例效果示例源代码(共100行)相关资料参考专栏介绍示例效果 示例源代码…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
