SpringBoot+SeetaFace6搭建人脸辨认平台

冬雨财经  金牌会员 | 2024-10-8 15:14:18 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 848|帖子 848|积分 2544

前言

最近多个项目需要接入人脸辨认功能,之前的方案是使用百度云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包
  1.         <dependency>
  2.             <groupId>com.seeta.sdk</groupId>
  3.             <artifactId>seeta-sdk-platform</artifactId>
  4.             <scope>system</scope>
  5.             <version>1.2.1</version>
  6.             <systemPath>${project.basedir}/lib/seetaface.jar</systemPath>
  7.         </dependency>
复制代码
bean对象注册

FaceDetectorProxy为人脸检测bean,能够检测图像中是否有人脸
FaceRecognizerProxy为人脸比对bean,能够比对两张人脸的相似度
FaceLandmarkerProxy为人脸关键点bean,能够检测人脸的关键点,支持5个点和68个点
  1. @Configuration
  2. public class FaceConfig {
  3.     @Value("${face.modelPath}")
  4.     private String modelPath;
  5.     @Bean
  6.     public FaceDetectorProxy faceDetector() throws FileNotFoundException {
  7.         SeetaConfSetting detectorPoolSetting = new SeetaConfSetting(
  8.                 new SeetaModelSetting(0, new String[]{modelPath + File.separator + "face_detector.csta"}, SeetaDevice.SEETA_DEVICE_CPU));
  9.         FaceDetectorProxy faceDetectorProxy = new FaceDetectorProxy(detectorPoolSetting);
  10.         return faceDetectorProxy;
  11.     }
  12.     @Bean
  13.     public FaceRecognizerProxy faceRecognizer() throws FileNotFoundException {
  14.         SeetaConfSetting detectorPoolSetting = new SeetaConfSetting(
  15.                 new SeetaModelSetting(0, new String[]{modelPath + File.separator + "face_recognizer.csta"}, SeetaDevice.SEETA_DEVICE_CPU));
  16.         FaceRecognizerProxy faceRecognizerProxy = new FaceRecognizerProxy(detectorPoolSetting);
  17.         return faceRecognizerProxy;
  18.     }
  19.     @Bean
  20.     public FaceLandmarkerProxy faceLandmarker() throws FileNotFoundException {
  21.         SeetaConfSetting detectorPoolSetting = new SeetaConfSetting(
  22.                 new SeetaModelSetting(0, new String[]{modelPath + File.separator + "face_landmarker_pts5.csta"}, SeetaDevice.SEETA_DEVICE_CPU));
  23.         FaceLandmarkerProxy faceLandmarkerProxy = new FaceLandmarkerProxy(detectorPoolSetting);
  24.         return faceLandmarkerProxy;
  25.     }
  26. }
复制代码
在使用相干bean对象时,需要举行library的当地注册,指定cpu还是gpu模式
  1. LoadNativeCore.LOAD_NATIVE(SeetaDevice.SEETA_DEVICE_CPU)
复制代码
人脸检测
  1.     public FaceEnum.CheckImageFaceStatus getFace(BufferedImage image) throws Exception {
  2.         SeetaImageData imageData = SeetafaceUtil.toSeetaImageData(image);
  3.         SeetaRect[] detects = faceDetectorProxy.detect(imageData);
  4.         if (detects.length == 0) {
  5.             return FaceEnum.CheckImageFaceStatus.NoFace;
  6.         } else if (detects.length == 1) {
  7.             return FaceEnum.CheckImageFaceStatus.OneFace;
  8.         } else {
  9.             return FaceEnum.CheckImageFaceStatus.MoreFace;
  10.         }
  11.     }
复制代码
人脸比对
  1.     public FaceEnum.CompareImageFaceStatus compareFace(BufferedImage source, BufferedImage compare) throws Exception {
  2.         float[] sourceFeature = extract(source);
  3.         float[] compareFeature = extract(compare);
  4.         if (sourceFeature != null && compareFeature != null) {
  5.             float calculateSimilarity = faceRecognizerProxy.calculateSimilarity(sourceFeature, compareFeature);
  6.             System.out.printf("相似度:%f\n", calculateSimilarity);
  7.             if (calculateSimilarity >= CHECK_SIM) {
  8.                 return FaceEnum.CompareImageFaceStatus.Same;
  9.             } else {
  10.                 return FaceEnum.CompareImageFaceStatus.Different;
  11.             }
  12.         } else {
  13.             return FaceEnum.CompareImageFaceStatus.LostFace;
  14.         }
  15.     }
复制代码
人脸关键点
  1.     private float[] extract(BufferedImage image) throws Exception {
  2.         SeetaImageData imageData = SeetafaceUtil.toSeetaImageData(image);
  3.         SeetaRect[] detects = faceDetectorProxy.detect(imageData);
  4.         if (detects.length > 0) {
  5.             SeetaPointF[] pointFS = faceLandmarkerProxy.mark(imageData, detects[0]);
  6.             float[] features = faceRecognizerProxy.extract(imageData, pointFS);
  7.             return features;
  8.         }
  9.         return null;
  10.     }
