From 5c6d9475f8dbae38b9618dcc3726093a3458ae42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A1=BE=E6=8C=BD?= Date: Sun, 27 Oct 2024 20:21:41 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A1=BE=E6=8C=BD10.27?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- login/pom.xml | 26 ++ .../java/com/guwan/config/GlobalValue.java | 3 + .../java/com/guwan/config/MinioConfig.java | 2 +- .../controller/login/FaceController.java | 117 ++--- .../controller/login/UploadController.java | 35 ++ .../controller/login/UserController.java | 46 ++ .../com/guwan/face/FaceEngineAutoRun.java | 120 +++++ .../face/config/ArcFaceAutoConfiguration.java | 133 ++++++ .../guwan/face/dto/CompareFacesReqDTO.java | 14 + .../com/guwan/face/dto/FaceAddReqDTO.java | 12 + .../com/guwan/face/dto/FaceDetectReqDTO.java | 10 + .../com/guwan/face/dto/FaceDetectResDTO.java | 14 + .../guwan/face/dto/FaceRecognitionReqDTO.java | 10 + .../guwan/face/dto/FaceRecognitionResDTO.java | 15 + .../java/com/guwan/face/dto/FaceVideoVo.java | 35 ++ .../com/guwan/face/dto/GetFaceListResDTO.java | 14 + .../com/guwan/face/entity/ProcessInfo.java | 12 + .../guwan/face/entity/UserCompareInfo.java | 12 + .../com/guwan/face/enums/ErrorCodeEnum.java | 50 +++ .../com/guwan/face/face/FacePreviewInfo.java | 46 ++ .../com/guwan/face/face/FaceRecognize.java | 293 ++++++++++++ .../guwan/face/factory/FaceEngineFactory.java | 73 +++ .../com/guwan/face/rpc/BusinessException.java | 64 +++ .../java/com/guwan/face/rpc/ErrorCode.java | 12 + .../face/rpc/GlobalExceptionHandler.java | 47 ++ .../java/com/guwan/face/rpc/Response.java | 39 ++ .../com/guwan/face/rtsp/RtspFrameGrabber.java | 420 ++++++++++++++++++ .../guwan/face/service/FaceEngineService.java | 29 ++ .../service/impl/FaceEngineServiceImpl.java | 353 +++++++++++++++ .../java/com/guwan/face/util/Base64Util.java | 33 ++ .../com/guwan/face/util/FaceEngineTest.java | 225 ++++++++++ .../java/com/guwan/face/util/UserInfo.java | 11 + .../com/guwan/face/util/UserRamCache.java | 66 +++ .../com/guwan/face/util/UserRamGroup.java | 42 ++ .../main/java/com/guwan/util/PathUtil.java | 12 + login/src/main/resources/application.yml | 28 +- login/src/main/resources/banner.txt | 1 + .../test/java/com/guwan/EncryptPwdUtil.java | 19 + 38 files changed, 2433 insertions(+), 60 deletions(-) create mode 100644 login/src/main/java/com/guwan/face/FaceEngineAutoRun.java create mode 100644 login/src/main/java/com/guwan/face/config/ArcFaceAutoConfiguration.java create mode 100644 login/src/main/java/com/guwan/face/dto/CompareFacesReqDTO.java create mode 100644 login/src/main/java/com/guwan/face/dto/FaceAddReqDTO.java create mode 100644 login/src/main/java/com/guwan/face/dto/FaceDetectReqDTO.java create mode 100644 login/src/main/java/com/guwan/face/dto/FaceDetectResDTO.java create mode 100644 login/src/main/java/com/guwan/face/dto/FaceRecognitionReqDTO.java create mode 100644 login/src/main/java/com/guwan/face/dto/FaceRecognitionResDTO.java create mode 100644 login/src/main/java/com/guwan/face/dto/FaceVideoVo.java create mode 100644 login/src/main/java/com/guwan/face/dto/GetFaceListResDTO.java create mode 100644 login/src/main/java/com/guwan/face/entity/ProcessInfo.java create mode 100644 login/src/main/java/com/guwan/face/entity/UserCompareInfo.java create mode 100644 login/src/main/java/com/guwan/face/enums/ErrorCodeEnum.java create mode 100644 login/src/main/java/com/guwan/face/face/FacePreviewInfo.java create mode 100644 login/src/main/java/com/guwan/face/face/FaceRecognize.java create mode 100644 login/src/main/java/com/guwan/face/factory/FaceEngineFactory.java create mode 100644 login/src/main/java/com/guwan/face/rpc/BusinessException.java create mode 100644 login/src/main/java/com/guwan/face/rpc/ErrorCode.java create mode 100644 login/src/main/java/com/guwan/face/rpc/GlobalExceptionHandler.java create mode 100644 login/src/main/java/com/guwan/face/rpc/Response.java create mode 100644 login/src/main/java/com/guwan/face/rtsp/RtspFrameGrabber.java create mode 100644 login/src/main/java/com/guwan/face/service/FaceEngineService.java create mode 100644 login/src/main/java/com/guwan/face/service/impl/FaceEngineServiceImpl.java create mode 100644 login/src/main/java/com/guwan/face/util/Base64Util.java create mode 100644 login/src/main/java/com/guwan/face/util/FaceEngineTest.java create mode 100644 login/src/main/java/com/guwan/face/util/UserInfo.java create mode 100644 login/src/main/java/com/guwan/face/util/UserRamCache.java create mode 100644 login/src/main/java/com/guwan/face/util/UserRamGroup.java create mode 100644 login/src/main/java/com/guwan/util/PathUtil.java create mode 100644 login/src/main/resources/banner.txt create mode 100644 login/src/test/java/com/guwan/EncryptPwdUtil.java diff --git a/login/pom.xml b/login/pom.xml index 57cc949..18bd519 100644 --- a/login/pom.xml +++ b/login/pom.xml @@ -60,6 +60,32 @@ 7.0.2 + + com.arcsoft.face + arcsoft-sdk-face + 4.1.1.0 + + + + + org.apache.commons + commons-pool2 + 2.12.0 + + + + + org.bytedeco + javacv-platform + 1.4.4 + + + + com.alibaba + druid-spring-boot-starter + 1.1.10 + + diff --git a/login/src/main/java/com/guwan/config/GlobalValue.java b/login/src/main/java/com/guwan/config/GlobalValue.java index 7f7fab2..ffbe08c 100644 --- a/login/src/main/java/com/guwan/config/GlobalValue.java +++ b/login/src/main/java/com/guwan/config/GlobalValue.java @@ -58,4 +58,7 @@ public class GlobalValue { private String minioBucketName; + @Value("${global.file_path.static-locations}") + private String staticLocations; + } diff --git a/login/src/main/java/com/guwan/config/MinioConfig.java b/login/src/main/java/com/guwan/config/MinioConfig.java index 472b61e..fcb3de2 100644 --- a/login/src/main/java/com/guwan/config/MinioConfig.java +++ b/login/src/main/java/com/guwan/config/MinioConfig.java @@ -23,7 +23,7 @@ public class MinioConfig { } @Bean("minioClient") public MinioClient minioClient(){ - MinioClient minioClient=null; + MinioClient minioClient = null; try { minioClient = new MinioClient(globalValue.getMinioEndpoint(), // globalValue.getMinioPort(), diff --git a/login/src/main/java/com/guwan/controller/login/FaceController.java b/login/src/main/java/com/guwan/controller/login/FaceController.java index a35dd9c..a905ab6 100644 --- a/login/src/main/java/com/guwan/controller/login/FaceController.java +++ b/login/src/main/java/com/guwan/controller/login/FaceController.java @@ -1,81 +1,89 @@ package com.guwan.controller.login; +import cn.hutool.core.collection.CollectionUtil; +import com.arcsoft.face.FaceInfo; +import com.arcsoft.face.enums.ExtractType; +import com.arcsoft.face.toolkit.ImageFactory; +import com.arcsoft.face.toolkit.ImageInfo; +import com.guwan.config.GlobalValue; import com.guwan.config.MinioConfig; +import com.guwan.face.dto.FaceRecognitionResDTO; +import com.guwan.face.service.FaceEngineService; import com.guwan.util.UUIDUtil; import io.minio.MinioClient; -import io.minio.PutObjectOptions; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; +import java.io.ByteArrayOutputStream; import java.io.InputStream; -import java.util.regex.Pattern; +import java.util.Base64; +import java.util.List; @RestController +@Slf4j public class FaceController { @Autowired private MinioConfig minioConfig; @Autowired private MinioClient minioClient; + @Autowired + private GlobalValue globalValue; + @Autowired + private FaceEngineService faceEngineService; @GetMapping("/11") - public String test() { + public Integer test() { try { - // 调用statObject()来判断对象是否存在。 - // 如果不存在, statObject()抛出异常, - // 否则则代表对象存在。 - minioClient.statObject(minioConfig.getBucketName(), "tempOrgImageFile"); + String tempOrgImageFile = "photo/t_1f952219ae6848a48fbf282d7d464623.jpg"; + // 调用statObject()来判断对象是否存在。如果不存在, statObject()抛出异常, 否则则代表对象存在。 + minioClient.statObject(minioConfig.getBucketName(), tempOrgImageFile); //判断人脸照片是否合格 - //1.保存到本地 - InputStream tempInputStream = minioClient.getObject(minioConfig.getBucketName(), tempOrgImageFile); - String tempPath = globalValue.getStaticLocations() + "/";//+globalValue.getTempDir()+"/"; - String tempOrgFilePath = tempPath + tempOrgImageFile; - int index; - byte[] bytes = new byte[1024]; - File outFile = new File(tempOrgFilePath); - FileOutputStream downloadFile = new FileOutputStream(outFile); - while ((index = tempInputStream.read(bytes)) != -1) { - downloadFile.write(bytes, 0, index); - downloadFile.flush(); + //1 + InputStream tempInputStream = minioClient.getObject(minioConfig.getBucketName(), + tempOrgImageFile); + //----------------算法检测---------------------------------------------- + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int length; + while ((length = tempInputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, length); } - downloadFile.close(); + byte[] bytes = outputStream.toByteArray(); + outputStream.close(); tempInputStream.close(); - //2.测试上传的文件 - String tempFaceFileName = UUIDUtil.uuid() + ".jpg"; - String tempFaceFilePath = tempPath + tempFaceFileName; - - String osName = System.getProperty("os.name");//获取指定键(即os.name)的系统属性,如:Windows 7。 -// if (Pattern.matches("Windows.*", osName)) { - if (!Pattern.matches("Windows.*", osName)) { - int res = PicSDK.getFace(tempOrgFilePath, tempFaceFilePath); - if (res != 0) { + //------------------------------------------------------------------------- + ImageInfo rgbData = ImageFactory.getRGBData(bytes); + List faceInfoList = faceEngineService.detectFaces(rgbData); + if (CollectionUtil.isNotEmpty(faceInfoList)) { + FaceInfo faceInfo = faceInfoList.get(0); + FaceRecognitionResDTO faceRecognitionResDTO = new FaceRecognitionResDTO(); + faceRecognitionResDTO.setRect(faceInfo.getRect()); + byte[] featureBytes = faceEngineService.extractFaceFeature(rgbData, faceInfo, ExtractType.REGISTER); + if (featureBytes != null) { +// UserRamCache.UserInfo userInfo = new UserCompareInfo(); +// userInfo.setFaceId(faceAddReqDTO.getName()); +// userInfo.setName(faceAddReqDTO.getName()); +// userInfo.setFaceFeature(feature); +// //这边注册到内存缓存中,也可以根据业务,注册到数据库中 +// UserRamCache.addUser(userInfo); + //entity.setFeature(Base64.getEncoder().encodeToString(featureBytes)); + System.out.println(Base64.getEncoder().encodeToString(featureBytes)); + }else{ log.error("图片不合格,未检测到人脸"); -// return 2; + return 2; } - //保存底片文件到oss - InputStream inputStream = new FileInputStream(tempFaceFilePath); - PutObjectOptions putObjectOptions = new PutObjectOptions(inputStream.available(), -1); - putObjectOptions.setContentType("image/jpeg"); - minioClient.putObject( - minioConfig.getBucketName(), faceImageFileName, inputStream, putObjectOptions); - inputStream.close(); - } else { - minioClient.copyObject( - minioConfig.getBucketName(), - faceImageFileName, - null, - null, - minioConfig.getBucketName(), - tempOrgImageFile, - null, - null); + }else{ + log.error("图片不合格,未检测到人脸"); + return 2; } + + + String orgImageFileName = "face/"+ "o_" + UUIDUtil.uuid() + ".jpg"; //拷贝临时文件正式文件 minioClient.copyObject( minioConfig.getBucketName(), @@ -87,17 +95,18 @@ public class FaceController { null, null); - entity.setOrgImage(orgImageFileName); - entity.setFaceImage(faceImageFileName); + + //删除临时文件oss minioClient.removeObject(minioConfig.getBucketName(), tempOrgImageFile); //删除本地临时文件 - new File(tempFaceFilePath).delete(); +// new File(tempFaceFilePath).delete(); } catch (Exception e) { - entity.setOrgImage(""); - entity.setFaceImage(""); + e.printStackTrace(); + return 10; } + return 1; } } diff --git a/login/src/main/java/com/guwan/controller/login/UploadController.java b/login/src/main/java/com/guwan/controller/login/UploadController.java index 6105ff8..dfa9f4c 100644 --- a/login/src/main/java/com/guwan/controller/login/UploadController.java +++ b/login/src/main/java/com/guwan/controller/login/UploadController.java @@ -1,7 +1,10 @@ package com.guwan.controller.login; import com.guwan.common.R; +import com.guwan.config.GlobalValue; import com.guwan.config.MinioConfig; +import com.guwan.util.IPUtils; +import com.guwan.util.PathUtil; import io.minio.MinioClient; import io.minio.PutObjectOptions; import lombok.RequiredArgsConstructor; @@ -11,6 +14,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; +import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.util.UUID; @@ -23,6 +28,7 @@ public class UploadController { private final MinioConfig minioConfig; private final MinioClient minioClient; + private final GlobalValue globalValue; @PostMapping("/GBUpload") public R gbUpload(MultipartFile file) { @@ -75,4 +81,33 @@ public class UploadController { } + + + @PostMapping("/demo111") + public void uploadFile(MultipartFile file) { + + + String path = PathUtil.path(""); + + try { + // 确保临时路径存在 + File tempDir = new File(path); + if (!tempDir.exists()) { + tempDir.mkdirs(); // 创建目录 + } + + // 构建文件的完整路径 + File serverFile = new File(path + File.separator + file.getOriginalFilename()); + + // 将上传的文件保存到服务器 + file.transferTo(serverFile); + + System.out.println("文件上传成功,保存路径为:" + serverFile.getAbsolutePath()); + } catch (IOException e) { + e.printStackTrace(); + System.out.println("文件上传失败:" + e.getMessage()); + } + } + + } diff --git a/login/src/main/java/com/guwan/controller/login/UserController.java b/login/src/main/java/com/guwan/controller/login/UserController.java index 28a8fb6..f43af0c 100644 --- a/login/src/main/java/com/guwan/controller/login/UserController.java +++ b/login/src/main/java/com/guwan/controller/login/UserController.java @@ -1,14 +1,22 @@ package com.guwan.controller.login; +import com.guwan.config.GlobalValue; import com.guwan.service.TokenService; import com.guwan.util.IPUtils; +import com.guwan.util.PathUtil; import io.swagger.v3.oas.annotations.Operation; import jakarta.annotation.security.PermitAll; import jakarta.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; @RestController @RequestMapping("/user") @@ -16,11 +24,20 @@ public class UserController { @Autowired private TokenService tokenService; + @Autowired + private GlobalValue globalValue; @GetMapping("/login") @PermitAll @Operation(summary = "使用账号密码登录") public String login(String userId, HttpServletRequest request) { + + + String test = PathUtil.path(); + + + System.out.println("tempPath = " + test); + String ip = IPUtils.getIpAddr(request); System.out.println("ip111 = " + ip); return tokenService.createToken(userId, ip); @@ -46,4 +63,33 @@ public class UserController { } return "getInfo"; } + + + @PostMapping("/demo111") + public void uploadFile(MultipartFile file) { + + + String tempPath = System.getProperty("user.dir") + globalValue.getStaticLocations(); + + try { + // 确保临时路径存在 + File tempDir = new File(tempPath); + if (!tempDir.exists()) { + tempDir.mkdirs(); // 创建目录 + } + + // 构建文件的完整路径 + File serverFile = new File(tempPath + File.separator + file.getOriginalFilename()); + + // 将上传的文件保存到服务器 + file.transferTo(serverFile); + + System.out.println("文件上传成功,保存路径为:" + serverFile.getAbsolutePath()); + } catch (IOException e) { + e.printStackTrace(); + System.out.println("文件上传失败:" + e.getMessage()); + } + } + + } diff --git a/login/src/main/java/com/guwan/face/FaceEngineAutoRun.java b/login/src/main/java/com/guwan/face/FaceEngineAutoRun.java new file mode 100644 index 0000000..cf62c1f --- /dev/null +++ b/login/src/main/java/com/guwan/face/FaceEngineAutoRun.java @@ -0,0 +1,120 @@ +/* +package com.guwan.face; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.guwan.config.GlobalValue; +import com.guwan.face.entity.UserCompareInfo; +import com.guwan.face.service.FaceEngineService; +import com.guwan.face.util.Base64Util; +import com.guwan.face.util.UserInfo; +import com.guwan.face.util.UserRamGroup; +import lombok.extern.slf4j.Slf4j; + +import net.shapelight.modules.ten.entity.TenCellEntity; +import net.shapelight.modules.ten.entity.TenPersonEntity; +import net.shapelight.modules.ten.service.TenCellService; +import net.shapelight.modules.ten.service.TenPersonService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +@Order(1) +@Slf4j +public class FaceEngineAutoRun implements ApplicationRunner { + @Autowired + private FaceEngineService faceEngineService; + @Autowired + private TenPersonService tenPersonService; + @Autowired + private TenCellService tenCellService; + @Autowired + private GlobalValue globalValue; + + @Override + public void run(ApplicationArguments args) throws Exception { + // 任务初始化 + log.debug("服务启动。。。。。初始化人脸库"); +// Map fileMap = Maps.newHashMap(); +// fileMap.put("zhao1", "赵丽颖"); +// fileMap.put("yang1", "杨紫"); +// fileMap.put("baixue", "白雪"); +// fileMap.put("chenchuang", "陈创"); +// for (String f : fileMap.keySet()) { +// ClassPathResource resource = new ClassPathResource("static/images/" + f + ".jpg"); +// InputStream inputStream = resource.getInputStream(); +// ImageInfo rgbData = ImageFactory.getRGBData(inputStream); +// List faceInfoList = faceEngineService.detectFaces(rgbData); +// if (CollectionUtil.isNotEmpty(faceInfoList)) { +// byte[] feature = faceEngineService.extractFaceFeature(rgbData, faceInfoList.get(0), ExtractType.REGISTER); +// UserRamCache.UserInfo userInfo = new UserCompareInfo(); +// userInfo.setFaceId(f); +// userInfo.setName(fileMap.get(f)); +// userInfo.setFaceFeature(feature); +// //这边注册到内存缓存中,也可以根据业务,注册到数据库中 +// UserRamCache.addUser(userInfo); +// } +// } + +// int count = tenPersonService.findCount(); +// int pageSize = 1000; +// int page = count/pageSize; +// if(count%1000!=0){ +// page = page+1; +// } +// int faceCount = 0; +// for (int i = 0; i < page; i++) { +// int start = i*1000; +// List listPage = tenPersonService.listPage(start,1000); +// for(TenPersonEntity personEntity: listPage){ +// if(personEntity.getFeature()!=null && personEntity.getFeature().length()>0){ +// UserRamCache.UserInfo userInfo = new UserCompareInfo(); +// userInfo.setFaceId(personEntity.getPersonId()+""); +// userInfo.setName(personEntity.getName()); +// userInfo.setFaceFeature(Base64Util.base64ToBytes(personEntity.getFeature())); +// //这边注册到内存缓存中 +// UserRamCache.addUser(userInfo); +// faceCount++; +// } +// } +// } + + + List cellList = tenCellService.list(new QueryWrapper() + .eq("tenant_id",globalValue.getTenantId()) + .eq("delete_flag",0)); + for(TenCellEntity cellEntity: cellList){ + String cellId = cellEntity.getCellId()+""; + UserRamGroup.addCell(cellId); + UserRamGroup.addOrgId(cellEntity.getOrgId(),cellId); + int count = tenPersonService.findCount(cellId); + int pageSize = 1000; + int page = count/pageSize; + if(count%1000!=0){ + page = page+1; + } + int faceCount = 0; + for (int i = 0; i < page; i++) { + int start = i*1000; + List listPage = tenPersonService.listPage(start,1000, cellId); + for(TenPersonEntity personEntity: listPage){ + if(personEntity.getFeature()!=null && personEntity.getFeature().length()>0){ + UserInfo userInfo = new UserCompareInfo(); + userInfo.setFaceId(personEntity.getPersonId()+""); + userInfo.setName(personEntity.getName()); + userInfo.setFaceFeature(Base64Util.base64ToBytes(personEntity.getFeature())); + //这边注册到内存缓存中 + UserRamGroup.addUser(userInfo,cellId); + faceCount++; + } + } + } + log.debug(cellEntity.getName()+":初始化人脸库完成,共 "+faceCount+" 人"); + } + } +} +*/ diff --git a/login/src/main/java/com/guwan/face/config/ArcFaceAutoConfiguration.java b/login/src/main/java/com/guwan/face/config/ArcFaceAutoConfiguration.java new file mode 100644 index 0000000..6f4699b --- /dev/null +++ b/login/src/main/java/com/guwan/face/config/ArcFaceAutoConfiguration.java @@ -0,0 +1,133 @@ +package com.guwan.face.config; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.LinkedList; +import java.util.List; + +@Slf4j +@Configuration +public class ArcFaceAutoConfiguration implements InitializingBean, DisposableBean { + + + private static final String PLATFORM; + + private static final String USER_HOME; + + public static String CACHE_LIB_FOLDER; + + @Value("${config.arcface-sdk.version}") + public String ARC_FACE_VERSION; + + static { + String jvmName = System.getProperty("java.vm.name", "").toLowerCase(); + String osName = System.getProperty("os.name", "").toLowerCase(); + String osArch = System.getProperty("os.arch", "").toLowerCase(); + String abiType = System.getProperty("sun.arch.abi", "").toLowerCase(); + String libPath = System.getProperty("sun.boot.library.path", "").toLowerCase(); + USER_HOME = System.getProperty("user.home"); + if (jvmName.startsWith("dalvik") && osName.startsWith("linux")) { + osName = "android"; + } else if (jvmName.startsWith("robovm") && osName.startsWith("darwin")) { + osName = "ios"; + osArch = "arm"; + } else if (osName.startsWith("mac os x") || osName.startsWith("darwin")) { + osName = "macosx"; + } else { + int spaceIndex = osName.indexOf(' '); + if (spaceIndex > 0) { + osName = osName.substring(0, spaceIndex); + } + } + if (osArch.equals("i386") || osArch.equals("i486") || osArch.equals("i586") || osArch.equals("i686")) { + osArch = "x86"; + } else if (osArch.equals("amd64") || osArch.equals("x86-64") || osArch.equals("x64")) { + osArch = "x86_64"; + } else if (osArch.startsWith("aarch64") || osArch.startsWith("armv8") || osArch.startsWith("arm64")) { + osArch = "arm64"; + } else if ((osArch.startsWith("arm")) && ((abiType.equals("gnueabihf")) || (libPath.contains("openjdk-armhf")))) { + osArch = "armhf"; + } else if (osArch.startsWith("arm")) { + osArch = "arm"; + } + PLATFORM = osName + "-" + osArch; + + } + + + @Override + public void afterPropertiesSet() throws IOException { + CACHE_LIB_FOLDER = USER_HOME + "/.arcface/cache/" + ARC_FACE_VERSION + "/" + PLATFORM + "/"; + loadLibrary(); + } + + public void loadLibrary() throws IOException { + String baseFolder = ""; + String suffix = ".dll"; + if ("windows-x86_64".equals(PLATFORM)) { + baseFolder = "WIN64"; + } else if ("windows-x86".equals(PLATFORM)) { + baseFolder = "WIN32"; + } else if ("linux-x86_64".equals(PLATFORM)) { + baseFolder = "LINUX64"; + suffix = ".so"; + } + + if ("".equals(baseFolder)) { + throw new RuntimeException("ArcFace不支持该操作系统"); + } + + + File file = new File(CACHE_LIB_FOLDER); + if (!file.exists()) { + file.mkdirs(); + } + + List libList = new LinkedList<>(); + libList.add("libarcsoft_face"); + libList.add("libarcsoft_face_engine"); + libList.add("libarcsoft_face_engine_jni"); + + for (String lib : libList) { + ClassPathResource resource = new ClassPathResource("libs/" + ARC_FACE_VERSION + "/" + baseFolder + "/" + lib + suffix); + InputStream inputStream = resource.getInputStream(); + int faceLength = inputStream.available(); + File facePath = new File(CACHE_LIB_FOLDER + lib + suffix); + if (facePath.exists()) { + if (facePath.length() == faceLength) { + continue; + } + facePath.delete(); + } + writeToLocal(CACHE_LIB_FOLDER + lib + suffix, inputStream); + } + } + + private void writeToLocal(String destination, InputStream input) + throws IOException { + int index; + byte[] bytes = new byte[1024 * 100]; + FileOutputStream fileOutputStream = new FileOutputStream(destination); + while ((index = input.read(bytes)) != -1) { + fileOutputStream.write(bytes, 0, index); + } + fileOutputStream.flush(); + fileOutputStream.close(); + input.close(); + } + + + @Override + public void destroy() throws Exception { + } + +} diff --git a/login/src/main/java/com/guwan/face/dto/CompareFacesReqDTO.java b/login/src/main/java/com/guwan/face/dto/CompareFacesReqDTO.java new file mode 100644 index 0000000..0fc1500 --- /dev/null +++ b/login/src/main/java/com/guwan/face/dto/CompareFacesReqDTO.java @@ -0,0 +1,14 @@ +package com.guwan.face.dto; + +import lombok.Data; + +/** + * @author shentao + * @desc + * @date 2022/3/30 + */ +@Data +public class CompareFacesReqDTO { + private String image1; + private String image2; +} diff --git a/login/src/main/java/com/guwan/face/dto/FaceAddReqDTO.java b/login/src/main/java/com/guwan/face/dto/FaceAddReqDTO.java new file mode 100644 index 0000000..fcadf6c --- /dev/null +++ b/login/src/main/java/com/guwan/face/dto/FaceAddReqDTO.java @@ -0,0 +1,12 @@ +package com.guwan.face.dto; + +import lombok.Data; + +@Data +public class FaceAddReqDTO { + + private String name; + + private String image; + +} diff --git a/login/src/main/java/com/guwan/face/dto/FaceDetectReqDTO.java b/login/src/main/java/com/guwan/face/dto/FaceDetectReqDTO.java new file mode 100644 index 0000000..c542929 --- /dev/null +++ b/login/src/main/java/com/guwan/face/dto/FaceDetectReqDTO.java @@ -0,0 +1,10 @@ +package com.guwan.face.dto; + +import lombok.Data; + +@Data +public class FaceDetectReqDTO { + + private String image; + +} diff --git a/login/src/main/java/com/guwan/face/dto/FaceDetectResDTO.java b/login/src/main/java/com/guwan/face/dto/FaceDetectResDTO.java new file mode 100644 index 0000000..1ad0583 --- /dev/null +++ b/login/src/main/java/com/guwan/face/dto/FaceDetectResDTO.java @@ -0,0 +1,14 @@ +package com.guwan.face.dto; + +import com.arcsoft.face.Rect; +import lombok.Data; + +@Data +public class FaceDetectResDTO { + private Rect rect; + private int orient; + private int faceId = -1; + private int age = -1; + private int gender = -1; + private int liveness = -1; +} diff --git a/login/src/main/java/com/guwan/face/dto/FaceRecognitionReqDTO.java b/login/src/main/java/com/guwan/face/dto/FaceRecognitionReqDTO.java new file mode 100644 index 0000000..342076c --- /dev/null +++ b/login/src/main/java/com/guwan/face/dto/FaceRecognitionReqDTO.java @@ -0,0 +1,10 @@ +package com.guwan.face.dto; + +import lombok.Data; + +@Data +public class FaceRecognitionReqDTO { + + private String image; + +} diff --git a/login/src/main/java/com/guwan/face/dto/FaceRecognitionResDTO.java b/login/src/main/java/com/guwan/face/dto/FaceRecognitionResDTO.java new file mode 100644 index 0000000..0cea030 --- /dev/null +++ b/login/src/main/java/com/guwan/face/dto/FaceRecognitionResDTO.java @@ -0,0 +1,15 @@ +package com.guwan.face.dto; + + +import com.arcsoft.face.Rect; +import lombok.Data; + +@Data +public class FaceRecognitionResDTO { + + private Rect rect; + private String personId; + private String name; + private float similar; + +} diff --git a/login/src/main/java/com/guwan/face/dto/FaceVideoVo.java b/login/src/main/java/com/guwan/face/dto/FaceVideoVo.java new file mode 100644 index 0000000..e1930de --- /dev/null +++ b/login/src/main/java/com/guwan/face/dto/FaceVideoVo.java @@ -0,0 +1,35 @@ +package com.guwan.face.dto; + + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Accessors(chain = true) +public class FaceVideoVo { + /** + * 人员id + */ + private String personId; + /** + * 人员name + */ + private String name; + /** + * 是否正脸 + */ + + private Integer isHeadOnView; //0否1是 + + /** + * 图片url + */ + private String imageUrl; + + + +} diff --git a/login/src/main/java/com/guwan/face/dto/GetFaceListResDTO.java b/login/src/main/java/com/guwan/face/dto/GetFaceListResDTO.java new file mode 100644 index 0000000..9bd9a18 --- /dev/null +++ b/login/src/main/java/com/guwan/face/dto/GetFaceListResDTO.java @@ -0,0 +1,14 @@ +package com.guwan.face.dto; + +import lombok.Data; + +@Data +public class GetFaceListResDTO { + + private String id; + + private String name; + + private String url; + +} diff --git a/login/src/main/java/com/guwan/face/entity/ProcessInfo.java b/login/src/main/java/com/guwan/face/entity/ProcessInfo.java new file mode 100644 index 0000000..516f558 --- /dev/null +++ b/login/src/main/java/com/guwan/face/entity/ProcessInfo.java @@ -0,0 +1,12 @@ +package com.guwan.face.entity; + + +import lombok.Data; + +@Data +public class ProcessInfo { + private int age; + private int gender; + private int liveness; + +} diff --git a/login/src/main/java/com/guwan/face/entity/UserCompareInfo.java b/login/src/main/java/com/guwan/face/entity/UserCompareInfo.java new file mode 100644 index 0000000..b21fd9e --- /dev/null +++ b/login/src/main/java/com/guwan/face/entity/UserCompareInfo.java @@ -0,0 +1,12 @@ +package com.guwan.face.entity; + + +import com.guwan.face.util.UserInfo; +import lombok.Data; + + +@Data +public class UserCompareInfo extends UserInfo { + private Float similar; + private Integer isHeadOnView; //0否1是 +} diff --git a/login/src/main/java/com/guwan/face/enums/ErrorCodeEnum.java b/login/src/main/java/com/guwan/face/enums/ErrorCodeEnum.java new file mode 100644 index 0000000..ec6859a --- /dev/null +++ b/login/src/main/java/com/guwan/face/enums/ErrorCodeEnum.java @@ -0,0 +1,50 @@ +package com.guwan.face.enums; + + +import com.guwan.face.rpc.ErrorCode; +import lombok.Getter; + + +@Getter +public enum ErrorCodeEnum implements ErrorCode { + + /** + * 成功 + */ + SUCCESS(0, "success", "成功"), + FAIL(1, "fail", "失败"), + PARAM_ERROR(2, "param error", "参数错误"), + SYSTEM_ERROR(999, "system error", "系统错误"), + + ; + private Integer code; + private String desc; + private String descCN; + + ErrorCodeEnum(Integer code, String desc) { + this.code = code; + this.desc = desc; + } + + ErrorCodeEnum(Integer code, String desc, String descCN) { + this.code = code; + this.desc = desc; + this.descCN = descCN; + } + + @Override + public Integer getCode() { + return code; + } + + @Override + public String getDesc() { + return desc; + } + + @Override + public String getDescCN() { + return descCN; + } + +} diff --git a/login/src/main/java/com/guwan/face/face/FacePreviewInfo.java b/login/src/main/java/com/guwan/face/face/FacePreviewInfo.java new file mode 100644 index 0000000..801270f --- /dev/null +++ b/login/src/main/java/com/guwan/face/face/FacePreviewInfo.java @@ -0,0 +1,46 @@ +package com.guwan.face.face; + +import com.arcsoft.face.FaceInfo; + +public class FacePreviewInfo { + private FaceInfo faceInfo; + private int trackId; + private int gender = -1; + + public FacePreviewInfo(FaceInfo faceInfo, int trackId) { + this.faceInfo = faceInfo; + this.trackId = trackId; + } + + public FacePreviewInfo(FaceInfo faceInfo, int trackId, int gender) { + this.faceInfo = faceInfo; + this.trackId = trackId; + this.gender = gender; + } + + public int getGender() { + return gender; + } + + public void setGender(int gender) { + this.gender = gender; + } + + public FaceInfo getFaceInfo() { + return faceInfo; + } + + public void setFaceInfo(FaceInfo faceInfo) { + this.faceInfo = faceInfo; + } + + + public int getTrackId() { + return trackId; + } + + public void setTrackId(int trackId) { + this.trackId = trackId; + } + +} diff --git a/login/src/main/java/com/guwan/face/face/FaceRecognize.java b/login/src/main/java/com/guwan/face/face/FaceRecognize.java new file mode 100644 index 0000000..de444ff --- /dev/null +++ b/login/src/main/java/com/guwan/face/face/FaceRecognize.java @@ -0,0 +1,293 @@ +package com.guwan.face.face; + +import com.arcsoft.face.*; +import com.arcsoft.face.enums.DetectMode; +import com.arcsoft.face.enums.ErrorInfo; +import com.arcsoft.face.enums.ExtractType; +import com.arcsoft.face.toolkit.ImageFactory; +import com.arcsoft.face.toolkit.ImageInfo; +import com.guwan.face.config.ArcFaceAutoConfiguration; +import com.guwan.face.factory.FaceEngineFactory; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.pool2.impl.GenericObjectPool; +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; + +import java.io.File; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +@Slf4j +public final class FaceRecognize { + + /** + * VIDEO模式人脸检测引擎,用于预览帧人脸追踪 + */ + private static FaceEngine ftEngine; + + /** + * 人脸注册引擎 + */ + private static FaceEngine regEngine; + + /** + * 用于人脸识别的引擎池 + */ + private static GenericObjectPool frEnginePool; + + + private static volatile ConcurrentHashMap faceResultRegistry = new ConcurrentHashMap<>(); + + private static ExecutorService frService = Executors.newFixedThreadPool(20); + + public static ConcurrentHashMap faceFeatureRegistry = new ConcurrentHashMap<>(); + + /** + * 初始化引擎 + */ + public void initEngine(String appId, String sdkKey, String activeKey, String activeFile) { + + //引擎配置 + ftEngine = new FaceEngine(ArcFaceAutoConfiguration.CACHE_LIB_FOLDER); + int activeCode; + if (StringUtils.isNotEmpty(activeFile)) { + activeCode = ftEngine.activeOffline(activeFile); + } else { + activeCode = ftEngine.activeOnline(appId, sdkKey, activeKey); + } + + EngineConfiguration ftEngineCfg = new EngineConfiguration(); + ftEngineCfg.setDetectMode(DetectMode.ASF_DETECT_MODE_VIDEO); + ftEngineCfg.setFunctionConfiguration(FunctionConfiguration.builder().supportFaceDetect(true).build()); + int ftInitCode = ftEngine.init(ftEngineCfg); + + //引擎配置 + regEngine = new FaceEngine(ArcFaceAutoConfiguration.CACHE_LIB_FOLDER); + + EngineConfiguration regEngineCfg = new EngineConfiguration(); + regEngineCfg.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE); + regEngineCfg.setFunctionConfiguration(FunctionConfiguration.builder().supportFaceDetect(true).supportFaceRecognition(true).build()); + int regInitCode = regEngine.init(regEngineCfg); + + + GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); + poolConfig.setMaxIdle(5); + poolConfig.setMaxTotal(5); + poolConfig.setMinIdle(5); + poolConfig.setLifo(false); + EngineConfiguration frEngineCfg = new EngineConfiguration(); + frEngineCfg.setFunctionConfiguration(FunctionConfiguration.builder().supportFaceRecognition(true).build()); + frEnginePool = new GenericObjectPool(new FaceEngineFactory(appId, sdkKey, activeKey,activeFile, frEngineCfg), poolConfig);//底层库算法对象池 + + + if (!(activeCode == ErrorInfo.MOK.getValue() || activeCode == ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue())) { + log.error("activeCode: " + activeCode); + throw new RuntimeException("activeCode: " + activeCode); + } + if (ftInitCode != ErrorInfo.MOK.getValue()) { + log.error("ftInitEngine: " + ftInitCode); + throw new RuntimeException("ftInitEngine: " + ftInitCode); + } + + if (regInitCode != ErrorInfo.MOK.getValue()) { + log.error("regInitEngine: " + regInitCode); + throw new RuntimeException("regInitEngine: " + regInitCode); + } + + } + + + public static void registerFace(String imagePath) { + + log.info("正在注册人脸"); + + int count = 0; + if (regEngine != null) { + File file = new File(imagePath); + File[] files = file.listFiles(); + + for (File file1 : files) { + ImageInfo imageInfo = ImageFactory.getRGBData(file1); + if (imageInfo != null) { + List faceInfoList = new ArrayList<>(); + int code = regEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), + imageInfo.getImageFormat(), faceInfoList); + + if (code == 0 && faceInfoList.size() > 0) { + FaceFeature faceFeature = new FaceFeature(); + int resCode = regEngine.extractFaceFeature(imageInfo, faceInfoList.get(0), ExtractType.REGISTER, 0, faceFeature); + if (resCode == 0) { + int lastIndexOf = file1.getName().lastIndexOf("."); + String name = file1.getName().substring(0, file1.getName().length() - lastIndexOf - 1); + faceFeatureRegistry.put(name, faceFeature.getFeatureData()); + log.info("成功注册人脸:" + name); + count++; + } + } + } + } + log.info("人脸注册完成,共注册:" + count + "张人脸"); + } else { + throw new RuntimeException("注册失败,引擎未初始化或初始化失败"); + } + + + } + + public static void registerFace(Map face) { + face.forEach((k, v) -> { + faceFeatureRegistry.put(k, v.clone()); + }); + } + + public static void removeFace(String name) { + faceFeatureRegistry.remove(name); + } + + public static void clearFace() { + faceFeatureRegistry.clear(); + } + + public static FaceResult getFaceResult(FaceInfo faceInfo, ImageInfo imageInfo) { + FaceResult faceResult = faceResultRegistry.get(faceInfo.getFaceId()); + if (faceResult == null) { + faceResult = new FaceResult(); + faceResultRegistry.put(faceInfo.getFaceId(), faceResult); + frService.submit(new FaceInfoRunnable(faceInfo, imageInfo, faceResult)); + } else if (faceResult.isFlag()) { + return faceResult; + } + return null; + } + + public List detectFaces(ImageInfo imageInfo) { + if (ftEngine != null) { + List faceInfoList = new ArrayList<>(); + int code = ftEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), + imageInfo.getImageFormat(), faceInfoList); + + List previewInfoList = new LinkedList<>(); + for (FaceInfo faceInfo : faceInfoList) { + FacePreviewInfo facePreviewInfo = new FacePreviewInfo(); + facePreviewInfo.setFaceInfo(faceInfo); + previewInfoList.add(facePreviewInfo); + } + + clearFaceResultRegistry(faceInfoList); + return previewInfoList; + + } + return null; + } + + + private long lastClearTime = System.currentTimeMillis(); + + //清理过时的人脸 + private void clearFaceResultRegistry(List faceInfoList) { + if (System.currentTimeMillis() - lastClearTime > 5000) { + Iterator iterator = faceResultRegistry.keySet().iterator(); + for (; iterator.hasNext(); ) { + Integer next = iterator.next(); + boolean flag = false; + for (FaceInfo faceInfo : faceInfoList) { + if (next.equals(faceInfo.getFaceId())) { + flag = true; + } + } + if (!flag) { + iterator.remove(); + } + + } + lastClearTime = System.currentTimeMillis(); + } + + + } + + + @Data + public static class FaceResult { + private boolean flag = false; + private String name; + private float score; + + + } + + @Data + public class FacePreviewInfo { + + private FaceInfo faceInfo; + private int age; + private boolean liveness; + + } + + + private static class FaceInfoRunnable implements Runnable { + private FaceInfo faceInfo; + private ImageInfo imageInfo; + private FaceResult faceResult; + + public FaceInfoRunnable(FaceInfo faceInfo, ImageInfo imageInfo, FaceResult faceResult) { + this.faceInfo = faceInfo; + this.imageInfo = imageInfo; + this.faceResult = faceResult; + } + + @Override + public void run() { + FaceEngine frEngine = null; + try { + frEngine = frEnginePool.borrowObject(); + if (frEngine != null) { + FaceFeature faceFeature = new FaceFeature(); + int resCode = frEngine.extractFaceFeature(imageInfo, faceInfo, ExtractType.RECOGNIZE, 0, faceFeature); + if (resCode == 0) { + + float score = 0.0F; + Iterator> iterator = faceFeatureRegistry.entrySet().iterator(); + for (; iterator.hasNext(); ) { + Map.Entry next = iterator.next(); + FaceFeature faceFeatureTarget = new FaceFeature(); + faceFeatureTarget.setFeatureData(next.getValue()); + + FaceSimilar faceSimilar = new FaceSimilar(); + frEngine.compareFaceFeature(faceFeatureTarget, faceFeature, faceSimilar); + if (faceSimilar.getScore() > score) { + score = faceSimilar.getScore(); + faceResult.setName(next.getKey()); + } + } + + log.info("相似度:" + score); + if (score >= 0.8f) { + faceResult.setScore(score); + faceResult.setFlag(true); + faceResultRegistry.put(faceInfo.getFaceId(), faceResult); + } else { + faceResultRegistry.remove(faceInfo.getFaceId()); + } + + } + } + } catch (Exception e) { + + } finally { + if (frEngine != null) { + frEnginePool.returnObject(frEngine); + } + } + + + } + } + + +} diff --git a/login/src/main/java/com/guwan/face/factory/FaceEngineFactory.java b/login/src/main/java/com/guwan/face/factory/FaceEngineFactory.java new file mode 100644 index 0000000..568856e --- /dev/null +++ b/login/src/main/java/com/guwan/face/factory/FaceEngineFactory.java @@ -0,0 +1,73 @@ +package com.guwan.face.factory; + +import com.arcsoft.face.EngineConfiguration; +import com.arcsoft.face.FaceEngine; +import com.arcsoft.face.enums.ErrorInfo; +import com.guwan.face.config.ArcFaceAutoConfiguration; +import com.guwan.face.enums.ErrorCodeEnum; +import com.guwan.face.rpc.BusinessException; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.pool2.BasePooledObjectFactory; +import org.apache.commons.pool2.PooledObject; +import org.apache.commons.pool2.impl.DefaultPooledObject; + +@Slf4j +public class FaceEngineFactory extends BasePooledObjectFactory { + + private String appId; + private String sdkKey; + private String activeKey; + private String activeFile; + private EngineConfiguration engineConfiguration; + + + public FaceEngineFactory(String appId, String sdkKey, String activeKey, String activeFile, EngineConfiguration engineConfiguration) { + this.appId = appId; + this.sdkKey = sdkKey; + this.activeKey = activeKey; + this.activeFile=activeFile; + this.engineConfiguration = engineConfiguration; + } + + + @Override + public FaceEngine create() { + + + FaceEngine faceEngine = new FaceEngine(ArcFaceAutoConfiguration.CACHE_LIB_FOLDER); + +// FaceEngine faceEngine = new FaceEngine("/home/huangyifang/gb/咸阳师范/ArcSoft_ArcFacePro_linux_java_V4.1/libs/LINUX64/"); + int activeCode; + if (StringUtils.isNotEmpty(activeFile)) { + activeCode = faceEngine.activeOffline(activeFile); + } else { + activeCode = faceEngine.activeOnline(appId, sdkKey, activeKey); + } + log.debug("引擎激活errorCode:" + activeCode); + if (activeCode != ErrorInfo.MOK.getValue() && activeCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) { + log.error("引擎激活失败" + activeCode); + throw new BusinessException(ErrorCodeEnum.FAIL, "引擎激活失败" + activeCode); + } + int initCode = faceEngine.init(engineConfiguration); + if (initCode != ErrorInfo.MOK.getValue()) { + log.error("引擎初始化失败" + initCode); + throw new BusinessException(ErrorCodeEnum.FAIL, "引擎初始化失败" + initCode); + } + log.debug("初始化引擎errorCode:" + initCode); + return faceEngine; + } + + @Override + public PooledObject wrap(FaceEngine faceEngine) { + return new DefaultPooledObject<>(faceEngine); + } + + + @Override + public void destroyObject(PooledObject p) throws Exception { + FaceEngine faceEngine = p.getObject(); + int result = faceEngine.unInit(); + super.destroyObject(p); + } +} diff --git a/login/src/main/java/com/guwan/face/rpc/BusinessException.java b/login/src/main/java/com/guwan/face/rpc/BusinessException.java new file mode 100644 index 0000000..a9df4b3 --- /dev/null +++ b/login/src/main/java/com/guwan/face/rpc/BusinessException.java @@ -0,0 +1,64 @@ +package com.guwan.face.rpc; + +import lombok.Data; + +/** + * @Author: st7251 + * @Date: 2018/11/23 14:18 + */ +@Data +public class BusinessException extends RuntimeException { + private ErrorCode errorCode; + private String msg; + private String msgCN; + + public BusinessException(Response response) { + this.errorCode = new ErrorCode() { + @Override + public Integer getCode() { + return response.getCode(); + } + + @Override + public String getDesc() { + return response.getMsg(); + } + + @Override + public String getDescCN() { + return response.getMsg(); + } + }; + this.msg=response.getMsg(); + this.msgCN=response.getMsg(); + } + + public BusinessException(ErrorCode errorCode) { + super(errorCode.getDesc()); + this.errorCode = errorCode; + this.msg= errorCode.getDesc(); + this.msgCN=errorCode.getDescCN(); + } + + public BusinessException(ErrorCode errorCode, String msg) { + super(errorCode.getDesc()); + this.errorCode = errorCode; + this.msg = msg; + this.msgCN=msg; + } + + public BusinessException(Throwable cause, ErrorCode errorCode) { + super(cause); + this.errorCode = errorCode; + this.msg= errorCode.getDesc(); + this.msgCN=errorCode.getDescCN(); + } + + + public BusinessException(Throwable cause, ErrorCode errorCode, String msg) { + super(cause); + this.errorCode = errorCode; + this.msg = msg; + this.msgCN=msg; + } +} diff --git a/login/src/main/java/com/guwan/face/rpc/ErrorCode.java b/login/src/main/java/com/guwan/face/rpc/ErrorCode.java new file mode 100644 index 0000000..abca5bb --- /dev/null +++ b/login/src/main/java/com/guwan/face/rpc/ErrorCode.java @@ -0,0 +1,12 @@ +package com.guwan.face.rpc; + +public interface ErrorCode { + + + Integer getCode(); + + String getDesc(); + + String getDescCN(); + +} diff --git a/login/src/main/java/com/guwan/face/rpc/GlobalExceptionHandler.java b/login/src/main/java/com/guwan/face/rpc/GlobalExceptionHandler.java new file mode 100644 index 0000000..93b7761 --- /dev/null +++ b/login/src/main/java/com/guwan/face/rpc/GlobalExceptionHandler.java @@ -0,0 +1,47 @@ +package com.guwan.face.rpc; + + +import com.guwan.face.enums.ErrorCodeEnum; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +@Slf4j +public class GlobalExceptionHandler{ + + + /** + * 自定义异常 + */ + @ExceptionHandler(BusinessException.class) + public Response businessException(BusinessException e) { + log.error(e.getMessage(), e); + Response response = new Response(); + response.setCode(e.getErrorCode().getCode()); + response.setMsg(e.getMsgCN()); + return response; + } + + @ExceptionHandler(IllegalArgumentException.class) + public Response handleIllegalArgumentException(IllegalArgumentException e) { + log.error(e.getMessage(), e); + Response response = new Response(); + response.setCode(ErrorCodeEnum.PARAM_ERROR.getCode()); + response.setMsg(e.getMessage()); + return response; + } + + @ExceptionHandler(Exception.class) + public Response handleException(Exception e) { + log.error(e.getMessage(), e); + Response response = new Response(); + response.setCode(ErrorCodeEnum.SYSTEM_ERROR.getCode()); + response.setMsg(ErrorCodeEnum.SYSTEM_ERROR.getDescCN()); + return response; + } + + + + +} diff --git a/login/src/main/java/com/guwan/face/rpc/Response.java b/login/src/main/java/com/guwan/face/rpc/Response.java new file mode 100644 index 0000000..6b7fc6c --- /dev/null +++ b/login/src/main/java/com/guwan/face/rpc/Response.java @@ -0,0 +1,39 @@ +package com.guwan.face.rpc; + +import lombok.Data; + +@Data +public class Response { + + private int code = -1; + private String msg = "success"; + private T data; + + public static Response newSuccessResponse(T data) { + return newResponse(data, 0, "success"); + } + + public static Response newFailedResponse(Integer code, String message) { + return newResponse(null, code, message); + } + + public static Response newFailedResponse(ErrorCode ErrorCode) { + return newResponse(null, ErrorCode.getCode(), ErrorCode.getDesc()); + } + + public static Response newFailedResponse(ErrorCode ErrorCode, String message) { + return newResponse(null, ErrorCode.getCode(), message); + } + + public static Response newResponse(T data, Integer code, String message) { + Response response = new Response(); + response.setCode(code); + response.setMsg(message); + if (data != null && data instanceof String && "".equals(data)) { + response.setData(null); + } else { + response.setData(data); + } + return response; + } +} diff --git a/login/src/main/java/com/guwan/face/rtsp/RtspFrameGrabber.java b/login/src/main/java/com/guwan/face/rtsp/RtspFrameGrabber.java new file mode 100644 index 0000000..fbd913a --- /dev/null +++ b/login/src/main/java/com/guwan/face/rtsp/RtspFrameGrabber.java @@ -0,0 +1,420 @@ +/* +package com.guwan.face.rtsp; + +import cn.hutool.core.collection.CollectionUtil; +import com.arcsoft.face.FaceInfo; +import com.arcsoft.face.enums.ExtractType; +import com.arcsoft.face.toolkit.ImageFactory; +import com.arcsoft.face.toolkit.ImageInfo; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.guwan.face.dto.FaceVideoVo; +import io.minio.MinioClient; +import io.minio.PutObjectOptions; +import lombok.extern.slf4j.Slf4j; +import net.shapelight.common.config.GlobalValue; +import net.shapelight.common.config.MinioConfig; +import net.shapelight.common.utils.Constant; +import net.shapelight.common.utils.UUIDUtil; +import net.shapelight.modules.face.entity.UserCompareInfo; +import net.shapelight.modules.face.service.FaceEngineService; +import net.shapelight.modules.face.util.UserInfo; +import net.shapelight.modules.face.util.UserRamGroup; +import net.shapelight.modules.feignClient.CxFeignClient; + +import net.shapelight.modules.ten.dao.TenCellDao; +import net.shapelight.modules.ten.entity.TenCellEntity; +import net.shapelight.modules.ten.entity.TenPersonEntity; +import net.shapelight.modules.ten.service.TenPersonService; +import net.shapelight.modules.ten.service.impl.TenPersonServiceImpl; +import org.bytedeco.javacpp.avutil; +import org.bytedeco.javacv.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import static org.bytedeco.javacpp.avutil.AV_LOG_ERROR; + +@Component +@Slf4j +public class RtspFrameGrabber { + + */ +/* @Autowired + private FaceEngineService faceEngineService; + + @Autowired + private TenPersonService personService; + + @Autowired + private GlobalValue globalValue; + + @Autowired + private CxFeignClient feignClient; + @Autowired + private TenPersonServiceImpl tenPersonService; + + @Autowired + private TenCellDao tenCellDao; + + @Autowired + private MinioConfig minioConfig; + @Autowired + private MinioClient minioClient; + + + *//* + + */ +/** + * 用于记录人脸识别相关状态 + *//* + + public ConcurrentHashMap requestFeatureStatusMap = new ConcurrentHashMap<>(); + */ +/** + * rtsp视频流url + *//* + + @Value("${global.Url.rtspUrl}") + private String rtspUrl; + */ +/** + * 帧抓取器 + *//* + + private FFmpegFrameGrabber grabber; + */ +/** + * 视频帧率 + *//* + + private int frameRate = 25; + */ +/** + * 视频码率 + *//* + +// private int bitRate = 2000000; + private int bitRate = 128000; + */ +/** + * 视频宽度 + *//* + + private int frameWidth = 480; + */ +/** + * 视频高度 + *//* + + private int frameHeight = 270; + + + + private void createGrabber() { + try { + + grabber = FFmpegFrameGrabber.createDefault(rtspUrl); + grabber.setOption("rtsp_transport", "tcp"); + +// grabber.setOption("reconnect", "1"); +// grabber.setOption("reconnect_at_eof", "1"); +// grabber.setOption("reconnect_streamed", "1"); +// grabber.setOption("reconnect_delay_max", "2"); +// grabber.setOption("preset", "veryfast"); +// grabber.setOption("probesize", "192"); +// grabber.setOption("tune", "zerolatency"); +// grabber.setFrameRate(30.0); +// grabber.setOption("buffer_size", "" + this.bufferSize); +// grabber.setOption("max_delay", "500000"); +// grabber.setOption("stimeout", String.valueOf(20000)); +// grabber.setOption("loglevel", "quiet"); + + +// grabber.setOption("appkey", "****");//海康视频 appkey +// grabber.setOption("secret", byte2Base64);//海康视频 secret +// grabber.setOption("port", "446");//默认443 +// grabber.setOption("enableHTTPS", "1"); //是否启用HTTPS协议,这里总是填1 +// grabber.setOption("rtsp_flags", "prefer_tcp"); + grabber.setOption("stimeout", "5000000");//5秒 + + + //设置帧率 + grabber.setFrameRate(frameRate); + //设置获取的视频宽度 + grabber.setImageWidth(frameWidth); + //设置获取的视频高度 + grabber.setImageHeight(frameHeight); + //设置视频bit率 + grabber.setVideoBitrate(bitRate); + grabber.start(); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + public List startGrabber(String cellId) { + + List faceVideoVos = new ArrayList<>(); + + avutil.av_log_set_level(AV_LOG_ERROR); + Java2DFrameConverter java2DFrameConverter = new Java2DFrameConverter(); + if (grabber == null) { + //log.info("连接rtsp:" + rstp + ",开始创建grabber"); + createGrabber(); + } + try { + Frame frame = grabber.grabImage(); + if (frame != null) { +// logger.info("处理帧............................................."); + BufferedImage bi = java2DFrameConverter.getBufferedImage(frame); + + byte[] bytes = imageToBytes(bi, "jpg"); + + */ +/* InputStream frameInputStream = new ByteArrayInputStream(bytes); + String frameFileName = "temp/" + "frame_" + UUIDUtil.uuid() + + ".jpg"; + + PutObjectOptions framePutObjectOptions = new PutObjectOptions(bytes.length, -1); + framePutObjectOptions.setContentType("image/jpeg"); + + minioClient.putObject( + minioConfig.getBucketName(), frameFileName, frameInputStream, framePutObjectOptions); + + System.out.println("文件名 = " + globalValue.getMinioEndpoint() + "/" + + globalValue.getMinioBucketName() + "/" + frameFileName);*//* + + */ +/* // 读取图片 + BufferedImage image = ImageIO.read(new File("C:\\Users\\zhangbo\\OneDrive\\图片\\Camera Roll\\1寸相片.jpg")); + + // 创建字节输出流 + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + // 使用ImageIO将BufferedImage编码为byte[] + ImageIO.write(image, "jpg", baos); + + // 转换为byte数组 + byte[] imageBytes = baos.toByteArray();*//* + + faceVideoVos = imageRecognition(bytes, cellId); + System.out.println("faceVideoVos = " + faceVideoVos); + + } else { + log.error("解码失败"); + if (grabber != null) { + try { + grabber.stop(); + } catch (FrameGrabber.Exception ex) { + log.error("grabber stop exception: " + ex.getMessage()); + } finally { + grabber = null; + } + } + } + } catch (Exception e) { + log.error(e.getMessage()); + + if (grabber != null) { + try { + grabber.stop(); + } catch (FrameGrabber.Exception ex) { + log.error("grabber stop exception: " + ex.getMessage()); + } finally { + grabber = null; + } + } + + } finally { + grabber = null; + } +// try { +// Thread.sleep(100); +// } catch (InterruptedException e) { +// logger.error(e.getMessage()); +// } + + return faceVideoVos; + } + + public List recognition(MultipartFile file,String cellId) { + try { + byte[] bytes = file.getBytes(); + return imageRecognition(bytes, cellId); + + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private List imageRecognition(byte[] bytes,String cellId) { + List temp = new ArrayList<>(); + if (bytes != null && bytes.length > 0) { + ImageInfo imageInfo = ImageFactory.getRGBData(bytes); + List faceInfoList = faceEngineService.detectFaces(imageInfo); + + + */ +/* for (FaceInfo faceInfo : faceInfoList) { + System.out.println(faceInfo.getFace3DAngle()); + //Yaw上下 Pitch左右 + if (faceInfo.getFace3DAngle().getYaw() > 20 || faceInfo.getFace3DAngle().getYaw() < -20) { + System.out.println("没在好好看!!!"); + // faceInfoList.remove(faceInfo); + } + if (faceInfo.getFace3DAngle().getPitch() > 20 || faceInfo.getFace3DAngle().getPitch() < -20) { + System.out.println("没在好好看!!!"); + } + }*//* + + + + if (CollectionUtil.isNotEmpty(faceInfoList)) { + faceInfoList.forEach(faceInfo -> { + */ +/* FaceRecognitionResDTO faceRecognitionResDTO = new FaceRecognitionResDTO(); + faceRecognitionResDTO.setRect(faceInfo.getRect());*//* + + + byte[] featureBytes = faceEngineService.extractFaceFeature(imageInfo, + faceInfo, ExtractType.REGISTER); + if (featureBytes != null) { + //底库 + List userInfoList = UserRamGroup.getUserList(cellId); + //人脸对比 这里长度永远为1 + List userCompareInfoList = faceEngineService + .faceRecognition(featureBytes, userInfoList, Float.parseFloat(globalValue.getRecFaceThd())); + + for (UserCompareInfo userCompareInfo : userCompareInfoList) { + FaceVideoVo faceVideoVo = new FaceVideoVo(); + if (faceInfo.getFace3DAngle().getYaw() > 20 || faceInfo.getFace3DAngle().getYaw() < -20) { + faceVideoVo.setIsHeadOnView(0); + }else if (faceInfo.getFace3DAngle().getPitch() > 20 || faceInfo.getFace3DAngle().getPitch() < -20) { + faceVideoVo.setIsHeadOnView(0); + }else { + faceVideoVo.setIsHeadOnView(1); + } + + faceVideoVo.setPersonId(userCompareInfo.getFaceId()).setName(userCompareInfo.getName()); + + + + InputStream frameInputStream = new ByteArrayInputStream(bytes); + String frameFileName = "temp/" + "frame_" + UUIDUtil.uuid() + + ".jpg"; + + PutObjectOptions framePutObjectOptions = new PutObjectOptions(bytes.length, -1); + framePutObjectOptions.setContentType("image/jpeg"); + + try { + frameInputStream.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + try { + minioClient.putObject( + minioConfig.getBucketName(), frameFileName, frameInputStream, framePutObjectOptions); + } catch (Exception e) { + throw new RuntimeException(e); + } + + System.out.println("文件名 = " + globalValue.getMinioEndpoint() + "/" + + globalValue.getMinioBucketName() + "/" + frameFileName); + + + + faceVideoVo.setImageUrl(frameFileName); + + temp.add(faceVideoVo); + } + if (!userCompareInfoList.isEmpty()) { + + for (UserCompareInfo userCompareInfo : userCompareInfoList) { + TenPersonEntity tenPerson = personService.getOne(new LambdaQueryWrapper() + .eq(TenPersonEntity::getPersonId, userCompareInfo.getFaceId())); + Map personnelTypeMap = new HashMap<>(); + personnelTypeMap.put(Constant.PERSON_TYPE_OWNER, "2");//内部人员 + personnelTypeMap.put(Constant.PERSON_TYPE_MEMBER, "1");//承包商 + personnelTypeMap.put(Constant.PERSON_TYPE_TENANT, "3");//长期供应商 + personnelTypeMap.put(Constant.PERSON_TYPE_GUEST, "4");//访客 + + // + Map params = new HashMap<>(); + params.put("pmWatchVideoRecordId", ""); + params.put("orgId", tenPerson.getOrgId()); + params.put("orgName", tenCellDao.selectOne(new QueryWrapper().eq("cell_id", tenPerson.getCellId()))); + params.put("personnelName", tenPerson.getName()); + params.put("personnelId", tenPerson.getOpenId()); + params.put("personnelCardId", tenPerson.getIdCard()); + params.put("personnelType", personnelTypeMap.get(tenPerson.getPersonType())); + params.put("dictSex", tenPerson.getGender() == 0 ? "女" : "男"); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); + params.put("watchVideoTime", sdf.format(System.currentTimeMillis())); + tenPerson.setIsWatchSafeVideo(1); + tenPersonService.updateById(tenPerson); + + System.out.println("params = " + params); + + */ +/* JSONObject jsonObject = feignClient.savePmWatchVideoRecord(params); + if (jsonObject.getBool("success") != null && jsonObject.getBool("success")) { + personService.update(new LambdaUpdateWrapper() + .set(TenPersonEntity::getIsWatchSafeVideo, 1) + .eq(TenPersonEntity::getPersonId, userCompareInfo.getFaceId())); + }*//* + + } + + + } + } else { + log.error("图片不合格,未检测到人脸"); + } + }); + + } else { + log.error("图片不合格,未检测到人脸"); + } + + } else { + } + return temp; + } + + */ +/** + * 图片转字节数组 + * + * @param _bi 图片数据 + * @return 图片字节码 + *//* + + private byte[] imageToBytes(BufferedImage _bi, String _format) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + ImageIO.write(_bi, _format, baos); + } catch (IOException e) { + log.error(e.getMessage()); + return null; + } + return baos.toByteArray(); + } + +} +*/ diff --git a/login/src/main/java/com/guwan/face/service/FaceEngineService.java b/login/src/main/java/com/guwan/face/service/FaceEngineService.java new file mode 100644 index 0000000..abf2a39 --- /dev/null +++ b/login/src/main/java/com/guwan/face/service/FaceEngineService.java @@ -0,0 +1,29 @@ +package com.guwan.face.service; + + +import com.arcsoft.face.FaceInfo; +import com.arcsoft.face.enums.ExtractType; +import com.arcsoft.face.toolkit.ImageInfo; +import com.guwan.face.entity.ProcessInfo; +import com.guwan.face.entity.UserCompareInfo; +import com.guwan.face.util.UserInfo; + + +import java.util.List; + + +public interface FaceEngineService { + + List detectFaces(ImageInfo imageInfo); + + Float compareFace(ImageInfo imageInfo1, ImageInfo imageInfo2) ; + + byte[] extractFaceFeature(ImageInfo imageInfo, FaceInfo faceInfo, ExtractType extractType); + + List faceRecognition(byte[] faceFeature, List userInfoList, float passRate) ; + + List process(ImageInfo imageInfo, List faceInfoList); + + + +} diff --git a/login/src/main/java/com/guwan/face/service/impl/FaceEngineServiceImpl.java b/login/src/main/java/com/guwan/face/service/impl/FaceEngineServiceImpl.java new file mode 100644 index 0000000..1c883ff --- /dev/null +++ b/login/src/main/java/com/guwan/face/service/impl/FaceEngineServiceImpl.java @@ -0,0 +1,353 @@ +package com.guwan.face.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import com.arcsoft.face.*; +import com.arcsoft.face.enums.DetectMode; +import com.arcsoft.face.enums.DetectOrient; +import com.arcsoft.face.enums.ExtractType; +import com.arcsoft.face.toolkit.ImageInfo; +import com.google.common.collect.Lists; +import com.guwan.face.entity.ProcessInfo; +import com.guwan.face.entity.UserCompareInfo; +import com.guwan.face.enums.ErrorCodeEnum; +import com.guwan.face.factory.FaceEngineFactory; +import com.guwan.face.rpc.BusinessException; +import com.guwan.face.service.FaceEngineService; +import com.guwan.face.util.UserInfo; +import jakarta.annotation.PostConstruct; +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.pool2.impl.GenericObjectPool; +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import jakarta.annotation.PostConstruct; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.*; + + +@Service("faceEngineService") +@Slf4j +public class FaceEngineServiceImpl implements FaceEngineService { + + public final static Logger logger = LoggerFactory.getLogger(FaceEngineServiceImpl.class); + + @Value("${config.arcface-sdk.app-id}") + public String appId; + + @Value("${config.arcface-sdk.sdk-key}") + public String sdkKey; + + @Value("${config.arcface-sdk.active-key}") + public String activeKey; + + @Value("${config.arcface-sdk.active-file}") + public String activeFile; + + @Value("${config.arcface-sdk.detect-pool-size}") + public Integer detectPooSize; + + @Value("${config.arcface-sdk.compare-pool-size}") + public Integer comparePooSize; + + private ExecutorService compareExecutorService; + + //通用人脸识别引擎池 + private GenericObjectPool faceEngineGeneralPool; + + //人脸比对引擎池 + private GenericObjectPool faceEngineComparePool; + + @PostConstruct + public void init() { + + + GenericObjectPoolConfig detectPoolConfig = new GenericObjectPoolConfig(); + detectPoolConfig.setMaxIdle(detectPooSize); + detectPoolConfig.setMaxTotal(detectPooSize); + detectPoolConfig.setMinIdle(detectPooSize); + detectPoolConfig.setLifo(false); + EngineConfiguration detectCfg = new EngineConfiguration(); + FunctionConfiguration detectFunctionCfg = new FunctionConfiguration(); + detectFunctionCfg.setSupportFaceDetect(true);//开启人脸检测功能 + detectFunctionCfg.setSupportFaceRecognition(true);//开启人脸识别功能 + detectFunctionCfg.setSupportAge(true);//开启年龄检测功能 + detectFunctionCfg.setSupportGender(true);//开启性别检测功能 + detectFunctionCfg.setSupportLiveness(true);//开启活体检测功能 + detectCfg.setFunctionConfiguration(detectFunctionCfg); + detectCfg.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);//图片检测模式,如果是连续帧的视频流图片,那么改成VIDEO模式 + detectCfg.setDetectFaceOrientPriority(DetectOrient.ASF_OP_0_ONLY);//人脸旋转角度 + faceEngineGeneralPool = new GenericObjectPool(new FaceEngineFactory(appId, sdkKey, activeKey, activeFile, detectCfg), detectPoolConfig);//底层库算法对象池 + + + //初始化特征比较线程池 + GenericObjectPoolConfig comparePoolConfig = new GenericObjectPoolConfig(); + comparePoolConfig.setMaxIdle(comparePooSize); + comparePoolConfig.setMaxTotal(comparePooSize); + comparePoolConfig.setMinIdle(comparePooSize); + comparePoolConfig.setLifo(false); + EngineConfiguration compareCfg = new EngineConfiguration(); + FunctionConfiguration compareFunctionCfg = new FunctionConfiguration(); + compareFunctionCfg.setSupportFaceRecognition(true);//开启人脸识别功能 + compareCfg.setFunctionConfiguration(compareFunctionCfg); + compareCfg.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);//图片检测模式,如果是连续帧的视频流图片,那么改成VIDEO模式 + compareCfg.setDetectFaceOrientPriority(DetectOrient.ASF_OP_0_ONLY);//人脸旋转角度 + faceEngineComparePool = new GenericObjectPool(new FaceEngineFactory(appId, sdkKey, activeKey, activeFile, compareCfg), comparePoolConfig);//底层库算法对象池 + compareExecutorService = Executors.newFixedThreadPool(comparePooSize); + } + + + @Override + public List detectFaces(ImageInfo imageInfo) { + + FaceEngine faceEngine = null; + try { + faceEngine = faceEngineGeneralPool.borrowObject(); + if (faceEngine == null) { + throw new BusinessException(ErrorCodeEnum.FAIL, "获取引擎失败"); + } + + //人脸检测得到人脸列表 + List faceInfoList = new ArrayList<>(); + //人脸检测 + int errorCode = faceEngine.detectFaces(imageInfo.getImageData(), + imageInfo.getWidth(), imageInfo.getHeight(), + imageInfo.getImageFormat(), faceInfoList); + if (errorCode == 0) { + return faceInfoList; + } else { + log.error("人脸检测失败,errorCode:" + errorCode); + } + + } catch (Exception e) { + log.error("", e); + } finally { + if (faceEngine != null) { + //释放引擎对象 + faceEngineGeneralPool.returnObject(faceEngine); + } + } + + return null; + + } + + @Override + public Float compareFace(ImageInfo imageInfo1, ImageInfo imageInfo2) { + + List faceInfoList1 = detectFaces(imageInfo1); + List faceInfoList2 = detectFaces(imageInfo2); + + if (CollectionUtil.isEmpty(faceInfoList1)) { + throw new BusinessException(ErrorCodeEnum.FAIL, "照片1未检测到人脸"); + } + if (CollectionUtil.isEmpty(faceInfoList2)) { + throw new BusinessException(ErrorCodeEnum.FAIL, "照片2未检测到人脸"); + } + + byte[] feature1 = extractFaceFeature(imageInfo1, faceInfoList1.get(0), ExtractType.REGISTER); + byte[] feature2 = extractFaceFeature(imageInfo2, faceInfoList2.get(0), ExtractType.RECOGNIZE); + + FaceEngine faceEngine = null; + try { + faceEngine = faceEngineGeneralPool.borrowObject(); + if (faceEngine == null) { + throw new BusinessException(ErrorCodeEnum.FAIL, "获取引擎失败"); + } + + FaceFeature faceFeature1 = new FaceFeature(); + faceFeature1.setFeatureData(feature1); + FaceFeature faceFeature2 = new FaceFeature(); + faceFeature2.setFeatureData(feature2); + //提取人脸特征 + FaceSimilar faceSimilar = new FaceSimilar(); + int errorCode = faceEngine.compareFaceFeature(faceFeature1, faceFeature2, faceSimilar); + if (errorCode == 0) { + return faceSimilar.getScore(); + } else { + log.error("特征提取失败,errorCode:" + errorCode); + } + + } catch (Exception e) { + log.error("", e); + } finally { + if (faceEngine != null) { + //释放引擎对象 + faceEngineGeneralPool.returnObject(faceEngine); + } + } + + return null; + + } + + /** + * 人脸特征 + * + * @param imageInfo + * @return + */ + @Override + public byte[] extractFaceFeature(ImageInfo imageInfo, FaceInfo faceInfo, ExtractType extractType) { + + FaceEngine faceEngine = null; + try { + faceEngine = faceEngineGeneralPool.borrowObject(); + if (faceEngine == null) { + throw new BusinessException(ErrorCodeEnum.FAIL, "获取引擎失败"); + } + + FaceFeature faceFeature = new FaceFeature(); + //提取人脸特征 + int errorCode = faceEngine.extractFaceFeature(imageInfo, faceInfo, extractType, 0, faceFeature); + if (errorCode == 0) { + return faceFeature.getFeatureData(); + } else { + log.error("特征提取失败,errorCode:" + errorCode); + } + + } catch (Exception e) { + log.error("", e); + } finally { + if (faceEngine != null) { + //释放引擎对象 + faceEngineGeneralPool.returnObject(faceEngine); + } + } + + return null; + + } + + @Override + public List faceRecognition(byte[] faceFeature, List userInfoList, float passRate) { + List resultUserInfoList = Lists.newLinkedList();//识别到的人脸列表 + + FaceFeature targetFaceFeature = new FaceFeature(); + targetFaceFeature.setFeatureData(faceFeature); + + List> faceUserInfoPartList = Lists.partition(userInfoList, 1000);//分成1000一组,多线程处理 + CompletionService> completionService = new ExecutorCompletionService(compareExecutorService); + for (List part : faceUserInfoPartList) { + completionService.submit(new CompareFaceTask(part, targetFaceFeature, passRate)); + } + for (int i = 0; i < faceUserInfoPartList.size(); i++) { + List faceUserInfoList = null; + try { + faceUserInfoList = completionService.take().get(); + } catch (InterruptedException | ExecutionException e) { + } + if (CollectionUtil.isNotEmpty(userInfoList)) { + resultUserInfoList.addAll(faceUserInfoList); + } + } + + resultUserInfoList.sort((h1, h2) -> h2.getSimilar().compareTo(h1.getSimilar()));//从大到小排序 + + return resultUserInfoList; + } + + + + @Override + public List process(ImageInfo imageInfo, List faceInfoList) { + FaceEngine faceEngine = null; + try { + //获取引擎对象 + faceEngine = faceEngineGeneralPool.borrowObject(); + if (faceEngine == null) { + throw new BusinessException(ErrorCodeEnum.FAIL, "获取引擎失败"); + } + + + int errorCode = faceEngine.process(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList, FunctionConfiguration.builder().supportAge(true).supportGender(true).supportLiveness(true).build()); + if (errorCode == 0) { + List processInfoList = Lists.newLinkedList(); + + //性别列表 + List genderInfoList = new ArrayList(); + faceEngine.getGender(genderInfoList); + + //年龄列表 + List ageInfoList = new ArrayList(); + faceEngine.getAge(ageInfoList); + //活体结果列表 + List livenessInfoList = new ArrayList(); + faceEngine.getLiveness(livenessInfoList); + + + for (int i = 0; i < genderInfoList.size(); i++) { + ProcessInfo processInfo = new ProcessInfo(); + processInfo.setGender(genderInfoList.get(i).getGender()); + processInfo.setAge(ageInfoList.get(i).getAge()); + processInfo.setLiveness(livenessInfoList.get(i).getLiveness()); + processInfoList.add(processInfo); + } + return processInfoList; + + } + + + } catch (Exception e) { + logger.error("", e); + } finally { + if (faceEngine != null) { + //释放引擎对象 + faceEngineGeneralPool.returnObject(faceEngine); + } + } + + return null; + + } + + + private class CompareFaceTask implements Callable> { + + private List userInfoList; + private FaceFeature targetFaceFeature; + private float passRate; + + + public CompareFaceTask(List userInfoList, FaceFeature targetFaceFeature, float passRate) { + this.userInfoList = userInfoList; + this.targetFaceFeature = targetFaceFeature; + this.passRate = passRate; + } + + @Override + public List call() throws Exception { + FaceEngine faceEngine = null; + List resultUserInfoList = Lists.newLinkedList();//识别到的人脸列表 + try { + faceEngine = faceEngineComparePool.borrowObject(); + for (UserInfo userInfo : userInfoList) { + FaceFeature sourceFaceFeature = new FaceFeature(); + sourceFaceFeature.setFeatureData(userInfo.getFaceFeature()); + FaceSimilar faceSimilar = new FaceSimilar(); + faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar); + if (faceSimilar.getScore() > passRate) {//相似值大于配置预期,加入到识别到人脸的列表 + UserCompareInfo info = new UserCompareInfo(); + info.setName(userInfo.getName()); + info.setFaceId(userInfo.getFaceId()); + info.setSimilar(faceSimilar.getScore()); + resultUserInfoList.add(info); + } + } + } catch (Exception e) { + logger.error("", e); + } finally { + if (faceEngine != null) { + faceEngineComparePool.returnObject(faceEngine); + } + } + + return resultUserInfoList; + } + + } +} diff --git a/login/src/main/java/com/guwan/face/util/Base64Util.java b/login/src/main/java/com/guwan/face/util/Base64Util.java new file mode 100644 index 0000000..be51cb7 --- /dev/null +++ b/login/src/main/java/com/guwan/face/util/Base64Util.java @@ -0,0 +1,33 @@ +package com.guwan.face.util; + +import org.springframework.util.ObjectUtils; + +import java.util.Base64; + +public class Base64Util { + public static String base64Process(String base64Str) { + if (!ObjectUtils.isEmpty(base64Str)) { + String photoBase64 = base64Str.substring(0, 30).toLowerCase(); + int indexOf = photoBase64.indexOf("base64,"); + if (indexOf > 0) { + base64Str = base64Str.substring(indexOf + 7); + } + base64Str = base64Str.replaceAll(" ", "+"); + base64Str = base64Str.replaceAll("\r|\n", ""); + return base64Str; + } + return ""; + } + + public static byte[] base64ToBytes(String base64) { + if (ObjectUtils.isEmpty(base64)) { + return null; + } + String base64Process = base64Process(base64); + + byte[] decode = Base64.getDecoder().decode(base64Process); + return decode; + + + } +} diff --git a/login/src/main/java/com/guwan/face/util/FaceEngineTest.java b/login/src/main/java/com/guwan/face/util/FaceEngineTest.java new file mode 100644 index 0000000..6606b09 --- /dev/null +++ b/login/src/main/java/com/guwan/face/util/FaceEngineTest.java @@ -0,0 +1,225 @@ +package com.guwan.face.util; + +import com.arcsoft.face.*; +import com.arcsoft.face.enums.*; +import com.arcsoft.face.toolkit.ImageFactory; +import com.arcsoft.face.toolkit.ImageInfo; +import com.arcsoft.face.toolkit.ImageInfoEx; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +public class FaceEngineTest { + + + public static void main(String[] args) { + + //激活码,从官网获取 + String appId = "DEnAZa1bWXcaAxyWUg33QZaKCmMkNmrQxuKZJQGmZsHJ"; + String sdkKey = "vWbvUyStZeartSaM6QoTzPYWFpSaj4uhfDmRifSzCd6"; + String activeKey = "82G1-11QA-713Y-8NB4"; + + System.err.println("注意,如果返回的errorCode不为0,可查看com.arcsoft.face.enums.ErrorInfo类获取相应的错误信息"); + + //人脸识别引擎库存放路径 + FaceEngine faceEngine = new FaceEngine("/home/huangyifang/gb/咸阳师范/ArcSoft_ArcFacePro_linux_java_V4.1/libs/LINUX64"); + //激活引擎 + int errorCode = faceEngine.activeOnline(appId, sdkKey, activeKey); + System.out.println("引擎激活errorCode:" + errorCode); + + ActiveDeviceInfo activeDeviceInfo = new ActiveDeviceInfo(); + //采集设备信息(可离线) + errorCode = faceEngine.getActiveDeviceInfo(activeDeviceInfo); + System.out.println("采集设备信息errorCode:" + errorCode); + System.out.println("设备信息:" + activeDeviceInfo.getDeviceInfo()); + +// faceEngine.activeOffline("d:\\ArcFacePro64.dat.offline"); + + ActiveFileInfo activeFileInfo = new ActiveFileInfo(); + errorCode = faceEngine.getActiveFileInfo(activeFileInfo); + System.out.println("获取激活文件errorCode:" + errorCode); + System.out.println("激活文件信息:" + activeFileInfo.toString()); + + //引擎配置 + EngineConfiguration engineConfiguration = new EngineConfiguration(); + engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE); + engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT); + engineConfiguration.setDetectFaceMaxNum(10); + //功能配置 + FunctionConfiguration functionConfiguration = new FunctionConfiguration(); + functionConfiguration.setSupportAge(true); + functionConfiguration.setSupportFaceDetect(true); + functionConfiguration.setSupportFaceRecognition(true); + functionConfiguration.setSupportGender(true); + functionConfiguration.setSupportLiveness(true); + functionConfiguration.setSupportIRLiveness(true); + functionConfiguration.setSupportImageQuality(true); + functionConfiguration.setSupportMaskDetect(true); + functionConfiguration.setSupportUpdateFaceData(true); + engineConfiguration.setFunctionConfiguration(functionConfiguration); + + //初始化引擎 + errorCode = faceEngine.init(engineConfiguration); + System.out.println("初始化引擎errorCode:" + errorCode); + VersionInfo version = faceEngine.getVersion(); + System.out.println(version); + + //人脸检测 + ImageInfo imageInfo = ImageFactory.getRGBData(new File("/home/huangyifang/gb/咸阳师范/10.jpg")); + List faceInfoList = new ArrayList(); + errorCode = faceEngine.detectFaces(imageInfo, faceInfoList); + System.out.println("人脸检测errorCode:" + errorCode); + System.out.println("检测到人脸数:" + faceInfoList.size()); + + ImageQuality imageQuality = new ImageQuality(); + errorCode = faceEngine.imageQualityDetect(imageInfo, faceInfoList.get(0), 0, imageQuality); + System.out.println("图像质量检测errorCode:" + errorCode); + System.out.println("图像质量分数:" + imageQuality.getFaceQuality()); + + //特征提取 + FaceFeature faceFeature = new FaceFeature(); + errorCode = faceEngine.extractFaceFeature(imageInfo, faceInfoList.get(0), ExtractType.REGISTER, 0, faceFeature); + System.out.println("特征提取errorCode:" + errorCode); + + //人脸检测2 + ImageInfo imageInfo2 = ImageFactory.getRGBData(new File("/home/huangyifang/gb/咸阳师范/10.jpg")); + List faceInfoList2 = new ArrayList(); + errorCode = faceEngine.detectFaces(imageInfo2, faceInfoList2); + System.out.println("人脸检测errorCode:" + errorCode); + System.out.println("检测到人脸数:" + faceInfoList.size()); + + //特征提取2 + FaceFeature faceFeature2 = new FaceFeature(); + errorCode = faceEngine.extractFaceFeature(imageInfo2, faceInfoList2.get(0), ExtractType.RECOGNIZE, 0, faceFeature2); + System.out.println("特征提取errorCode:" + errorCode); + + //特征比对 + FaceFeature targetFaceFeature = new FaceFeature(); + targetFaceFeature.setFeatureData(faceFeature.getFeatureData()); + FaceFeature sourceFaceFeature = new FaceFeature(); + sourceFaceFeature.setFeatureData(faceFeature2.getFeatureData()); + FaceSimilar faceSimilar = new FaceSimilar(); + + errorCode = faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar); + System.out.println("特征比对errorCode:" + errorCode); + System.out.println("人脸相似度:" + faceSimilar.getScore()); + + + //人脸属性检测 + FunctionConfiguration configuration = new FunctionConfiguration(); + configuration.setSupportAge(true); + configuration.setSupportGender(true); + configuration.setSupportLiveness(true); + configuration.setSupportMaskDetect(true); + errorCode = faceEngine.process(imageInfo, faceInfoList, configuration); + System.out.println("图像属性处理errorCode:" + errorCode); + + //性别检测 + List genderInfoList = new ArrayList(); + errorCode = faceEngine.getGender(genderInfoList); + System.out.println("性别:" + genderInfoList.get(0).getGender()); + + //年龄检测 + List ageInfoList = new ArrayList(); + errorCode = faceEngine.getAge(ageInfoList); + System.out.println("年龄:" + ageInfoList.get(0).getAge()); + + //活体检测 + List livenessInfoList = new ArrayList(); + errorCode = faceEngine.getLiveness(livenessInfoList); + System.out.println("活体:" + livenessInfoList.get(0).getLiveness()); + + //口罩检测 + List maskInfoList = new ArrayList(); + errorCode = faceEngine.getMask(maskInfoList); + System.out.println("口罩:" + maskInfoList.get(0).getMask()); + + + //IR属性处理 + ImageInfo imageInfoGray = ImageFactory.getGrayData(new File("/home/huangyifang/gb/咸阳师范/10.jpg")); + List faceInfoListGray = new ArrayList(); + errorCode = faceEngine.detectFaces(imageInfoGray, faceInfoListGray); + + FunctionConfiguration configuration2 = new FunctionConfiguration(); + configuration2.setSupportIRLiveness(true); + errorCode = faceEngine.processIr(imageInfoGray, faceInfoListGray, configuration2); + //IR活体检测 + List irLivenessInfo = new ArrayList<>(); + errorCode = faceEngine.getLivenessIr(irLivenessInfo); + System.out.println("IR活体:" + irLivenessInfo.get(0).getLiveness()); + + //获取激活文件信息 + ActiveFileInfo activeFileInfo2 = new ActiveFileInfo(); + errorCode = faceEngine.getActiveFileInfo(activeFileInfo2); + + //更新人脸数据 + errorCode = faceEngine.updateFaceData(imageInfo, faceInfoList); + + //高级人脸图像处理接口 + ImageInfoEx imageInfoEx = new ImageInfoEx(); + imageInfoEx.setHeight(imageInfo.getHeight()); + imageInfoEx.setWidth(imageInfo.getWidth()); + imageInfoEx.setImageFormat(imageInfo.getImageFormat()); + imageInfoEx.setImageDataPlanes(new byte[][]{imageInfo.getImageData()}); + imageInfoEx.setImageStrides(new int[]{imageInfo.getWidth() * 3}); + List faceInfoList1 = new ArrayList<>(); + errorCode = faceEngine.detectFaces(imageInfoEx, DetectModel.ASF_DETECT_MODEL_RGB, faceInfoList1); + ImageQuality imageQuality1 = new ImageQuality(); + errorCode = faceEngine.imageQualityDetect(imageInfoEx, faceInfoList1.get(0), 0, imageQuality1); + FunctionConfiguration fun = new FunctionConfiguration(); + fun.setSupportAge(true); + errorCode = faceEngine.process(imageInfoEx, faceInfoList1, fun); + List ageInfoList1 = new ArrayList<>(); + int age = faceEngine.getAge(ageInfoList1); + FaceFeature feature = new FaceFeature(); + errorCode = faceEngine.extractFaceFeature(imageInfoEx, faceInfoList1.get(0), ExtractType.REGISTER, 0, feature); + errorCode = faceEngine.updateFaceData(imageInfoEx, faceInfoList1); + + //设置活体测试 + errorCode = faceEngine.setLivenessParam(0.5f, 0.7f, 0.3f); + System.out.println("设置活体活体阈值errorCode:" + errorCode); + + LivenessParam livenessParam=new LivenessParam(); + errorCode = faceEngine.getLivenessParam(livenessParam); + + //注册人脸信息1 + FaceFeatureInfo faceFeatureInfo = new FaceFeatureInfo(); + faceFeatureInfo.setSearchId(5); + faceFeatureInfo.setFaceTag("FeatureData1"); + faceFeatureInfo.setFeatureData(faceFeature.getFeatureData()); + errorCode = faceEngine.registerFaceFeature(faceFeatureInfo); + + //注册人脸信息2 + FaceFeatureInfo faceFeatureInfo2 = new FaceFeatureInfo(); + faceFeatureInfo2.setSearchId(6); + faceFeatureInfo2.setFaceTag("FeatureData2"); + faceFeatureInfo2.setFeatureData(faceFeature2.getFeatureData()); + errorCode = faceEngine.registerFaceFeature(faceFeatureInfo2); + + //获取注册人脸个数 + FaceSearchCount faceSearchCount = new FaceSearchCount(); + errorCode = faceEngine.getFaceCount(faceSearchCount); + System.out.println("注册人脸个数:" + faceSearchCount.getCount()); + + //搜索最相似人脸 + SearchResult searchResult = new SearchResult(); + errorCode = faceEngine.searchFaceFeature(faceFeature, CompareModel.LIFE_PHOTO, searchResult); + System.out.println("最相似人脸Id:" + searchResult.getFaceFeatureInfo().getSearchId()); + + //更新人脸信息 + FaceFeatureInfo faceFeatureInfo3 = new FaceFeatureInfo(); + faceFeatureInfo3.setSearchId(6); + faceFeatureInfo3.setFaceTag("FeatureData2Update"); + faceFeatureInfo3.setFeatureData(faceFeature2.getFeatureData()); + errorCode = faceEngine.updateFaceFeature(faceFeatureInfo3); + + //移除人脸信息 + errorCode = faceEngine.removeFaceFeature(6); + + //引擎卸载 + errorCode = faceEngine.unInit(); + + + } +} \ No newline at end of file diff --git a/login/src/main/java/com/guwan/face/util/UserInfo.java b/login/src/main/java/com/guwan/face/util/UserInfo.java new file mode 100644 index 0000000..a5f3bba --- /dev/null +++ b/login/src/main/java/com/guwan/face/util/UserInfo.java @@ -0,0 +1,11 @@ +package com.guwan.face.util; + + +import lombok.Data; + +@Data +public class UserInfo { + private String faceId; + private String name; + private byte[] faceFeature; +} diff --git a/login/src/main/java/com/guwan/face/util/UserRamCache.java b/login/src/main/java/com/guwan/face/util/UserRamCache.java new file mode 100644 index 0000000..911fa7a --- /dev/null +++ b/login/src/main/java/com/guwan/face/util/UserRamCache.java @@ -0,0 +1,66 @@ +package com.guwan.face.util; + +import com.google.common.collect.Lists; + +import java.util.List; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArraySet; + +public class UserRamCache { + + private final ConcurrentHashMap USER_INFO_MAP = new ConcurrentHashMap<>(); + + private final Set REGISTER = new CopyOnWriteArraySet<>(); + + public void addUser(UserInfo userInfo) { + USER_INFO_MAP.put(userInfo.getFaceId(), userInfo); + for (Listener listener : REGISTER) { + listener.onAdd(userInfo); + } + } + + public void removeUser(String faceId) { + UserInfo userInfo = USER_INFO_MAP.remove(faceId); + for (Listener listener : REGISTER) { + listener.onRemove(userInfo); + } + } + + public List getUserList() { + List userInfoList = Lists.newLinkedList(); + userInfoList.addAll(USER_INFO_MAP.values()); + return userInfoList; + } + + public void clear(){ + USER_INFO_MAP.clear(); + REGISTER.clear(); + } + + public void addListener(Listener listener) { + REGISTER.add(listener); + } + + public void removeListener(Listener listener) { + REGISTER.remove(listener); + } + +// @Data +// public class UserInfo { +// +// private String faceId; +// private String name; +// private byte[] faceFeature; +// +// } + + public interface Listener { + default void onAdd(UserInfo userInfo) { + } + + default void onRemove(UserInfo userInfo) { + + } + } +} diff --git a/login/src/main/java/com/guwan/face/util/UserRamGroup.java b/login/src/main/java/com/guwan/face/util/UserRamGroup.java new file mode 100644 index 0000000..429724b --- /dev/null +++ b/login/src/main/java/com/guwan/face/util/UserRamGroup.java @@ -0,0 +1,42 @@ +package com.guwan.face.util; + +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +public class UserRamGroup { + + private static final ConcurrentHashMap USER_RAM_GROUP_MAP = new ConcurrentHashMap<>(); + private static final ConcurrentHashMap ORG_CELL_MAP = new ConcurrentHashMap<>(); + + public static void addCell(String cellId){ + UserRamCache cell = new UserRamCache(); + USER_RAM_GROUP_MAP.put(cellId,cell); + } + + public static void removeCell(String cellId){ + USER_RAM_GROUP_MAP.remove(cellId); + } + + public static void addUser(UserInfo userInfo, String cellId) { + USER_RAM_GROUP_MAP.get(cellId).addUser(userInfo); + } + + public static void removeUser(String faceId, String cellId) { + USER_RAM_GROUP_MAP.get(cellId).removeUser(faceId); + } + + public static List getUserList(String cellId) { + return USER_RAM_GROUP_MAP.get(cellId).getUserList(); + } + + public static void addOrgId(String orgId,String cellId){ + ORG_CELL_MAP.put(orgId,cellId); + } + public static String getOrgCellMap(String orgId) { + return ORG_CELL_MAP.get(orgId); + } + + public static void clear(){ + USER_RAM_GROUP_MAP.clear(); + } +} diff --git a/login/src/main/java/com/guwan/util/PathUtil.java b/login/src/main/java/com/guwan/util/PathUtil.java new file mode 100644 index 0000000..fab958a --- /dev/null +++ b/login/src/main/java/com/guwan/util/PathUtil.java @@ -0,0 +1,12 @@ +package com.guwan.util; + +public class PathUtil { + + public static String path(){ + return System.getProperty("user.dir") + "\\Guwan\\"; + } + + public static String path(String path){ + return System.getProperty("user.dir") + "\\Guwan\\" + path; + } +} diff --git a/login/src/main/resources/application.yml b/login/src/main/resources/application.yml index 4ace2f2..ad1fe7e 100644 --- a/login/src/main/resources/application.yml +++ b/login/src/main/resources/application.yml @@ -9,10 +9,12 @@ spring: password: aliredis666 database: 1 datasource: - driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://127.0.0.1:3306/studb - username: root - password: 123456 + druid: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://127.0.0.1:3306/studb + username: root + password: X1p6x5irECRCLpqsOAIjh1w4VBPK0x3AP1WNNz8xVmhGx98BANEsw2KQKmBIagzCVo6aBrveoHwWa6FA9gXcwQ== + connection-properties: config.decrypt=true;config.decrypt.key=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAIQ/kwu9OapBDTOTUzM7CGWbbo2+qfCybUDctQcKeGptz8nhQYAzsU9JyfaDQE9RhFj7pwwD8JgB4qJWycicdXcCAwEAAQ== servlet: multipart: @@ -50,4 +52,20 @@ global: port: 9000 accessKey: admin secretKey: admin123456 - bucketName: cuwan \ No newline at end of file + bucketName: cuwan + + file_path: + static-locations: \Guwan\ + + +config: + arcface-sdk: + version: 4.1 + app-id: FnMJV3NVD5ddwF43mdjNDLWPJwXjLAcp8qJDdkaijus4 + sdk-key: AWJo7q7994q97qHrXKvZ54mAADcrkLvEBLZ1voPdUxZE + active-key: 86L1-11RL-613B-GT8B #本机 + active-file: + detect-pool-size: 16 + compare-pool-size: 16 + rec-face-thd: 0.8 + rec-id-thd: 0.5 \ No newline at end of file diff --git a/login/src/main/resources/banner.txt b/login/src/main/resources/banner.txt new file mode 100644 index 0000000..189afd3 --- /dev/null +++ b/login/src/main/resources/banner.txt @@ -0,0 +1 @@ +零基础!学挨踢!!月薪过ONE!!! \ No newline at end of file diff --git a/login/src/test/java/com/guwan/EncryptPwdUtil.java b/login/src/test/java/com/guwan/EncryptPwdUtil.java new file mode 100644 index 0000000..e9fef0f --- /dev/null +++ b/login/src/test/java/com/guwan/EncryptPwdUtil.java @@ -0,0 +1,19 @@ +package com.guwan; + +import com.alibaba.druid.filter.config.ConfigTools; + +public class EncryptPwdUtil { + + public static void main(String[] args) { + try { + String password = "123456"; + String[] arr = ConfigTools.genKeyPair(512); + + // System.out.println("privateKey:" + arr[0]); + System.out.println("publicKey:" + arr[1]); + System.out.println("password:" + ConfigTools.encrypt(arr[0], password)); + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file