SpringBoot+SeetaFace6搭建人脸识别平台

news/2024/12/21 23:54:18/文章来源:https://www.cnblogs.com/yanpeng19940119/p/18451538

前言

最近多个项目需要接入人脸识别功能,之前的方案是使用百度云api集成,但是后续部分项目是内网部署及使用,考虑到接入复杂程度及收费等多种因素,决定参考开源方案自己搭建,保证服务的稳定性与可靠性

项目地址:https://gitee.com/code2roc/fastface

设计

经过检索对别多个方案后,使用了基于seetaface6+springboot的方式进行搭建,能够无缝接入应用

seetaface6是中科视拓最新开源的商业正式版本,包含人脸识别的基本能力:人脸检测、关键点定位、人脸识别,同时增加了活体检测、质量评估、年龄性别估计

官网地址:https://github.com/SeetaFace6Open/index

使用对接的sdk是tracy100大神的封装,支持 jdk8-jdk14,支持windows和Linux,无需考虑部署问题,直接使用jar包实现业务即可,内部同时封装了bean对象spring能够开箱即用

官网地址:https://github.com/tracy100/seetaface6SDK

系统目标实现人脸注册,人脸比对,人脸查找基础功能即可

实现

引用jar包

        <dependency><groupId>com.seeta.sdk</groupId><artifactId>seeta-sdk-platform</artifactId><scope>system</scope><version>1.2.1</version><systemPath>${project.basedir}/lib/seetaface.jar</systemPath></dependency>

bean对象注册

FaceDetectorProxy为人脸检测bean,能够检测图像中是否有人脸

FaceRecognizerProxy为人脸比对bean,能够比对两张人脸的相似度

FaceLandmarkerProxy为人脸关键点bean,能够检测人脸的关键点,支持5个点和68个点

@Configuration
public class FaceConfig {@Value("${face.modelPath}")private String modelPath;@Beanpublic FaceDetectorProxy faceDetector() throws FileNotFoundException {SeetaConfSetting detectorPoolSetting = new SeetaConfSetting(new SeetaModelSetting(0, new String[]{modelPath + File.separator + "face_detector.csta"}, SeetaDevice.SEETA_DEVICE_CPU));FaceDetectorProxy faceDetectorProxy = new FaceDetectorProxy(detectorPoolSetting);return faceDetectorProxy;}@Beanpublic FaceRecognizerProxy faceRecognizer() throws FileNotFoundException {SeetaConfSetting detectorPoolSetting = new SeetaConfSetting(new SeetaModelSetting(0, new String[]{modelPath + File.separator + "face_recognizer.csta"}, SeetaDevice.SEETA_DEVICE_CPU));FaceRecognizerProxy faceRecognizerProxy = new FaceRecognizerProxy(detectorPoolSetting);return faceRecognizerProxy;}@Beanpublic FaceLandmarkerProxy faceLandmarker() throws FileNotFoundException {SeetaConfSetting detectorPoolSetting = new SeetaConfSetting(new SeetaModelSetting(0, new String[]{modelPath + File.separator + "face_landmarker_pts5.csta"}, SeetaDevice.SEETA_DEVICE_CPU));FaceLandmarkerProxy faceLandmarkerProxy = new FaceLandmarkerProxy(detectorPoolSetting);return faceLandmarkerProxy;}
}

在使用相关bean对象时,需要进行library的本地注册,指定cpu还是gpu模式

LoadNativeCore.LOAD_NATIVE(SeetaDevice.SEETA_DEVICE_CPU)

人脸检测

    public FaceEnum.CheckImageFaceStatus getFace(BufferedImage image) throws Exception {SeetaImageData imageData = SeetafaceUtil.toSeetaImageData(image);SeetaRect[] detects = faceDetectorProxy.detect(imageData);if (detects.length == 0) {return FaceEnum.CheckImageFaceStatus.NoFace;} else if (detects.length == 1) {return FaceEnum.CheckImageFaceStatus.OneFace;} else {return FaceEnum.CheckImageFaceStatus.MoreFace;}}

人脸比对

    public FaceEnum.CompareImageFaceStatus compareFace(BufferedImage source, BufferedImage compare) throws Exception {float[] sourceFeature = extract(source);float[] compareFeature = extract(compare);if (sourceFeature != null && compareFeature != null) {float calculateSimilarity = faceRecognizerProxy.calculateSimilarity(sourceFeature, compareFeature);System.out.printf("相似度:%f\n", calculateSimilarity);if (calculateSimilarity >= CHECK_SIM) {return FaceEnum.CompareImageFaceStatus.Same;} else {return FaceEnum.CompareImageFaceStatus.Different;}} else {return FaceEnum.CompareImageFaceStatus.LostFace;}}