复制代码
人脸数据库


  • 注册
  1.     public long registFace(BufferedImage image) throws Exception {
  2.         long result = -1;
  3.         SeetaImageData imageData = SeetafaceUtil.toSeetaImageData(image);
  4.         SeetaRect[] detects = faceDetectorProxy.detect(imageData);
  5.         if (detects.length > 0) {
  6.             SeetaPointF[] pointFS = faceLandmarkerProxy.mark(imageData, detects[0]);
  7.             result = faceDatabase.Register(imageData, pointFS);
  8.             faceDatabase.Save(dataBasePath);
  9.         }
  10.         return result;
  11.     }
复制代码

  • 查找
  1.     public long queryFace(BufferedImage image) throws Exception {
  2.         long result = -1;
  3.         SeetaImageData imageData = SeetafaceUtil.toSeetaImageData(image);
  4.         SeetaRect[] detects = faceDetectorProxy.detect(imageData);
  5.         if (detects.length > 0) {
  6.             SeetaPointF[] pointFS = faceLandmarkerProxy.mark(imageData, detects[0]);
  7.             long[] index = new long[1];
  8.             float[] sim = new float[1];
  9.             result = faceDatabase.QueryTop(imageData, pointFS, 1, index, sim);
  10.             if (result > 0) {
  11.                 float similarity = sim[0];
  12.                 if (similarity >= CHECK_SIM) {
  13.                     result = index[0];
  14.                 } else {
  15.                     result = -1;
  16.                 }
  17.             }
  18.         }
  19.         return result;
  20.     }
复制代码

  • 删除
  1.     public long deleteFace(long index) throws Exception {
  2.         long result = faceDatabase.Delete(index);
  3.         faceDatabase.Save(dataBasePath);
  4.         return result;
  5.     }
复制代码
拓展

集成了face-api.js,实现简单的张张嘴,摇摇头活体检测,精确度不是很高,作为一个参考选项
官网地址:https://github.com/justadudewhohacks/face-api.js
加载模型
  1.         Promise.all([
  2.             faceapi.loadFaceDetectionModel('models'),
  3.             faceapi.loadFaceLandmarkModel('models')
  4.         ]).then(startAnalysis);
  5.     function startAnalysis() {
  6.         console.log('模型加载成功!');
  7.         var canvas1 = faceapi.createCanvasFromMedia(document.getElementById('showImg'))
  8.         faceapi.detectSingleFace(canvas1).then((detection) => {
  9.             if (detection) {
  10.                 faceapi.detectFaceLandmarks(canvas1).then((landmarks) => {
  11.                     console.log('模型预热调用成功!');
  12.                 })
  13.             }
  14.         })
  15.     }
复制代码
打开摄像头
  1.         <video id="video" muted playsinline></video>
  2.     function AnalysisFaceOnline() {
  3.         var videoElement = document.getElementById('video');
  4.         // 检查浏览器是否支持getUserMedia API
  5.         if (navigator.mediaDevices.getUserMedia) {
  6.             navigator.mediaDevices.getUserMedia({ video: { facingMode: "user" } }) // 请求视频流
  7.                 .then(function(stream) {
  8.                     videoElement.srcObject = stream; // 将视频流设置到<video>元素
  9.                     videoElement.play();
  10.                 })
  11.                 .catch(function(err) {
  12.                     console.error("获取摄像头错误:", err); // 处理错误
  13.                 });
  14.         } else {
  15.             console.error("您的浏览器不支持getUserMedia API");
  16.         }
  17.     }
复制代码
捕捉帧计算关键点
  1. function vedioCatchInit() {
  2.         video.addEventListener('play', function() {
  3.             function captureFrame() {
  4.                 if (!video.paused && !video.ended) {
  5.                     // 设置canvas的尺寸与视频帧相同
  6.                     canvas.width = 200;
  7.                     canvas.height = 300;
  8.                     // 绘制当前视频帧到canvas
  9.                     context.drawImage(video, 0, 0, canvas.width, canvas.height);
  10.                     // 将canvas内容转换为data URL
  11.                     //outputImage.src = canvas.toDataURL('image/png');
  12.                     // 可以在这里添加代码将data URL发送到服务器或进行其他处理
  13.                     faceapi.detectSingleFace(canvas).then((detection) => {
  14.                         if (detection) {
  15.                             faceapi.detectFaceLandmarks(canvas).then((landmarks) => {
  16.                               
  17.      
  18.                             })
  19.                         } else {
  20.                             console.log("no face")
  21.                         }
  22.                     })
  23.                     // 递归调用以持续捕获帧
  24.                     setTimeout(captureFrame, 100); // 每500毫秒捕获一次
  25.                 }
  26.             }
  27.             captureFrame(); // 开始捕获帧
  28.         });
  29.     }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

冬雨财经

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表