|
@@ -15,16 +15,14 @@ import cn.com.qmth.examcloud.support.cache.CacheHelper;
|
|
|
import cn.com.qmth.examcloud.support.cache.bean.ExamRecordPropertyCacheBean;
|
|
|
import cn.com.qmth.examcloud.support.cache.bean.SysPropertyCacheBean;
|
|
|
import cn.com.qmth.examcloud.web.bootstrap.PropertyHolder;
|
|
|
+import com.alibaba.fastjson.JSONArray;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
import org.apache.commons.io.IOUtils;
|
|
|
import org.apache.commons.logging.Log;
|
|
|
import org.apache.commons.logging.LogFactory;
|
|
|
-import org.json.JSONArray;
|
|
|
-import org.json.JSONException;
|
|
|
-import org.json.JSONObject;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
-import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.data.domain.Example;
|
|
|
import org.springframework.data.redis.core.RedisTemplate;
|
|
|
import org.springframework.stereotype.Service;
|
|
@@ -80,7 +78,7 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
|
|
|
*/
|
|
|
@Override
|
|
|
@Transactional
|
|
|
- public void disposeFaceCompare(ExamCaptureQueueEntity examCaptureQueue) throws JSONException {
|
|
|
+ public void disposeFaceCompare(ExamCaptureQueueEntity examCaptureQueue) {
|
|
|
//将队列记录修改为处理中
|
|
|
examCaptureQueueRepo.updateExamCaptureQueueStatusWithProcessing(examCaptureQueue.getId());
|
|
|
examCaptureQueue.setFaceCompareStartTime(System.currentTimeMillis());
|
|
@@ -101,9 +99,12 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
|
|
|
//调用face++API执行人脸比对,得到返回结果
|
|
|
faceCompareResult = faceCompareService.getFaceppCompareResultByUrl(examCaptureQueue.getBaseFaceToken(),
|
|
|
examCaptureQueue.getFileUrl());
|
|
|
+ if (captureLog.isDebugEnabled()) {
|
|
|
+ captureLog.debug("[DISPOSE_FACE_COMPARE] 调用face++API执行人脸比对,得到返回结果faceCompareResult:" + faceCompareResult);
|
|
|
+ }
|
|
|
examCaptureQueue.setFaceCompareResult(faceCompareResult.toString());
|
|
|
|
|
|
- if (faceCompareResult.has(Constants.ERROR_MSG)) {
|
|
|
+ if (faceCompareResult.containsKey(Constants.ERROR_MSG)) {
|
|
|
String errMsg = faceCompareResult.getString(Constants.ERROR_MSG);
|
|
|
|
|
|
//如果API并发次数超过上限,则保存错误信息到队列,并抛出异常,用于协调满载队列线程
|
|
@@ -118,14 +119,14 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
|
|
|
|
|
|
//face++无需重试的错误信息
|
|
|
SysPropertyCacheBean objNotRetryErrMsg = CacheHelper.getSysProperty("facePlusPlus.faceCompare.notRetry.errMsg");
|
|
|
- if (!objNotRetryErrMsg.getHasValue()){
|
|
|
- throw new StatusException("100001","未找到face++人脸比对错误消息的相关配置");
|
|
|
+ if (!objNotRetryErrMsg.getHasValue()) {
|
|
|
+ throw new StatusException("100001", "未找到face++人脸比对错误消息的相关配置");
|
|
|
}
|
|
|
String objNotRetryErrMsgs = objNotRetryErrMsg.getValue().toString();
|
|
|
String[] notRetryErrMsgsArr = objNotRetryErrMsgs.split(",");
|
|
|
- for (int i=0;i<notRetryErrMsgsArr.length;i++){
|
|
|
+ for (int i = 0; i < notRetryErrMsgsArr.length; i++) {
|
|
|
//如果是配置中的无法处理的图片,则保存人脸检测最终结果并删除队列
|
|
|
- if (errMsg.contains(notRetryErrMsgsArr[i])){
|
|
|
+ if (errMsg.contains(notRetryErrMsgsArr[i])) {
|
|
|
saveExamCaptureAndDeleteQueue(examCaptureQueue);
|
|
|
|
|
|
captureLog.debug("[DISPOSE_FACE_COMPARE] face++人脸比对无法处理的图片,保存人脸检测最终结果并删除队列,errMsg=" + errMsg);
|
|
@@ -158,7 +159,7 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
|
|
|
faceCompareResult.toString(), ExamCaptureQueueStatus.PROCESS_FACE_COMPARE_FAILED);
|
|
|
} else {
|
|
|
//face++的结果检测到人脸,才执行百度活体检测
|
|
|
- if (faceCompareResult.has("confidence")) {
|
|
|
+ if (faceCompareResult.containsKey("confidence")) {
|
|
|
examCaptureQueue.setIsPass(calculateFaceCompareIsPass(faceCompareResult));
|
|
|
examCaptureQueue.setIsStranger(calculateFaceCompareIsStranger(examCaptureQueue.getExamRecordDataId(), faceCompareResult));
|
|
|
//更新队列状态为face++比对完成
|
|
@@ -181,7 +182,7 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
|
|
|
|
|
|
@Override
|
|
|
//face++人脸比对失败时,需要将状态置为失败,并清空批次号
|
|
|
- public void disposeFaceCompareFaild(ExamCaptureQueueEntity examCaptureQueue){
|
|
|
+ public void disposeFaceCompareFaild(ExamCaptureQueueEntity examCaptureQueue) {
|
|
|
examCaptureQueue.setStatus(ExamCaptureQueueStatus.PROCESS_FACE_COMPARE_FAILED);
|
|
|
examCaptureQueue.setProcessBatchNum("000000");
|
|
|
examCaptureQueueRepo.save(examCaptureQueue);
|
|
@@ -189,7 +190,7 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
|
|
|
|
|
|
@Override
|
|
|
//百度活体检测失败时,需要将状态置为失败,并清空批次号
|
|
|
- public void disposeBaiDuFaceLivenessFaild(ExamCaptureQueueEntity examCaptureQueue){
|
|
|
+ public void disposeBaiDuFaceLivenessFaild(ExamCaptureQueueEntity examCaptureQueue) {
|
|
|
examCaptureQueue.setStatus(ExamCaptureQueueStatus.PROCESS_FACELIVENESS_FAILED);
|
|
|
examCaptureQueue.setProcessBatchNum("000000");
|
|
|
examCaptureQueueRepo.save(examCaptureQueue);
|
|
@@ -202,7 +203,7 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
|
|
|
* @param examCaptureQueue 抓拍照片队列表
|
|
|
*/
|
|
|
@Override
|
|
|
- public void disposeBaiDuFaceLiveness(ExamCaptureQueueEntity examCaptureQueue) throws JSONException {
|
|
|
+ public void disposeBaiDuFaceLiveness(ExamCaptureQueueEntity examCaptureQueue) {
|
|
|
//活体检测超时次数
|
|
|
int facelivenessTimeOutTimes = 0;
|
|
|
//百度活检超时最大重试次数
|
|
@@ -210,7 +211,7 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
|
|
|
boolean retry = false;
|
|
|
JSONObject faceLivenessResultJson;
|
|
|
do {
|
|
|
- retry=false;
|
|
|
+ retry = false;
|
|
|
|
|
|
//仅用于日志时间计算
|
|
|
long startTime = System.currentTimeMillis();
|
|
@@ -220,7 +221,7 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
|
|
|
faceLivenessResultJson = faceLivenessService.getBaiduFaceLivenessResultJson(examCaptureQueue.getFileUrl());
|
|
|
|
|
|
//如果百度活体检测执行失败,调用队列失败处理,程序退出,失败的数据,后续会有自动服务重新处理
|
|
|
- if (faceLivenessResultJson.has(Constants.BAIDU_ERROR_CODE) &&
|
|
|
+ if (faceLivenessResultJson.containsKey(Constants.BAIDU_ERROR_CODE) &&
|
|
|
!faceLivenessResultJson.getString(Constants.BAIDU_ERROR_CODE).equals(Constants.BAIDU_SUCCESS_ERROR_CODE_VALUE)) {
|
|
|
String errCode = faceLivenessResultJson.getString(Constants.BAIDU_ERROR_CODE);
|
|
|
|
|
@@ -236,14 +237,14 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
|
|
|
|
|
|
//百度无需重试的错误信息
|
|
|
SysPropertyCacheBean objNotRetryErrMsg = CacheHelper.getSysProperty("baidu.faceLiveness.notRetry.errCode");
|
|
|
- if (!objNotRetryErrMsg.getHasValue()){
|
|
|
- throw new StatusException("100002","未找到百度活体检测错误代码的相关配置");
|
|
|
+ if (!objNotRetryErrMsg.getHasValue()) {
|
|
|
+ throw new StatusException("100002", "未找到百度活体检测错误代码的相关配置");
|
|
|
}
|
|
|
- String objNotRetryErrMsgs = objNotRetryErrMsg.getValue().toString();
|
|
|
+ String objNotRetryErrMsgs = objNotRetryErrMsg.getValue().toString();
|
|
|
String[] notRetryErrMsgsArr = objNotRetryErrMsgs.split(",");
|
|
|
- for (int i=0;i<notRetryErrMsgsArr.length;i++){
|
|
|
+ for (int i = 0; i < notRetryErrMsgsArr.length; i++) {
|
|
|
//如果是配置中的无法处理的图片,则保存人脸检测最终结果并删除队列
|
|
|
- if (errCode.equals(notRetryErrMsgsArr[i])){
|
|
|
+ if (errCode.equals(notRetryErrMsgsArr[i])) {
|
|
|
captureLog.debug("[DISPOSE_BAIDUFACELIVENESS] 百度活体检测,无法处理的图片,将保存人脸检测最终结果并删除队列,errCode=" + errCode);
|
|
|
|
|
|
saveExamCaptureAndDeleteQueue(examCaptureQueue);
|
|
@@ -342,26 +343,21 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
|
|
|
compareFaceSyncInfo.setStudentId(studentId);
|
|
|
File tempFile = getUploadFile(file);
|
|
|
|
|
|
- try {
|
|
|
- JSONObject facePPResult = faceCompareService.getFaceppCompareResultByFile(baseFaceToken, tempFile);
|
|
|
- if (facePPResult.has(Constants.ERROR_MSG)) {
|
|
|
+ JSONObject facePPResult = faceCompareService.getFaceppCompareResultByFile(baseFaceToken, tempFile);
|
|
|
+ if (facePPResult.containsKey(Constants.ERROR_MSG)) {
|
|
|
+ compareFaceSyncInfo.setIsPass(false);
|
|
|
+ compareFaceSyncInfo.setErrorMsg(facePPResult.toString());
|
|
|
+ } else {
|
|
|
+ if (facePPResult.containsKey("confidence")) {
|
|
|
+ double confidence = facePPResult.getDouble("confidence");
|
|
|
+ JSONObject thresholdsJsonObject = facePPResult.getJSONObject("thresholds");
|
|
|
+ double le4 = thresholdsJsonObject.getDouble("1e-4");
|
|
|
+ compareFaceSyncInfo.setIsPass(confidence >= le4);//是否通过
|
|
|
+ compareFaceSyncInfo.setErrorMsg(confidence >= le4 ? null : "confidence<le4");
|
|
|
+ } else {
|
|
|
compareFaceSyncInfo.setIsPass(false);
|
|
|
compareFaceSyncInfo.setErrorMsg(facePPResult.toString());
|
|
|
- } else {
|
|
|
- if (facePPResult.has("confidence")) {
|
|
|
- double confidence = facePPResult.getDouble("confidence");
|
|
|
- JSONObject thresholdsJsonObject = facePPResult.getJSONObject("thresholds");
|
|
|
- double le4 = thresholdsJsonObject.getDouble("1e-4");
|
|
|
- compareFaceSyncInfo.setIsPass(confidence >= le4);//是否通过
|
|
|
- compareFaceSyncInfo.setErrorMsg(confidence >= le4 ? null : "confidence<le4");
|
|
|
- } else {
|
|
|
- compareFaceSyncInfo.setIsPass(false);
|
|
|
- compareFaceSyncInfo.setErrorMsg(facePPResult.toString());
|
|
|
- }
|
|
|
}
|
|
|
- } catch (JSONException e) {
|
|
|
- e.printStackTrace();
|
|
|
- throw new StatusException("JsonFormat001", "同步比较人脸失败");
|
|
|
}
|
|
|
|
|
|
tempFile.delete();
|
|
@@ -372,28 +368,23 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
|
|
|
public CompareFaceSyncInfo compareFaceSyncByFileUrl(Long studentId, String baseFaceToken, String fileUrl) {
|
|
|
CompareFaceSyncInfo compareFaceSyncInfo = new CompareFaceSyncInfo();
|
|
|
compareFaceSyncInfo.setStudentId(studentId);
|
|
|
- try {
|
|
|
- JSONObject facePPResult = faceCompareService.getFaceppCompareResultByUrl(baseFaceToken, fileUrl);
|
|
|
- if (facePPResult.has(Constants.ERROR_MSG)) {
|
|
|
+ JSONObject facePPResult = faceCompareService.getFaceppCompareResultByUrl(baseFaceToken, fileUrl);
|
|
|
+ if (facePPResult.containsKey(Constants.ERROR_MSG)) {
|
|
|
+ compareFaceSyncInfo.setIsPass(false);
|
|
|
+ compareFaceSyncInfo.setErrorMsg(facePPResult.toString());
|
|
|
+ } else {
|
|
|
+ if (facePPResult.containsKey("confidence")) {
|
|
|
+ double confidence = facePPResult.getDouble("confidence");
|
|
|
+ JSONObject thresholdsJsonObject = facePPResult.getJSONObject("thresholds");
|
|
|
+ double le4 = thresholdsJsonObject.getDouble("1e-4");
|
|
|
+ JSONArray face2Array = facePPResult.getJSONArray("faces2");
|
|
|
+ compareFaceSyncInfo.setIsStranger(face2Array.size() > 1);//是否有陌生人
|
|
|
+ compareFaceSyncInfo.setIsPass(confidence >= le4);//是否通过
|
|
|
+ compareFaceSyncInfo.setErrorMsg(confidence >= le4 ? null : "confidence<le4");
|
|
|
+ } else {
|
|
|
compareFaceSyncInfo.setIsPass(false);
|
|
|
compareFaceSyncInfo.setErrorMsg(facePPResult.toString());
|
|
|
- } else {
|
|
|
- if (facePPResult.has("confidence")) {
|
|
|
- double confidence = facePPResult.getDouble("confidence");
|
|
|
- JSONObject thresholdsJsonObject = facePPResult.getJSONObject("thresholds");
|
|
|
- double le4 = thresholdsJsonObject.getDouble("1e-4");
|
|
|
- JSONArray face2Array = facePPResult.getJSONArray("faces2");
|
|
|
- compareFaceSyncInfo.setIsStranger(face2Array.length() > 1);//是否有陌生人
|
|
|
- compareFaceSyncInfo.setIsPass(confidence >= le4);//是否通过
|
|
|
- compareFaceSyncInfo.setErrorMsg(confidence >= le4 ? null : "confidence<le4");
|
|
|
- } else {
|
|
|
- compareFaceSyncInfo.setIsPass(false);
|
|
|
- compareFaceSyncInfo.setErrorMsg(facePPResult.toString());
|
|
|
- }
|
|
|
}
|
|
|
- } catch (JSONException e) {
|
|
|
- e.printStackTrace();
|
|
|
- throw new StatusException("JsonFormat002", "同步比较人脸失败");
|
|
|
}
|
|
|
|
|
|
return compareFaceSyncInfo;
|
|
@@ -435,7 +426,7 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
|
|
|
* @return
|
|
|
* @throws JSONException
|
|
|
*/
|
|
|
- private boolean calculateFaceCompareIsStranger(Long examRecordDataId, JSONObject jsonObject) throws JSONException {
|
|
|
+ private boolean calculateFaceCompareIsStranger(Long examRecordDataId, JSONObject jsonObject) {
|
|
|
JSONArray face2Array = jsonObject.getJSONArray("faces2");
|
|
|
//添加是否有陌生人开关功能
|
|
|
ExamRecordPropertyCacheBean examRecordPropertyCache = CacheHelper.getExamRecordProperty(examRecordDataId);
|
|
@@ -443,12 +434,12 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
|
|
|
String isStrangerEnableStr = "true";
|
|
|
if (examRecordPropertyCache != null) {
|
|
|
isStrangerEnableStr = CacheHelper.getExamOrgProperty(examRecordPropertyCache.getExamId(),
|
|
|
- examRecordPropertyCache.getOrgId(),ExamProperties.IS_STRANGER_ENABLE.name()).getValue();
|
|
|
+ examRecordPropertyCache.getOrgId(), ExamProperties.IS_STRANGER_ENABLE.name()).getValue();
|
|
|
}
|
|
|
boolean isStranger;
|
|
|
// 如果开启了陌生人检测才记录陌生人数据,否则认为没有陌生人
|
|
|
if (Constants.isTrue.equals(isStrangerEnableStr)) {
|
|
|
- isStranger = face2Array.length() > 1;//是否有陌生人
|
|
|
+ isStranger = face2Array.size() > 1;//是否有陌生人
|
|
|
} else {
|
|
|
isStranger = false;
|
|
|
}
|
|
@@ -462,7 +453,7 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
|
|
|
* @return
|
|
|
* @throws JSONException
|
|
|
*/
|
|
|
- private boolean calculateFaceCompareIsPass(JSONObject jsonObject) throws JSONException {
|
|
|
+ private boolean calculateFaceCompareIsPass(JSONObject jsonObject) {
|
|
|
//比对结果置信度,范围 [0,100],小数点后3位有效数字,数字越大表示两个人脸越可能是同一个人。
|
|
|
double confidence = jsonObject.getDouble("confidence");
|
|
|
//一组用于参考的置信度阈值,包含以下三个字段。每个字段的值为一个 [0,100] 的浮点数,小数点后 3 位有效数字。
|