Java 虹软人脸本地识别
开发语言:Java
虹软SDK版本:2.1
添加SDK
虹软官网:https://ai.arcsoft.com.cn/product/liveness_detection.html?utm_source=baidu3a4&utm_medium=cpc
从官网进入,添加SDK,并且下载。
在此,以windows版本为例,把libs/WIN64下的.dll
文件放到java.library.path
所包含的目录下.
例如 windows 可以放到 C:\Windows\System32
linux 可以放到usr/lib64
下
具体路径可以通过 System.getProperty("java.library.path");
查看
这一步是必须要做的,否则就会如下错误
Exception in thread “main” java.lang.UnsatisfiedLinkError: no libarcsoft_face_engine_jni in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
at java.lang.Runtime.loadLibrary0(Runtime.java:870)
at java.lang.System.loadLibrary(System.java:1122)
at com.arcsoft.face.FaceEngine.(FaceEngine.java:19)
at com.test.FaceEngineTest.faceEngineTest(FaceEngineTest.java:26)
at com.test.FaceEngineTest.main(FaceEngineTest.java:18)
把dll文件放到特定目录
当然有的时候不想或者不能放到usr/lib64 下的时候也可以放到项目路径下例如 src/lib
下,然后通过一下代码加载类库
String path = "D:\\webapp\\hongruan\\src\\lib\\";
this.addDirToPath(path);
System.load(path+"libarcsoft_face.dll");
System.load(path+"libarcsoft_face_engine.dll");
System.load(path+"libarcsoft_face_engine_jni.dll");
private void addDirToPath(String s) throws NoSuchFieldException {
try {
//获取系统path变量对象
java.lang.reflect.Field field = ClassLoader.class.getDeclaredField("sys_paths");
//设置此变量对象可访问
field.setAccessible(true);
//获取此变量对象的值
String[] path = (String[]) field.get(null);
//是否已经存在 for(int i=0;i<path.length;i++) {
if (s.equals(path)) {
field.setAccessible(false);
return;
}
//创建字符串数组,在原来的数组长度上增加一个,用于存放增加的目录
String[] tem = new String[path.length + 1];
//将原来的path变量复制到tem中
System.arraycopy(path, 0, tem, 0, path.length);
//将增加的目录存入新的变量数组中
tem[path.length] = s;
//将增加目录后的数组赋给path变量对象
field.set(null, tem);
} catch (Exception e) {
e.printStackTrace();
}
}
代码解析
SDK压缩文件中doc目录下会有一个pdf文件,解析主要代码
public void faceEngineTest() {
// 这里填写添加SDK的激活码
// APP_ID
String appId = " ";
//SDK_KEY
String sdkKey = " ";
FaceEngine faceEngine = new FaceEngine();
//激活引擎
faceEngine.active(appId, sdkKey);
EngineConfiguration engineConfiguration = EngineConfiguration.builder().functionConfiguration(
FunctionConfiguration.builder()
// 这里按照自己的需要添加
.supportAge(true)
.supportFace3dAngle(true)
.supportFaceDetect(true)
.supportFaceRecognition(true)
.supportGender(true)
.supportLiveness(true)
.build()).build();
//初始化引擎
faceEngine.init(engineConfiguration);
// 以上是初始化步骤,不需要修改
// 这里添加两个图片进行对比
ImageInfo imageInfo = getRGBData(new File("C:\\Users\\Administrator\\Desktop\\sad\\1.jpg"));
ImageInfo imageInfo2 = getRGBData(new File("C:\\Users\\Administrator\\Desktop\\sad\\22.jpg"));
//人脸检测
List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
faceEngine.detectFaces(imageInfo.getRgbData(), imageInfo.getWidth(), imageInfo.getHeight(), ImageFormat.CP_PAF_BGR24, faceInfoList);
//提取人脸特征
FaceFeature faceFeature = new FaceFeature();
faceEngine.extractFaceFeature(imageInfo.getRgbData(), imageInfo.getWidth(), imageInfo.getHeight(), ImageFormat.CP_PAF_BGR24, faceInfoList.get(0), faceFeature);
// 二进制文件保存 faceFeature2.featureData() 是特征文件, 然后通过特征文件进行对比
FaceFeature faceFeature2 = new FaceFeature();
faceEngine.extractFaceFeature(imageInfo2.getRgbData(), imageInfo2.getWidth(), imageInfo2.getHeight(), ImageFormat.CP_PAF_BGR24, faceInfoList.get(0), faceFeature2);
//人脸对比
FaceFeature targetFaceFeature = new FaceFeature();
targetFaceFeature.setFeatureData(faceFeature.getFeatureData());
FaceFeature sourceFaceFeature = new FaceFeature();
sourceFaceFeature.setFeatureData(faceFeature2.getFeatureData());
FaceSimilar faceSimilar = new FaceSimilar();
faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar);
// 打印对比分数
System.out.println(faceSimilar.getScore());
int processResult = faceEngine.process(imageInfo.getRgbData(), imageInfo.getWidth(), imageInfo.getHeight(), ImageFormat.CP_PAF_BGR24, faceInfoList, FunctionConfiguration.builder().supportAge(true).supportFace3dAngle(true).supportGender(true).supportLiveness(true).build());
//性别提取
List<GenderInfo> genderInfoList = new ArrayList<GenderInfo>();
int genderCode = faceEngine.getGender(genderInfoList);
//年龄提取
List<AgeInfo> ageInfoList = new ArrayList<AgeInfo>();
int ageCode = faceEngine.getAge(ageInfoList);
//3D信息提取
List<Face3DAngle> face3DAngleList = new ArrayList<Face3DAngle>();
int face3dCode = faceEngine.getFace3DAngle(face3DAngleList);
//活体信息
List<LivenessInfo> livenessInfoList = new ArrayList<LivenessInfo>();
int livenessCode = faceEngine.getLiveness(livenessInfoList);
System.out.println(livenessCode);
}
这是pdf 中的主要代码了,刚开始看到这里很是疑惑,SDK中只提供了1:1的比对,然后1:n该怎么操作?
这里告诉大家怎么1:n
这块特别坑,在以上代码中 有一个faceFeature2.featureData()
这个是二进制的特征文件,虹软2.1版本只有1K大小,我们可以把每一个人脸的二进制文件保存到缓存,或者数据库,或者文件夹中,这些二进制文件的集合就可以称为人脸库,等需要人脸人脸识别操作的时候例如:人脸解锁等操作的时候,进行for循环比对,比对分值达到一定的分数(例如:0.8分)的时候则可以认为找到对应的人脸数据。
最后如何提升比对的效率就要考验大家的代码优化能力了…
代码不知道怎么写的, 大家可以借鉴这里https://ai.arcsoft.com.cn/bbs/forum.php?mod=viewthread&tid=1483&extra=page%3D1
它的代码写了多线程比对的例子
备注下遇到的两个错误
Exception in thread “main” java.lang.IllegalArgumentException: MERR_ASF_DEVICE_MISMATCH
at com.arcsoft.face.FaceEngine.active(FaceEngine.java:125)
at com.test.Test.asd(Test.java:32)
at com.test.Test.main(Test.java:18)
解决方法:执行成功会生成一个激活文件(asf_install.dat),一个激活文件对应一台设备。如果后面更换了appId和key,一定要删除了激活文件(可能是隐藏文件)
解决地址:https://www.cnblogs.com/KEAIILINN/p/10571244.html
Exception in thread “main” java.lang.IllegalArgumentException: init fail:MERR_ASF_EX_FEATURE_UNSUPPORTED_ON_INIT
at com.arcsoft.face.FaceEngine.init(FaceEngine.java:182)
at com.test.Test.asd(Test.java:43)
at com.test.Test.main(Test.java:18)
本人的解决方法: dll或者so 文件最好放到项目路径下 例如 src/lib 下
希望对大家有用!