|
@@ -1,14 +1,19 @@
|
|
|
package cn.com.qmth.examcloud.starters.face.verify.service.impl;
|
|
|
|
|
|
import cn.com.qmth.examcloud.starters.face.verify.FaceVerifyProperties;
|
|
|
-import cn.com.qmth.examcloud.starters.face.verify.common.IResult;
|
|
|
+import cn.com.qmth.examcloud.starters.face.verify.common.FaceResult;
|
|
|
+import cn.com.qmth.examcloud.starters.face.verify.common.JsonHelper;
|
|
|
import cn.com.qmth.examcloud.starters.face.verify.service.FaceVerifyService;
|
|
|
-import cn.com.qmth.examcloud.starters.face.verify.service.baidu.BaiduApiHelper;
|
|
|
-import cn.com.qmth.examcloud.starters.face.verify.service.baidu.BaiduSession;
|
|
|
+import cn.com.qmth.examcloud.starters.face.verify.service.baidu.*;
|
|
|
import cn.com.qmth.examcloud.starters.face.verify.service.faceplus.FacePlusApiHelper;
|
|
|
+import cn.com.qmth.examcloud.starters.face.verify.service.faceplus.FacePlusResponse;
|
|
|
+import cn.com.qmth.examcloud.starters.face.verify.service.faceplus.FacePlusThresholds;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
public class FaceVerifyServiceImpl implements FaceVerifyService {
|
|
|
|
|
|
private final static Logger log = LoggerFactory.getLogger(FaceVerifyServiceImpl.class);
|
|
@@ -16,35 +21,150 @@ public class FaceVerifyServiceImpl implements FaceVerifyService {
|
|
|
private FaceVerifyProperties properties;
|
|
|
|
|
|
@Override
|
|
|
- public IResult faceDetectByBaidu(String imageUrl) {
|
|
|
+ public FaceResult faceDetectByBaidu(String imageUrl) {
|
|
|
String accessToken = null;
|
|
|
if (properties.getBaiduAccessTokenEnabled()) {
|
|
|
BaiduSession session = BaiduApiHelper.getAccessToken(properties.getBaiduKey(), properties.getBaiduSecret(), properties.getBaiduTokenUrl());
|
|
|
accessToken = session.getAccess_token();
|
|
|
}
|
|
|
|
|
|
- return BaiduApiHelper.faceDetect(accessToken, properties.getBaiduFaceDetectUrl(), imageUrl);
|
|
|
+ BaiduResponse response = BaiduApiHelper.faceDetect(accessToken, properties.getBaiduFaceDetectUrl(), imageUrl);
|
|
|
+
|
|
|
+ FaceResult result = new FaceResult();
|
|
|
+ result.setPass(false);
|
|
|
+ result.setApiLimit(false);
|
|
|
+
|
|
|
+ if (response.getError_code() != 0) {
|
|
|
+ result.setError(response.getError_code() + " - " + response.getError_msg());
|
|
|
+
|
|
|
+ // 请求并发超限(约10个/秒)
|
|
|
+ if (response.getError_code() == 18) {
|
|
|
+ result.setApiLimit(true);
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ BaiduResult data = response.getResult();
|
|
|
+ if (data != null) {
|
|
|
+ double faceLiveness = data.getFace_liveness() != null ? data.getFace_liveness() : 0d;
|
|
|
+
|
|
|
+ result.setScore(faceLiveness);
|
|
|
+ result.setThresholds(new JsonHelper().toJson(data.getThresholds()));
|
|
|
+
|
|
|
+ if (data.getFace_num() != null) {
|
|
|
+ result.setFaceNum(data.getFace_num());
|
|
|
+ } else {
|
|
|
+ List<BaiduFace> faces = data.getFace_list();
|
|
|
+ result.setFaceNum(faces != null ? faces.size() : 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 活体分数值,推荐阈值0.393241
|
|
|
+ if (faceLiveness >= 0.39d) {
|
|
|
+ result.setPass(true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public IResult faceCompareByBaidu(String imageUrl, String imageUrl2) {
|
|
|
+ public FaceResult faceCompareByBaidu(String imageUrl, String imageUrl2) {
|
|
|
String accessToken = null;
|
|
|
if (properties.getBaiduAccessTokenEnabled()) {
|
|
|
BaiduSession session = BaiduApiHelper.getAccessToken(properties.getBaiduKey(), properties.getBaiduSecret(), properties.getBaiduTokenUrl());
|
|
|
accessToken = session.getAccess_token();
|
|
|
}
|
|
|
|
|
|
- return BaiduApiHelper.faceCompare(accessToken, properties.getBaiduFaceCompareUrl(), imageUrl, imageUrl2);
|
|
|
+ BaiduResponse response = BaiduApiHelper.faceCompare(accessToken, properties.getBaiduFaceCompareUrl(), imageUrl, imageUrl2);
|
|
|
+
|
|
|
+ FaceResult result = new FaceResult();
|
|
|
+ result.setPass(false);
|
|
|
+ result.setApiLimit(false);
|
|
|
+
|
|
|
+ if (response.getError_code() != 0) {
|
|
|
+ result.setError(response.getError_code() + " - " + response.getError_msg());
|
|
|
+
|
|
|
+ // 请求并发超限(约10个/秒)
|
|
|
+ if (response.getError_code() == 18) {
|
|
|
+ result.setApiLimit(true);
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ BaiduResult data = response.getResult();
|
|
|
+ if (data != null) {
|
|
|
+ result.setScore(data.getScore());
|
|
|
+
|
|
|
+ // 人脸相似度得分,推荐阈值80分
|
|
|
+ if (data.getScore() != null && data.getScore() >= 80d) {
|
|
|
+ result.setPass(true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public IResult faceDetectByFacePlus(String imageUrl) {
|
|
|
- return FacePlusApiHelper.faceDetect(properties.getFacePlusKey(), properties.getFacePlusSecret(), properties.getFacePlusFaceDetectUrl(), imageUrl);
|
|
|
+ public FaceResult faceDetectByFacePlus(String imageUrl) {
|
|
|
+ FacePlusResponse response = FacePlusApiHelper.faceDetect(properties.getFacePlusKey(), properties.getFacePlusSecret(), properties.getFacePlusFaceDetectUrl(), imageUrl);
|
|
|
+
|
|
|
+ FaceResult result = new FaceResult();
|
|
|
+ result.setPass(false);
|
|
|
+ result.setApiLimit(false);
|
|
|
+
|
|
|
+ if (StringUtils.isNotEmpty(response.getError_message())) {
|
|
|
+ result.setError(response.getError_message());
|
|
|
+
|
|
|
+ // 请求并发是否超限(约20个/秒)
|
|
|
+ if ("CONCURRENCY_LIMIT_EXCEEDED".equals(response.getError_message())) {
|
|
|
+ result.setApiLimit(true);
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ int faceNum = response.getFace_num() != null ? response.getFace_num() : 0;
|
|
|
+ result.setFaceNum(faceNum);
|
|
|
+
|
|
|
+ if (faceNum == 1) {
|
|
|
+ // 是否人脸检测通过 (只有一张人脸算成功,否则算失败)
|
|
|
+ result.setPass(true);
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public IResult faceCompareByFacePlus(String imageUrl, String imageUrl2) {
|
|
|
- return FacePlusApiHelper.faceCompare(properties.getFacePlusKey(), properties.getFacePlusSecret(), properties.getFacePlusFaceCompareUrl(), imageUrl, imageUrl2);
|
|
|
+ public FaceResult faceCompareByFacePlus(String imageUrl, String imageUrl2) {
|
|
|
+ FacePlusResponse response = FacePlusApiHelper.faceCompare(properties.getFacePlusKey(), properties.getFacePlusSecret(), properties.getFacePlusFaceCompareUrl(), imageUrl, imageUrl2);
|
|
|
+
|
|
|
+ FaceResult result = new FaceResult();
|
|
|
+ result.setPass(false);
|
|
|
+ result.setApiLimit(false);
|
|
|
+
|
|
|
+ if (StringUtils.isNotEmpty(response.getError_message())) {
|
|
|
+ result.setError(response.getError_message());
|
|
|
+
|
|
|
+ // 请求并发是否超限(约20个/秒)
|
|
|
+ if ("CONCURRENCY_LIMIT_EXCEEDED".equals(response.getError_message())) {
|
|
|
+ result.setApiLimit(true);
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ FacePlusThresholds thresholds = response.getThresholds();
|
|
|
+ if (thresholds != null) {
|
|
|
+ float confidence = response.getConfidence() != null ? response.getConfidence() : 0f;
|
|
|
+
|
|
|
+ result.setScore((double) confidence);
|
|
|
+ result.setThresholds(new JsonHelper().toJson(thresholds));
|
|
|
+
|
|
|
+ // 是否人脸对比通过
|
|
|
+ if (confidence >= thresholds.getLe_4()) {
|
|
|
+ result.setPass(true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
public void setProperties(FaceVerifyProperties properties) {
|