|
@@ -5,9 +5,13 @@ import cn.hutool.core.date.DateUtil;
|
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
|
import com.arcsoft.face.toolkit.ImageInfo;
|
|
import com.arcsoft.face.toolkit.ImageInfo;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
import lombok.RequiredArgsConstructor;
|
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
import org.apache.dubbo.config.annotation.DubboReference;
|
|
import org.apache.dubbo.config.annotation.DubboReference;
|
|
|
import org.dromara.backstage.api.RemoteUserAccountService;
|
|
import org.dromara.backstage.api.RemoteUserAccountService;
|
|
|
import org.dromara.backstage.api.domain.vo.RemoteUserAccountVo;
|
|
import org.dromara.backstage.api.domain.vo.RemoteUserAccountVo;
|
|
|
|
|
+import org.dromara.common.core.domain.R;
|
|
|
|
|
+import org.dromara.common.core.domain.model.ErrorInfo;
|
|
|
|
|
+import org.dromara.common.core.enums.ResultCodeEnum;
|
|
|
import org.dromara.common.core.utils.MapstructUtils;
|
|
import org.dromara.common.core.utils.MapstructUtils;
|
|
|
import org.dromara.server.consume.domain.bo.PtArcFaceFeatureBo;
|
|
import org.dromara.server.consume.domain.bo.PtArcFaceFeatureBo;
|
|
|
import org.dromara.server.consume.domain.vo.PtArcFaceFeatureVo;
|
|
import org.dromara.server.consume.domain.vo.PtArcFaceFeatureVo;
|
|
@@ -20,8 +24,10 @@ import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
|
|
import java.io.File;
|
|
import java.io.File;
|
|
|
|
|
+import java.text.MessageFormat;
|
|
|
import java.util.Date;
|
|
import java.util.Date;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
|
|
|
|
import static com.arcsoft.face.toolkit.ImageFactory.getRGBData;
|
|
import static com.arcsoft.face.toolkit.ImageFactory.getRGBData;
|
|
|
|
|
|
|
@@ -37,19 +43,18 @@ import static com.arcsoft.face.toolkit.ImageFactory.getRGBData;
|
|
|
*/
|
|
*/
|
|
|
@RequiredArgsConstructor
|
|
@RequiredArgsConstructor
|
|
|
@Service
|
|
@Service
|
|
|
|
|
+@Slf4j
|
|
|
public class ArcFaceBusiness {
|
|
public class ArcFaceBusiness {
|
|
|
- @Value("${upload.upload-path}/") // 文件上传路径
|
|
|
|
|
- private String uploadPath;
|
|
|
|
|
- @Value("${upload.image.user}/") // 用户头像路径
|
|
|
|
|
- private String userPath;
|
|
|
|
|
-
|
|
|
|
|
private final IPtTermFaceVersionService termFaceVersionService;
|
|
private final IPtTermFaceVersionService termFaceVersionService;
|
|
|
private final IPtArcFaceFeatureService arcFaceFeatureService;
|
|
private final IPtArcFaceFeatureService arcFaceFeatureService;
|
|
|
private final IPtArcFaceKeyService arcFaceKeyService;
|
|
private final IPtArcFaceKeyService arcFaceKeyService;
|
|
|
private final FaceEngineService faceEngineService;
|
|
private final FaceEngineService faceEngineService;
|
|
|
-
|
|
|
|
|
@DubboReference
|
|
@DubboReference
|
|
|
private final RemoteUserAccountService remoteUserAccountService;
|
|
private final RemoteUserAccountService remoteUserAccountService;
|
|
|
|
|
+ @Value("${upload.upload-path}/") // 文件上传路径
|
|
|
|
|
+ private String uploadPath;
|
|
|
|
|
+ @Value("${upload.image.user}/") // 用户头像路径
|
|
|
|
|
+ private String userPath;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 全量下载人脸特征数据
|
|
* 全量下载人脸特征数据
|
|
@@ -96,7 +101,7 @@ public class ArcFaceBusiness {
|
|
|
|
|
|
|
|
// 如果不存在或者已更新,则重新生成特征码
|
|
// 如果不存在或者已更新,则重新生成特征码
|
|
|
if (ObjectUtil.isEmpty(vo) || ObjectUtil.notEqual(photoUrl, vo.getPhotoUrl())) {
|
|
if (ObjectUtil.isEmpty(vo) || ObjectUtil.notEqual(photoUrl, vo.getPhotoUrl())) {
|
|
|
- String fileUrl = uploadPath + userPath +photoUrl;
|
|
|
|
|
|
|
+ String fileUrl = uploadPath + userPath + photoUrl;
|
|
|
File imageFile = new File(fileUrl);
|
|
File imageFile = new File(fileUrl);
|
|
|
if (!imageFile.exists()) {
|
|
if (!imageFile.exists()) {
|
|
|
return null;
|
|
return null;
|
|
@@ -123,6 +128,8 @@ public class ArcFaceBusiness {
|
|
|
// 重新从数据中获取数据
|
|
// 重新从数据中获取数据
|
|
|
vo = arcFaceFeatureService.getOneFeatureDataUser(userId);
|
|
vo = arcFaceFeatureService.getOneFeatureDataUser(userId);
|
|
|
vo.setUserNo(accountVo.getUserNo().toString());
|
|
vo.setUserNo(accountVo.getUserNo().toString());
|
|
|
|
|
+ vo.setUserNumb(accountVo.getUserNumb());
|
|
|
|
|
+ vo.setRealName(accountVo.getRealName());
|
|
|
return MapstructUtils.convert(vo, YcFaceFeatureVo.class);
|
|
return MapstructUtils.convert(vo, YcFaceFeatureVo.class);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -158,12 +165,92 @@ public class ArcFaceBusiness {
|
|
|
return termFaceVersionService.updateFaceVersionByTerm(termNo, versionTime);
|
|
return termFaceVersionService.updateFaceVersionByTerm(termNo, versionTime);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- public void createAllFeatureDataUser(){
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 创建所有用户的人脸特征数据。
|
|
|
|
|
+ * 该方法会从远程用户账户服务获取所有用户账户信息,并为每个用户生成人脸特征数据。
|
|
|
|
|
+ * 如果用户的照片不为空,则尝试为其生成人脸特征码。此过程是并行执行的。
|
|
|
|
|
+ * 方法会统计总处理人数、成功人数和失败人数,并在完成后返回结果信息。
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return 返回一个包含操作结果信息的R对象。如果没有任何需要生成人脸特征的人员,将返回相应的提示信息;
|
|
|
|
|
+ * 否则,返回生成特征码的结果摘要信息。
|
|
|
|
|
+ */
|
|
|
|
|
+ public R<Void> createAllFeatureDataUser() {
|
|
|
List<RemoteUserAccountVo> userAccountVoList = remoteUserAccountService.getAllUserAccountVo();
|
|
List<RemoteUserAccountVo> userAccountVoList = remoteUserAccountService.getAllUserAccountVo();
|
|
|
|
|
+ AtomicInteger totalCount = new AtomicInteger();
|
|
|
|
|
+ AtomicInteger okCount = new AtomicInteger();
|
|
|
|
|
+ AtomicInteger failCount = new AtomicInteger();
|
|
|
if (CollectionUtil.isNotEmpty(userAccountVoList)) {
|
|
if (CollectionUtil.isNotEmpty(userAccountVoList)) {
|
|
|
- userAccountVoList.parallelStream().forEach(p->{
|
|
|
|
|
- YcFaceFeatureVo vo = this.getOneFeatureDataUser(p.getUserId());
|
|
|
|
|
|
|
+ userAccountVoList.parallelStream().forEach(p -> {
|
|
|
|
|
+ if (ObjectUtil.isNotEmpty(p.getPhoto())) {
|
|
|
|
|
+ totalCount.getAndIncrement();
|
|
|
|
|
+ try {
|
|
|
|
|
+ R<ErrorInfo> result = createFeatureDataOne(p.getUserId(), p.getPhoto());
|
|
|
|
|
+ if (R.isError(result)) {
|
|
|
|
|
+ log.error("[生成特征码失败]-[{}]", result.getData());
|
|
|
|
|
+ failCount.getAndIncrement();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ okCount.getAndIncrement();
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("生成特征码失败", e);
|
|
|
|
|
+ failCount.getAndIncrement();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
});
|
|
});
|
|
|
|
|
+ String msg = MessageFormat.format("[生成人脸特征码完成]-[共:{0}人,成功:{1}人,失败:{2}人]", totalCount, okCount.get(), failCount.get());
|
|
|
|
|
+ return R.ok(msg);
|
|
|
|
|
+ }
|
|
|
|
|
+ return R.ok("没有需要生成人脸特征的人员");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 创建人脸特征数据。
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param userId 用户ID,不能为空。
|
|
|
|
|
+ * @param photoUrl 照片URL,不能为空。
|
|
|
|
|
+ * @return 返回一个包含错误信息的Result对象。如果操作成功,则返回成功的结果;如果失败,则返回相应的错误信息。
|
|
|
|
|
+ */
|
|
|
|
|
+ public R<ErrorInfo> createFeatureDataOne(Long userId, String photoUrl) {
|
|
|
|
|
+ if (ObjectUtil.isEmpty(photoUrl)) {
|
|
|
|
|
+ return R.fail(new ErrorInfo(ResultCodeEnum.PARAM_IS_BLANK.code(), "", "照片路径不能为空"));
|
|
|
|
|
+ }
|
|
|
|
|
+ if (ObjectUtil.isEmpty(userId)) {
|
|
|
|
|
+ return R.fail(new ErrorInfo(ResultCodeEnum.PARAM_IS_BLANK.code(), "", "照片路径不能为空"));
|
|
|
|
|
+ }
|
|
|
|
|
+ String fileUrl = uploadPath + userPath + photoUrl;
|
|
|
|
|
+ File imageFile = new File(fileUrl);
|
|
|
|
|
+ if (!imageFile.exists()) {
|
|
|
|
|
+ return R.fail(new ErrorInfo(ResultCodeEnum.RESOURCE_NOT_EXISTED.code(), "", "无人脸照片文件"));
|
|
|
|
|
+ }
|
|
|
|
|
+ ImageInfo imageInfo = getRGBData(imageFile);
|
|
|
|
|
+ if (imageInfo == null) {
|
|
|
|
|
+ return R.fail(new ErrorInfo(ResultCodeEnum.RESOURCE_NOT_EXISTED.code(), "", "生成人脸图片信息失败"));
|
|
|
|
|
+ }
|
|
|
|
|
+ String featureData = faceEngineService.createFeatureData(imageInfo);
|
|
|
|
|
+ if (ObjectUtil.isEmpty(featureData)) {
|
|
|
|
|
+ return R.fail(new ErrorInfo(ResultCodeEnum.RESOURCE_NOT_EXISTED.code(), "", "生成人脸特征信息失败"));
|
|
|
|
|
+ }
|
|
|
|
|
+ insertFaceFeatureInfo(userId, photoUrl, featureData);
|
|
|
|
|
+ return R.ok();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 人脸特征信息入库
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param userId 用户Id.
|
|
|
|
|
+ * @param photoUrl 照片地址
|
|
|
|
|
+ * @param featureData 人脸特征数据
|
|
|
|
|
+ */
|
|
|
|
|
+ public void insertFaceFeatureInfo(Long userId, String photoUrl, String featureData) {
|
|
|
|
|
+ PtArcFaceFeatureVo vo = arcFaceFeatureService.getOneFeatureDataUser(userId);
|
|
|
|
|
+ if (ObjectUtil.isEmpty(vo)) {
|
|
|
|
|
+ PtArcFaceFeatureBo bo = new PtArcFaceFeatureBo();
|
|
|
|
|
+ bo.setUserId(userId);
|
|
|
|
|
+ bo.setPhotoUrl(photoUrl);
|
|
|
|
|
+ bo.setFeatureData(featureData);
|
|
|
|
|
+ arcFaceFeatureService.insertByBo(bo);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ arcFaceFeatureService.updateFeatureDataByUserId(userId, featureData, photoUrl);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|