人脸关键点

    private float[] extract(BufferedImage image) throws Exception {SeetaImageData imageData = SeetafaceUtil.toSeetaImageData(image);SeetaRect[] detects = faceDetectorProxy.detect(imageData);if (detects.length > 0) {SeetaPointF[] pointFS = faceLandmarkerProxy.mark(imageData, detects[0]);float[] features = faceRecognizerProxy.extract(imageData, pointFS);return features;}return null;}

人脸数据库

  • 注册
    public long registFace(BufferedImage image) throws Exception {long result = -1;SeetaImageData imageData = SeetafaceUtil.toSeetaImageData(image);SeetaRect[] detects = faceDetectorProxy.detect(imageData);if (detects.length > 0) {SeetaPointF[] pointFS = faceLandmarkerProxy.mark(imageData, detects[0]);result = faceDatabase.Register(imageData, pointFS);faceDatabase.Save(dataBasePath);}return result;}
  • 查找
    public long queryFace(BufferedImage image) throws Exception {long result = -1;SeetaImageData imageData = SeetafaceUtil.toSeetaImageData(image);SeetaRect[] detects = faceDetectorProxy.detect(imageData);if (detects.length > 0) {SeetaPointF[] pointFS = faceLandmarkerProxy.mark(imageData, detects[0]);long[] index = new long[1];float[] sim = new float[1];result = faceDatabase.QueryTop(imageData, pointFS, 1, index, sim);if (result > 0) {float similarity = sim[0];if (similarity >= CHECK_SIM) {result = index[0];} else {result = -1;}}}return result;}
  • 删除
    public long deleteFace(long index) throws Exception {long result = faceDatabase.Delete(index);faceDatabase.Save(dataBasePath);return result;}

拓展

集成了face-api.js,实现简单的张张嘴,摇摇头活体检测,精确度不是很高,作为一个参考选项

官网地址:https://github.com/justadudewhohacks/face-api.js

加载模型

        Promise.all([faceapi.loadFaceDetectionModel('models'),faceapi.loadFaceLandmarkModel('models')]).then(startAnalysis);function startAnalysis() {console.log('模型加载成功!');var canvas1 = faceapi.createCanvasFromMedia(document.getElementById('showImg'))faceapi.detectSingleFace(canvas1).then((detection) => {if (detection) {faceapi.detectFaceLandmarks(canvas1).then((landmarks) => {console.log('模型预热调用成功!');})}})}

