package com.whyc.util;
|
|
import com.arcsoft.face.*;
|
import com.arcsoft.face.enums.DetectMode;
|
import com.arcsoft.face.enums.DetectOrient;
|
import com.arcsoft.face.enums.ErrorInfo;
|
import com.arcsoft.face.toolkit.ImageInfo;
|
import com.whyc.constant.YamlProperties;
|
import com.whyc.dto.Response;
|
|
import java.io.File;
|
import java.util.ArrayList;
|
import java.util.List;
|
|
/**
|
* @Description : 虹软人脸识别工具类
|
* @date 2020/10/28
|
**/
|
public class FaceIdentifyUtil {
|
|
//外网激活
|
public static boolean activeOnline(){
|
boolean res = false;
|
|
String appId="";
|
String sdkKey="";
|
FaceEngine faceEngine =null;
|
|
/*//从官网我的应用中获取
|
String appId4Win = "AafPX5afzycEnTqH3v79gY3VozNVTSNqT8kzSmP7b48q";
|
String sdkKey4Win = "GsYwWhxzuQEE1WE34J3Fo8d2QppjkqYGojyc4625JhKb";
|
|
//Linux系统appId和sdkKey及文件加载
|
String appId4Linux ="AafPX5afzycEnTqH3v79gY3VozNVTSNqT8kzSmP7b48q";
|
String sdkKey4Linux ="GsYwWhxzuQEE1WE34J3Fo8d2GiFdddqH81ghetQQTGmv";*/
|
//从官网我的应用中获取
|
String appId4Win = YamlProperties.appId4Win;
|
String sdkKey4Win = YamlProperties.sdkKey4Win;
|
|
//Linux系统appId和sdkKey及文件加载
|
String appId4Linux =YamlProperties.appId4Linux;
|
String sdkKey4Linux =YamlProperties.sdkKey4Linux;
|
|
//String realPath = ActionUtil.getApplication().getRealPath("/");
|
String realPath = CommonUtil.classesPath();
|
System.out.println("========realPath=========:"+realPath);
|
System.out.println("========faceEngine dll 路径=========:"+realPath+ File.separator+"lib"+File.separator+"WIN64");
|
//判断是什么系统
|
if(System.getProperty("os.name").toLowerCase().contains("window")){
|
appId=appId4Win;
|
sdkKey=sdkKey4Win;
|
faceEngine = new FaceEngine(realPath+ File.separator+"lib"+File.separator+"WIN64");
|
|
|
}else{
|
appId=appId4Linux;
|
sdkKey=sdkKey4Linux;
|
faceEngine = new FaceEngine(realPath+ File.separator+"WEB-INF"+File.separator+"lib"+File.separator+"LINUX64");
|
}
|
//激活引擎,只需一次就行,后续无需再激活
|
int errorCode = faceEngine.activeOnline(appId, sdkKey);
|
if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
|
//激活失败
|
}else{
|
res=true;
|
|
}
|
return res;
|
}
|
|
/**初始化*/
|
public static FaceEngine init(){
|
FaceEngine faceEngine=null;
|
String realPath = CommonUtil.classesPath();
|
if(System.getProperty("os.name").toLowerCase().contains("window")) {
|
faceEngine = new FaceEngine(realPath + File.separator + "lib" + File.separator + "WIN64");
|
}else{
|
faceEngine = new FaceEngine(realPath + File.separator + "lib" + File.separator + "LINUX64");
|
}
|
//引擎配置
|
EngineConfiguration engineConfiguration = new EngineConfiguration();
|
engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
|
//对特定场景推荐单一角度而非全角度,那样精度更高
|
engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
|
//最多支持的人脸数量
|
// engineConfiguration.setDetectFaceMaxNum(10);
|
engineConfiguration.setDetectFaceMaxNum(1);
|
engineConfiguration.setDetectFaceScaleVal(16);
|
//功能配置
|
FunctionConfiguration functionConfiguration = new FunctionConfiguration();
|
// functionConfiguration.setSupportAge(true);
|
functionConfiguration.setSupportFace3dAngle(true);
|
functionConfiguration.setSupportFaceDetect(true);
|
functionConfiguration.setSupportFaceRecognition(true);
|
// functionConfiguration.setSupportGender(true);
|
functionConfiguration.setSupportLiveness(true);
|
// functionConfiguration.setSupportIRLiveness(true);
|
engineConfiguration.setFunctionConfiguration(functionConfiguration);
|
|
|
//初始化引擎
|
int errorCode = faceEngine.init(engineConfiguration);
|
|
if (errorCode != ErrorInfo.MOK.getValue()) {
|
System.out.println("初始化引擎失败");
|
return null;
|
}
|
System.out.println("初始化faceEngine引擎成功");
|
return faceEngine;
|
|
}
|
|
public static Response orientAndPxDetect(FaceEngine faceEngine, ImageInfo imageInfo) {
|
//检查角度是否端正,检查人脸像素大小是否>50×50
|
List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
|
faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
|
if (faceInfoList.size()<1){
|
return new Response().set(1,false,"无效的人脸信息");
|
}else {
|
FaceInfo faceInfo = faceInfoList.get(0);
|
Rect rect = faceInfo.getRect();
|
if (faceInfo.getOrient() != 1) {
|
return new Response().set(1,false,"人像姿势不端正");
|
} else if ((rect.bottom - rect.top) < 50 || (rect.right - rect.left) < 50) {
|
return new Response().set(1,false,"人像面部像素太低");
|
}
|
}
|
return new Response().set(1,true,"校验通过");
|
}
|
|
public static Response liveDetect(FaceEngine faceEngine, ImageInfo imageInfo) {
|
Response res = new Response();
|
|
int errorCode=0;
|
List<FaceInfo> faceInfoList = new ArrayList<>();
|
List<LivenessInfo> livenessInfoList = new ArrayList<>();
|
|
errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
|
|
//设置活体测试
|
//活体取值范围为[0~1],推荐阈值如下,高于此阈值的即可判断为活体。
|
// RGB 活体:0.5
|
// IR 活体:0.7
|
errorCode = faceEngine.setLivenessParam(0.5f, 0.7f);
|
//人脸属性检测
|
FunctionConfiguration configuration = new FunctionConfiguration();
|
// configuration.setSupportAge(true);
|
configuration.setSupportFace3dAngle(true);
|
// configuration.setSupportGender(true);
|
configuration.setSupportLiveness(true);
|
errorCode = faceEngine.process(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList, configuration);
|
|
faceEngine.getLiveness(livenessInfoList);
|
if(livenessInfoList.size()<1 || livenessInfoList.get(0).getLiveness()!=1){
|
res.setCode(0);
|
res.setMsg("无效的脸部信息");
|
}else{
|
res.setCode(1);
|
}
|
return res;
|
}
|
|
public static Response faceCompare(FaceEngine faceEngine, ImageInfo imageInfo, ImageInfo imageInfo2) {
|
Response res = new Response();
|
int errorCode=0;
|
//人脸检测
|
List<FaceInfo> faceInfoList = new ArrayList<>();
|
errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
|
|
//特征提取
|
FaceFeature faceFeature = new FaceFeature();
|
errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature);
|
|
//人脸检测2
|
List<FaceInfo> faceInfoList2 = new ArrayList<>();
|
errorCode = faceEngine.detectFaces(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(),imageInfo2.getImageFormat(), faceInfoList2);
|
|
//特征提取2
|
FaceFeature faceFeature2 = new FaceFeature();
|
errorCode = faceEngine.extractFaceFeature(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(), imageInfo2.getImageFormat(), faceInfoList2.get(0), faceFeature2);
|
|
//特征比对
|
FaceFeature targetFaceFeature = new FaceFeature();
|
targetFaceFeature.setFeatureData(faceFeature.getFeatureData());
|
FaceFeature sourceFaceFeature = new FaceFeature();
|
sourceFaceFeature.setFeatureData(faceFeature2.getFeatureData());
|
FaceSimilar faceSimilar = new FaceSimilar();
|
|
errorCode = faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar);
|
|
//官方建议:
|
//人脸比对取值范围为[0~1],推荐阈值如下,高于此阈值的即可判断为同一人。
|
// 用于生活照之间的特征比对,推荐阈值0.80
|
// 用于证件照或生活照与证件照之间的特征比对,推荐阈值0.82
|
float faceThreshold = YamlProperties.faceThreshold;
|
if(faceSimilar.getScore()<faceThreshold){
|
res.setCode(0);
|
res.setMsg("人脸不匹配");
|
}else{
|
res.setCode(1);
|
res.setMsg("匹配成功");
|
}
|
return res;
|
}
|
}
|