|
@@ -0,0 +1,223 @@
|
|
|
|
+package com.pj.project4sp.face.handler.impl;
|
|
|
|
+
|
|
|
|
+import cn.hutool.core.io.FileUtil;
|
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
|
+import com.arcsoft.face.*;
|
|
|
|
+import com.arcsoft.face.enums.DetectMode;
|
|
|
|
+import com.arcsoft.face.enums.DetectOrient;
|
|
|
|
+import com.arcsoft.face.toolkit.ImageFactory;
|
|
|
|
+import com.arcsoft.face.toolkit.ImageInfo;
|
|
|
|
+import com.pj.current.config.SystemObject;
|
|
|
|
+import com.pj.project4sp.face.brand.FaceBrand;
|
|
|
|
+import com.pj.project4sp.face.factory.FaceEngineFactory;
|
|
|
|
+import com.pj.project4sp.face.handler.IFaceHandler;
|
|
|
|
+import com.pj.project4sp.face.handler.VerifyVO;
|
|
|
|
+import com.pj.utils.sg.AjaxError;
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
|
+import org.apache.commons.pool2.impl.GenericObjectPool;
|
|
|
|
+import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
|
|
|
|
+import org.springframework.context.annotation.DependsOn;
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
+
|
|
|
|
+import javax.annotation.PostConstruct;
|
|
|
|
+import java.io.File;
|
|
|
|
+import java.io.FileOutputStream;
|
|
|
|
+import java.io.IOException;
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
+import java.util.Base64;
|
|
|
|
+import java.util.List;
|
|
|
|
+import java.util.concurrent.ExecutorService;
|
|
|
|
+import java.util.concurrent.Executors;
|
|
|
|
+
|
|
|
|
+import static com.arcsoft.face.toolkit.ImageFactory.getRGBData;
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 基于ArcSoft Face的人��识别
|
|
|
|
+ */
|
|
|
|
+@Service
|
|
|
|
+@Slf4j
|
|
|
|
+@DependsOn({"systemObject"})
|
|
|
|
+public class ArcsoftFaceHandlerImpl implements IFaceHandler {
|
|
|
|
+
|
|
|
|
+ //通用人脸识别引擎池
|
|
|
|
+ private GenericObjectPool<FaceEngine> faceEngineGeneralPool;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ private ExecutorService compareExecutorService;
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public boolean checkIsLive(String baseImg) {
|
|
|
|
+ List<LivenessInfo> livenessInfoList = new ArrayList<>();
|
|
|
|
+ FaceEngine faceEngine = null;
|
|
|
|
+ try {
|
|
|
|
+ faceEngine = faceEngineGeneralPool.borrowObject();
|
|
|
|
+ faceEngine.getLiveness(livenessInfoList);
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ throw new AjaxError("获取识别引擎失败");
|
|
|
|
+ } finally {
|
|
|
|
+ if (faceEngine != null) {
|
|
|
|
+ faceEngineGeneralPool.returnObject(faceEngine);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return livenessInfoList.get(0).getLiveness() == 1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void createPersonByBase(String faceId, String name, String imageBase) {
|
|
|
|
+ byte[] imageBytes = Base64.getDecoder().decode(imageBase);
|
|
|
|
+ this.createPersonByBase(faceId, name, imageBytes);
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void createPersonByBase(String faceId, String name, byte[] imageBytes) {
|
|
|
|
+ String facePath = SystemObject.getFaceImgPath();
|
|
|
|
+ File outputFile = new File(facePath + File.separator + faceId + ".png");
|
|
|
|
+ FileUtil.del(outputFile);
|
|
|
|
+ // 创建输出流
|
|
|
|
+ try (FileOutputStream fileOutputStream = new FileOutputStream(outputFile)) {
|
|
|
|
+ // 写入数据到文件
|
|
|
|
+ fileOutputStream.write(imageBytes);
|
|
|
|
+ } catch (IOException e) {
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void deletePerson(String faceId) {
|
|
|
|
+ String facePath = SystemObject.getFaceImgPath();
|
|
|
|
+ File outputFile = new File(facePath + File.separator + faceId + ".png");
|
|
|
|
+ FileUtil.del(outputFile);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public boolean checkHasPerson(String img) {
|
|
|
|
+ byte[] imageBytes = Base64.getDecoder().decode(img);
|
|
|
|
+ return this.checkHasPerson(imageBytes);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public boolean checkHasPerson(byte[] imageBase) {
|
|
|
|
+ ImageInfo imageInfo = getRGBData(imageBase);
|
|
|
|
+ List<FaceInfo> faceInfoList = new ArrayList<>();
|
|
|
|
+ FaceEngine faceEngine = null;
|
|
|
|
+ try {
|
|
|
|
+ faceEngine = faceEngineGeneralPool.borrowObject();
|
|
|
|
+ faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ throw new AjaxError("获取识别引擎失败");
|
|
|
|
+ } finally {
|
|
|
|
+ if (faceEngine != null) {
|
|
|
|
+ faceEngineGeneralPool.returnObject(faceEngine);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return faceInfoList.size() == 1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public VerifyVO verify(String faceId, String baseImage) {
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ byte[] imageBytes = Base64.getDecoder().decode(baseImage);
|
|
|
|
+ return this.verify(faceId,imageBytes);
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public VerifyVO verify(String faceId, byte[] imageBytes) {
|
|
|
|
+ VerifyVO vo = new VerifyVO();
|
|
|
|
+ String facePath = SystemObject.getFaceImgPath();
|
|
|
|
+ File file = new File(facePath + File.separator + faceId + ".png");
|
|
|
|
+ if (!file.exists()) {
|
|
|
|
+ vo.setMsg("人员ID不存在");
|
|
|
|
+ return vo;
|
|
|
|
+ }
|
|
|
|
+ ImageInfo sourceImageInfo = getRGBData(imageBytes);
|
|
|
|
+ List<FaceInfo> sourceFaceInfoList = new ArrayList<>();
|
|
|
|
+ FaceEngine faceEngine = null;
|
|
|
|
+ try {
|
|
|
|
+ faceEngine = faceEngineGeneralPool.borrowObject();
|
|
|
|
+ faceEngine.detectFaces(sourceImageInfo.getImageData(), sourceImageInfo.getWidth(), sourceImageInfo.getHeight(), sourceImageInfo.getImageFormat(), sourceFaceInfoList);
|
|
|
|
+ if (sourceFaceInfoList.size() == 0) {
|
|
|
|
+ vo.setMsg("No faces");
|
|
|
|
+ return vo;
|
|
|
|
+ }
|
|
|
|
+ if (sourceFaceInfoList.size() > 1) {
|
|
|
|
+ vo.setMsg("图片中存在多个人脸");
|
|
|
|
+ return vo;
|
|
|
|
+ }
|
|
|
|
+ FaceInfo faceInfo = sourceFaceInfoList.get(0);
|
|
|
|
+ FaceFeature sourceFaceFeature = new FaceFeature();
|
|
|
|
+ faceEngine.extractFaceFeature(sourceImageInfo.getImageData(), sourceImageInfo.getWidth(), sourceImageInfo.getHeight(), sourceImageInfo.getImageFormat(), faceInfo, sourceFaceFeature);
|
|
|
|
+
|
|
|
|
+ //目标图片人脸
|
|
|
|
+ List<FaceInfo> targeFaceInfoList = new ArrayList<>();
|
|
|
|
+ ImageInfo imageInfo2 = getRGBData(file);
|
|
|
|
+ faceEngine.detectFaces(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(), imageInfo2.getImageFormat(), targeFaceInfoList);
|
|
|
|
+ //特征提取
|
|
|
|
+ FaceFeature targeFaceFeature = new FaceFeature();
|
|
|
|
+ faceEngine.extractFaceFeature(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(), imageInfo2.getImageFormat(), targeFaceInfoList.get(0), targeFaceFeature);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ FaceSimilar faceSimilar = new FaceSimilar();
|
|
|
|
+ faceEngine.compareFaceFeature(new FaceFeature(targeFaceFeature.getFeatureData()), new FaceFeature(sourceFaceFeature.getFeatureData()), faceSimilar);
|
|
|
|
+ boolean result = faceSimilar.getScore() > 0.85f;
|
|
|
|
+ String msg = result ? "人脸一致" : "不匹配";
|
|
|
|
+ vo.setSuccess(result);
|
|
|
|
+ vo.setMsg(msg);
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ throw new AjaxError("获取识别引擎失败");
|
|
|
|
+ } finally {
|
|
|
|
+ if (faceEngine != null) {
|
|
|
|
+ faceEngineGeneralPool.returnObject(faceEngine);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return vo;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public List<String> faceSearch(String baseImg) {
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public FaceBrand faceBrand() {
|
|
|
|
+ return FaceBrand.ARCSOFT;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ @PostConstruct
|
|
|
|
+ public void init() {
|
|
|
|
+
|
|
|
|
+ if (!StrUtil.equals(SystemObject.config.getFaceType(), FaceBrand.ARCSOFT.getType())) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ String appId = SystemObject.config.getArcsoftAppid();
|
|
|
|
+ String sdkKey = SystemObject.config.getArcsoftSdkKey();
|
|
|
|
+ log.info("Initializing------:{}:{}", appId, sdkKey);
|
|
|
|
+
|
|
|
|
+ GenericObjectPoolConfig detectPoolConfig = new GenericObjectPoolConfig();
|
|
|
|
+ detectPoolConfig.setMaxIdle(5);
|
|
|
|
+ detectPoolConfig.setMaxTotal(5);
|
|
|
|
+ detectPoolConfig.setMinIdle(5);
|
|
|
|
+ detectPoolConfig.setLifo(false);
|
|
|
|
+ EngineConfiguration detectCfg = new EngineConfiguration();
|
|
|
|
+ FunctionConfiguration detectFunctionCfg = new FunctionConfiguration();
|
|
|
|
+ detectFunctionCfg.setSupportFaceDetect(true);//开启人脸检测功能
|
|
|
|
+ detectFunctionCfg.setSupportFaceRecognition(true);//开启人脸识别功能
|
|
|
|
+ detectCfg.setFunctionConfiguration(detectFunctionCfg);
|
|
|
|
+ detectCfg.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);//图片检测模式,如果是连续帧的视频流图片,那么改成VIDEO模式
|
|
|
|
+ detectCfg.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);//人脸旋转角度
|
|
|
|
+ faceEngineGeneralPool = new GenericObjectPool(new FaceEngineFactory(appId, sdkKey, null, detectCfg), detectPoolConfig);//底层库算法对象池
|
|
|
|
+ compareExecutorService = Executors.newFixedThreadPool(5);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+}
|