打开摄像头

	<video id="video" muted playsinline></video>function AnalysisFaceOnline() {var videoElement = document.getElementById('video');// 检查浏览器是否支持getUserMedia APIif (navigator.mediaDevices.getUserMedia) {navigator.mediaDevices.getUserMedia({ video: { facingMode: "user" } }) // 请求视频流.then(function(stream) {videoElement.srcObject = stream; // 将视频流设置到<video>元素videoElement.play();}).catch(function(err) {console.error("获取摄像头错误:", err); // 处理错误});} else {console.error("您的浏览器不支持getUserMedia API");}}

捕捉帧计算关键点

function vedioCatchInit() {video.addEventListener('play', function() {function captureFrame() {if (!video.paused && !video.ended) {// 设置canvas的尺寸与视频帧相同canvas.width = 200;canvas.height = 300;// 绘制当前视频帧到canvascontext.drawImage(video, 0, 0, canvas.width, canvas.height);// 将canvas内容转换为data URL//outputImage.src = canvas.toDataURL('image/png');// 可以在这里添加代码将data URL发送到服务器或进行其他处理faceapi.detectSingleFace(canvas).then((detection) => {if (detection) {faceapi.detectFaceLandmarks(canvas).then((landmarks) => {})} else {console.log("no face")}})// 递归调用以持续捕获帧setTimeout(captureFrame, 100); // 每500毫秒捕获一次}}captureFrame(); // 开始捕获帧});}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

day02_基本的DOS命令

电脑常用快捷键 常用快捷键快捷键 作用CTRL + c 复制CTRL + v 粘贴CTRL + x 剪切CTRL + z 撤销CTRL + s 保存alt + f4 关闭窗口del 删除shift + del 强制删除Windows + r 打开 “运行” 窗口windows + e 打开 “我的文档”ctrl + alt + del 锁定/切换用户/注销/更改密码/任务管…

组态也能开发WEB前端 | uiotos致敬amis、nodered、appsmith、codewave、goview、dataroom、iotrouter、FUXA、乐吾乐

WEB组态开发SCADA、HMI画面、大屏可视化,还比较常见。比如下面: UIOTOS组态示例 那么常规WEB前端功能,组态能否一并做了呢?比如下面这种: UIOTOS前端示例 答案是可以的!UIOTOS支持页面无限嵌套,能实现原型即应用。现在就以一个具体小示例介绍如何实现的。 效果 如下所示…

GUI无代码小示例 - 工作流连线实现0/1连续翻转

效果 如下所示,连续点击按钮,输出0、1、0、1...。 步骤新建页面,拖入组件拖入3个组件:数学计算、输入框、按钮。如下所示: 连线和配置按钮点击 → 函数执行1减去输入,作为函数输出这样,当首次执行时,默认操作数1将减去输入的1,输出0。 函数输出→ 输入框 → 函数输入 …

Java生成条形码(亲测可通过扫码枪扫出)

Java生成条形码(亲测可通过扫码枪扫出) 秃秃爱健身该博客介绍了如何在Java项目中通过barcode4j库生成Code128条形码,解决了条形码扫不出或美观度不足的问题。提供了相关代码示例,包括Maven依赖、工具类和生成条形码的方法,可以自定义条形码的高度、宽度、是否留白和隐藏文…

点“亮”户外应用场景,来看触想高亮显示器TPC-M8的硬实力!

工业显示器作为信息可视化和人机交互的重要媒介,正在越来越多领域担当关键任务,工业显示器的可读性及耐用性,影响应用体验、设备安全和生产效率。尤其在户外,面对高低温、灰尘雨水、强光紫外线等极端因素,常规性能的工业显示器已不足以覆盖户外高风险应用需求。为此,触想…

phpvulhunter工具:静态 php 代码审计

phpvulhunter是一款PHP源码自动化审计工具,通过这个工具,可以对一些开源CMS进行自动化的代码审计,并生成漏洞报告。 1、安装 首先从github上进行获取: git clone https://github.com/OneSourceCat/phpvulhunter2、下载完成后,将工程目录放置于 WAMP 等 PHP-Web 运行环境中…

YOLOv8-seg训练与推理

1.YOLOv8-seg简介 YOLOv8-seg是YOLO系列模型的其中一个版本。YOLOv8-seg在继承YOLO系列模型高效性和准确性的基础上,增加了实例分割的能力。 2.数据集使用的数据集较简单,主要以下目录:images:存放原始图片(1500张),大小为128x128。部分如下: images_json:存放labelme标注的…

易基因: cfMeDIP-seq揭示cfDNA甲基化高效区分原发性和转移性前列腺|Nat Commun

大家好,这里是专注表观组学十余年,领跑多组学科研服务的易基因。 前列腺癌(Prostate cancer,PCa)是男性中第二常见的恶性肿瘤,也是全球癌症相关死亡的第三大原因。虽然大多数原发性前列腺癌可以治愈,但转移性前列腺癌患者的5年生存率仍低至30%。大多数患者很快就会发展成…

从零搭建Xswitch进行测试

1 xswitch官网 拉取社区版xwitch docker镜像,编译之,修改.env文件 ,把docker跑起来,这个是核心服务 跑起来如下,端口映射不需要管,他内部做好的,默认sip使用7060 前端ws连接端口 8081 wss连接端口 8082 2 自己照着官网ES6 demo 例子写 Vetro 例子,我是用的vue搞的前端…

【日记】医生拆线居然还能没拆干净(1796 字)

正文早上拆线,医院的门诊登记簿上写名字排队。我前面人还挺多。不过医生问过前面的情况之后,就先给我做了,因为拆线快。等我到市里转车,吃过饭后才发现,那个医生拆线没拆干净…… 吃了饭感觉口腔里还是有奇怪的东西,那个粗糙的质感,确定是线头没错了……找了个酒店的卫生…

Docker 学习笔记-基本概念与安装

Docker 学习笔记 基本概念镜像:Docker 的镜像概念类似于虚拟机里的镜像,是一个只读的模板,一个独立的文件系统,包括运行容器所需的数据,可以用来创建新的容器。 DockerFile;镜像可以基于 DockerFile 构建,DockerFile 是一个描述文件,里面包含若干条命令,每条命令都会对…

面相快速入门教程7木型

7 木型 在本章中,我将介绍木型的基础知识,你将学会如何识别木型。首先,我们来快速参考一下木的特征:能量:向上、推动、活跃、早晨、春天、童年 特质:乐观、热情、活跃、人道主义、自信、愤怒、沮丧、冲动、反应灵敏、直接、敏锐、实际、逻辑性强、有条理、果断、有判断力…