|
@@ -1,44 +1,129 @@
|
|
|
package org.dromara.server.consume.service.impl;
|
|
package org.dromara.server.consume.service.impl;
|
|
|
|
|
|
|
|
-import cn.hutool.core.date.DateUtil;
|
|
|
|
|
-import cn.hutool.core.util.ObjectUtil;
|
|
|
|
|
|
|
+import cn.hutool.core.codec.Base64;
|
|
|
|
|
+import com.arcsoft.face.*;
|
|
|
|
|
+import com.arcsoft.face.enums.DetectMode;
|
|
|
|
|
+import com.arcsoft.face.enums.DetectOrient;
|
|
|
|
|
+import com.arcsoft.face.toolkit.ImageInfo;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
import lombok.RequiredArgsConstructor;
|
|
|
-import org.dromara.server.consume.domain.vo.YcFaceFeatureVo;
|
|
|
|
|
-import org.dromara.server.consume.service.IFaceEngineService;
|
|
|
|
|
-import org.dromara.server.consume.service.IPtTermFaceVersionService;
|
|
|
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
+import org.apache.commons.pool2.impl.GenericObjectPool;
|
|
|
|
|
+import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
|
|
|
|
|
+import org.dromara.server.consume.config.ArcFaceConfig;
|
|
|
|
|
+import org.dromara.server.consume.config.FaceEngineFactory;
|
|
|
|
|
+import org.dromara.server.consume.service.FaceEngineService;
|
|
|
|
|
+import org.slf4j.Logger;
|
|
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
|
|
-import java.util.Date;
|
|
|
|
|
|
|
+import javax.annotation.PostConstruct;
|
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
|
+import java.util.Arrays;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * name: FaceEngineServiceImpl
|
|
|
|
|
- * package: org.dromara.server.consume.service.impl
|
|
|
|
|
- * description: 人脸消费相关服务实现
|
|
|
|
|
- * date: 2025-02-26 14:08:27 14:08
|
|
|
|
|
- *
|
|
|
|
|
- * @author luoyibo
|
|
|
|
|
- * @version 0.1
|
|
|
|
|
- * @since JDK 1.8
|
|
|
|
|
|
|
+ * @author flysheep
|
|
|
|
|
+ * @date 2020/7/27 0027
|
|
|
|
|
+ * @time 15:40
|
|
|
*/
|
|
*/
|
|
|
-@RequiredArgsConstructor
|
|
|
|
|
@Service
|
|
@Service
|
|
|
-public class FaceEngineServiceImpl implements IFaceEngineService {
|
|
|
|
|
- private final IPtTermFaceVersionService termFaceVersionService;
|
|
|
|
|
- /**
|
|
|
|
|
- * 增量获取人脸特征数据
|
|
|
|
|
- * @param termNo 消费机编号
|
|
|
|
|
- * @return 人脸特征数据
|
|
|
|
|
- */
|
|
|
|
|
|
|
+@Slf4j
|
|
|
|
|
+@RequiredArgsConstructor
|
|
|
|
|
+public class FaceEngineServiceImpl implements FaceEngineService {
|
|
|
|
|
+ public final static Logger logger = LoggerFactory.getLogger(FaceEngineServiceImpl.class);
|
|
|
|
|
+ private final ArcFaceConfig arcFaceConfig;
|
|
|
|
|
+ // 通用人脸识别引擎池
|
|
|
|
|
+ private GenericObjectPool<FaceEngine> faceEngineGeneralPool;
|
|
|
|
|
+
|
|
|
|
|
+ // 引擎配置
|
|
|
|
|
+ @PostConstruct
|
|
|
|
|
+ public void init() {
|
|
|
|
|
+ GenericObjectPoolConfig detectPoolConfig = new GenericObjectPoolConfig();
|
|
|
|
|
+ detectPoolConfig.setMaxIdle(arcFaceConfig.getDetectPooSize());
|
|
|
|
|
+ detectPoolConfig.setMaxTotal(arcFaceConfig.getDetectPooSize());
|
|
|
|
|
+ detectPoolConfig.setMinIdle(arcFaceConfig.getDetectPooSize());
|
|
|
|
|
+ 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(arcFaceConfig.getSdkLibPath(),
|
|
|
|
|
+ arcFaceConfig.getAppId(), arcFaceConfig.getSdkKey(), null, detectCfg,
|
|
|
|
|
+ arcFaceConfig.activeFile), detectPoolConfig);// 底层库算法对象池
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 人脸检测
|
|
|
@Override
|
|
@Override
|
|
|
- public List<YcFaceFeatureVo> getIncrementFeatureDataUser(Integer termNo) {
|
|
|
|
|
- Long versionTime = termFaceVersionService.getFaceVersionByTerm(termNo);
|
|
|
|
|
- if(ObjectUtil.isEmpty(versionTime) || versionTime==0L){
|
|
|
|
|
- // 如果没有该值或为0,那么认为是初次调用,因此返回全量数据
|
|
|
|
|
- return List.of();
|
|
|
|
|
|
|
+ public List<FaceInfo> detectFaces(ImageInfo imageInfo) {
|
|
|
|
|
+ // 参数判断
|
|
|
|
|
+ if (imageInfo == null)
|
|
|
|
|
+ return null;
|
|
|
|
|
+ // FaceEngine人脸引擎类
|
|
|
|
|
+ FaceEngine faceEngine = null;
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 这里进行获取
|
|
|
|
|
+ faceEngine = faceEngineGeneralPool.borrowObject();
|
|
|
|
|
+ if (faceEngine == null) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ List<FaceInfo> faceInfoList = new ArrayList<>();
|
|
|
|
|
+ // 我们进行人脸检测
|
|
|
|
|
+
|
|
|
|
|
+ int errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(),
|
|
|
|
|
+ imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
|
|
|
|
|
+ if (errorCode == 0) {
|
|
|
|
|
+ return faceInfoList;
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ logger.error(e.getMessage());
|
|
|
|
|
+ logger.error(Arrays.toString(e.getStackTrace()));
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ if (faceEngine != null) {
|
|
|
|
|
+ // 释放引擎对象
|
|
|
|
|
+ faceEngineGeneralPool.returnObject(faceEngine);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- Date lastDown = DateUtil.date(versionTime);
|
|
|
|
|
- return List.of();
|
|
|
|
|
|
|
+ // 生成特征码
|
|
|
|
|
+ // 这里还需要改,关于图片处理
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public String createFeatureData(ImageInfo imageInfo) {
|
|
|
|
|
+ // 获取脸部算法
|
|
|
|
|
+ // FaceEngine人脸引擎类
|
|
|
|
|
+ FaceEngine faceEngine = null;
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 这里进行获取人脸引擎
|
|
|
|
|
+ faceEngine = faceEngineGeneralPool.borrowObject();
|
|
|
|
|
+ List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
|
|
|
|
|
+ // 人脸检测返回值
|
|
|
|
|
+ int code = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(),
|
|
|
|
|
+ imageInfo.getImageFormat(), faceInfoList);
|
|
|
|
|
+ if (code == 0 && !faceInfoList.isEmpty()) {
|
|
|
|
|
+ FaceFeature faceFeature = new FaceFeature();
|
|
|
|
|
+ faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(),
|
|
|
|
|
+ imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature);
|
|
|
|
|
+ return Base64.encode(faceFeature.getFeatureData());
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ logger.error(e.getMessage());
|
|
|
|
|
+ logger.error(Arrays.toString(e.getStackTrace()));
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ if (faceEngine != null) {
|
|
|
|
|
+ // 释放引擎对象
|
|
|
|
|
+ faceEngineGeneralPool.returnObject(faceEngine);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return null;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
}
|
|
}
|