基于虹软人脸识别SDK的Java项目集成指南
虹软人脸识别SDK是一款功能全面且成熟的解决方案,广泛应用于智能设备、人脸识别门禁、身份验证等领域。集成虹软人脸识别SDK到Java项目中,可以实现高效的人脸检测、特征提取和比对功能,使得Java开发者能够在各类应用场景中快速部署人脸识别技术。
技术实现概述:
首先,开发者需要下载虹软人脸识别SDK并在Java项目中进行依赖配置。由于虹软的核心库是基于C/C++编写的,需要通过JNI(Java Native Interface)与Java进行交互。这意味着需要确保本地库(如DLL或SO文件)能够在Java环境中正确加载。开发者可以利用System.loadLibrary()方法动态加载本地库,并确保相关依赖路径的正确配置。
在SDK的API设计中,提供了多种用于人脸检测和特征比对的接口。例如,可以通过FaceEngine类初始化引擎,加载人脸检测、年龄预测、性别识别等多种模块。为了提高性能,开发者可以根据实际需求设置不同的检测模式,如仅检测人脸框或同时进行多模态特征分析。SDK还支持在多线程环境下运行,能够有效提升实时检测和并发处理的性能。
关键技术点:
1. 模型加载与初始化: 在初始化过程中,需要加载多个模型文件(如人脸检测、特征点检测等)。开发者需要确保模型文件路径正确,并为不同功能模块分配足够的内存资源。通常情况下,初始化时需要指定检测器的工作模式,如图像模式或视频模式。
2. 人脸特征提取: 虹软SDK提供了高精度的人脸特征提取算法,能够在极短时间内提取128维或256维的特征向量。开发者可以利用这些特征向量与数据库中的人脸信息进行高效比对,完成身份验证等任务。
3. 错误处理与性能优化: 开发者需要为可能出现的异常情况(如初始化失败、图像数据错误等)设置合适的错误处理机制。此外,在处理大量图像或实时视频流时,合理使用多线程和并发技术能够有效降低延迟,提升识别效率。
通过集成虹软人脸识别SDK,Java开发者能够快速实现复杂的人脸识别功能,并能够根据项目需求进行定制化开发,满足不同场景下的识别精度与性能要求。
1. 注册开发者账号并下载SDK
首先,登录虹软视觉开放平台,进入开发者中心并下载SDK。下载地址是:https://ai.arcsoft.com.cn/ucenter/resource/build/index.html
下载的SDK文件与您的APP_ID和SDK_KEY绑定,解压后可以找到libs
文件夹,里面包含必要的库文件。
2. 集成jar包至本地服务
解压SDK后,可以看到一个名为arcsoft-sdk-face-3.0.0.0.jar的Jar文件。根据操作系统的不同,需要使用相应的引擎文件:
Linux系统:需要.so引擎文件
Windows系统:需要.dll引擎文件
将这些文件放置到项目的合适目录中(例如src/main/resources/lib/arcsoft/)。
3. 集成jar包至Maven
由于该Jar包没有在远程仓库中发布,需要使用mvn命令将本地的JAR文件安装到本地Maven仓库中。
运行以下命令将Jar包安装到本地Maven仓库:
mvn install:install-file -Dfile=src/main/resources/lib/arcsoft/arcsoft-sdk-face-3.0.0.0.jar -DgroupId=com.arcsoft -DartifactId=json -Dversion=1.0 -Dpackaging=jar
然后,在pom.xml文件中添加以下依赖:
<dependency>
<groupId>com.arcsoft</groupId>
<artifactId>json</artifactId>
<version>1.0</version>
</dependency>
4. 在项目中初始化引擎
在项目中创建一个Bean初始化引擎,配置EngineConfiguration(引擎配置类)和FunctionConfiguration(功能配置类)。
以下是初始化引擎的代码示例:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
public class DllLoaderUtil {
public static void loadDllFromResource(String resourcePath, String dllName, String dllSuffix) {
try {
// 检查库文件是否已经加载
String tempDir = System.getProperty("java.io.tmpdir");
File tempDll = new File(tempDir, dllName + dllSuffix);
if (!tempDll.exists()) {
// 提取DLL到临时文件
extractDllFromResource(resourcePath, tempDll);
}
// 加载 DLL
System.load(tempDll.getAbsolutePath());
} catch (Exception e) {
throw new RuntimeException("Failed to load DLL from resource", e);
}
}
private static void extractDllFromResource(String resourcePath, File tempDll) throws IOException {
URL dllUrl = DllLoaderUtil.class.getClassLoader().getResource(resourcePath);
if (dllUrl == null) {
throw new IllegalStateException("DLL resource not found: " + resourcePath);
}
try (InputStream in = dllUrl.openStream();
FileOutputStream out = new FileOutputStream(tempDll)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
}
tempDll.deleteOnExit();
}
}
import cn.hutool.core.img.Img;
import cn.hutool.core.io.FileUtil;
import java.io.ByteArrayOutputStream;
import java.net.URL;
public class FcFileKit {
/**
* 本地文件path转化为二进制文件
*
* @param imagePath 本地文件path
* @return 二进制文件
*/
public static byte[] imagePathToBytes(String imagePath) {
try {
return FileUtil.readBytes(imagePath);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 远程文件Url转化为二进制文件
*
* @param imageUrl 文件Url
* @return 二进制文件
*/
public static byte[] imageUrlToBytes(String imageUrl) {
try {
URL url = new URL(imageUrl);
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
Img.from(url).write(outputStream); // 写文件
return outputStream.toByteArray();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}catch (Exception e){
e.printStackTrace();
return null;
}
}
}
import com.arcsoft.face.ActiveFileInfo;
import com.arcsoft.face.EngineConfiguration;
import com.arcsoft.face.FaceEngine;
import com.arcsoft.face.FunctionConfiguration;
import com.arcsoft.face.enums.DetectMode;
import com.arcsoft.face.enums.DetectOrient;
import com.arcsoft.face.enums.ErrorInfo;
import com.njmh.authority.utils.DllLoaderUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
@Component
@RequiredArgsConstructor
public class FaceEngineFactory {
private static final String FACE_ENGINE_KEY = "face_engine_key";
private static final String FUNCTION_CONFIGURATION_KEY = "function_configuration_key";
private ConcurrentHashMap<String, FaceEngine> faceEngineMap = new ConcurrentHashMap<>(); // 引擎Bean
private ConcurrentHashMap<String, FunctionConfiguration> functionConfigurationMap = new ConcurrentHashMap<>(); // 引擎配置
private final FaceEngineProperties faceEngineProperties;
@PostConstruct
public void init() {
log.info("进入人脸引擎初始化");
String tempDir = System.getProperty("java.io.tmpdir");
String osName = System.getProperty("os.name").toLowerCase();
if (osName.contains("win")) {
DllLoaderUtil.loadDllFromResource("lib/arcsoft/WIN64/libarcsoft_face.dll", "libarcsoft_face", ".dll");
DllLoaderUtil.loadDllFromResource("lib/arcsoft/WIN64/libarcsoft_face_engine.dll", "libarcsoft_face_engine", ".dll");
DllLoaderUtil.loadDllFromResource("lib/arcsoft/WIN64/libarcsoft_face_engine_jni.dll", "libarcsoft_face_engine_jni", ".dll");
} else if (osName.contains("nix") || osName.contains("nux") || osName.contains("mac")) {
DllLoaderUtil.loadDllFromResource("lib/arcsoft/WIN64/libarcsoft_face.so", "libarcsoft_face", ".so");
DllLoaderUtil.loadDllFromResource("lib/arcsoft/WIN64/libarcsoft_face_engine.so", "libarcsoft_face_engine", ".so");
DllLoaderUtil.loadDllFromResource("lib/arcsoft/WIN64/libarcsoft_face_engine_jni.so", "libarcsoft_face_engine_jni", ".so");
} else {
throw new UnsupportedOperationException("Unsupported operating system: " + osName);
}
FaceEngine faceEngine = new FaceEngine(tempDir);
int errorCode = faceEngine.activeOnline(faceEngineProperties.getAppId(), faceEngineProperties.getSdkKey());
if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
log.error("人脸引擎激活失败");
return;
}
ActiveFileInfo activeFileInfo = new ActiveFileInfo();
errorCode = faceEngine.getActiveFileInfo(activeFileInfo);
if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
log.error("获取激活文件信息失败");
return;
}
EngineConfiguration engineConfiguration = new EngineConfiguration();
engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
engineConfiguration.setDetectFaceMaxNum(10);
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);
errorCode = faceEngine.init(engineConfiguration);
if (errorCode != ErrorInfo.MOK.getValue()) {
log.error("初始化人脸引擎失败");
return;
}
faceEngineMap.put(FACE_ENGINE_KEY, faceEngine);
functionConfigurationMap.put(FUNCTION_CONFIGURATION_KEY, functionConfiguration);
log.info("人脸引擎初始化完成");
}
/**
* 工厂方法
*
* @return 人脸引擎
*/
public FaceEngine getFaceEngine() {
return faceEngineMap.get(FACE_ENGINE_KEY);
}
/**
* 工厂方法
*
* @return 引擎配置
*/
public FunctionConfiguration getFunctionConfiguration() {
return functionConfigurationMap.get(FUNCTION_CONFIGURATION_KEY);
}
}
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* 人脸认证引擎配置
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "face-engine")
public class FaceEngineProperties {
/**
* appId
*/
private String appId;
/**
* sdkKey
*/
private String sdkKey;
/**
* 人脸对比阀值
*/
private Float faceSimilarScore;
/**
* RGB活体检测阀值
*/
private Float rgbThreshold;
/**
* IR活体检测阀值
*/
private Float irThreshold;
}
import lombok.Data;
import java.io.Serializable;
@Data
public class FaceEngineR<T> implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 成功标记
*/
private static Integer SUCCESS = 0;
/**
* 失败标记
*/
private static Integer FAIL = 1;
/**
* 返回标记:成功标记=0,失败标记=1
*/
private int code;
/**
* 返回信息
*/
private String msg;
/**
* 数据
*/
private T data;
public static <T> FaceEngineR<T> ok() {
return restResult(null, SUCCESS, "成功");
}
public static <T> FaceEngineR<T> ok(T data) {
return restResult(data, SUCCESS, "成功");
}
public static <T> FaceEngineR<T> ok(T data, String msg) {
return restResult(data, SUCCESS, msg);
}
public static <T> FaceEngineR<T> failed() {
return restResult(null, FAIL, "失败");
}
public static <T> FaceEngineR<T> failed(String msg) {
return restResult(null, FAIL, msg);
}
public static <T> FaceEngineR<T> failed(T data) {
return restResult(data, FAIL, "失败");
}
public static <T> FaceEngineR<T> failed(T data, String msg) {
return restResult(data, FAIL, msg);
}
static <T> FaceEngineR<T> restResult(T data, int code, String msg) {
FaceEngineR<T> apiResult = new FaceEngineR<>();
apiResult.setCode(code);
apiResult.setData(data);
apiResult.setMsg(msg);
return apiResult;
}
}
5. 编写服务api
添加application.yml文件内容:
# 人脸认证引擎配置
face-engine:
# 应用id
app-id: 开发者中心的APP_ID
# sdk密匙
sdk-key: 开发者中心的SDK_KEY
# 人脸对比阀值(建议0.8)
face-similar-score: 0.8
# RGB活体检测阀值(建议0.5)
rgb-threshold: 0.5
# IR活体检测阀值(建议0.7)
ir-threshold: 0.7
创建一个API服务类,用于实现人脸检测和人脸比对功能。以下是API示例:
import com.njmh.common.arcsoft.FaceEngineProperties;
import com.njmh.common.arcsoft.FaceEngineR;
import com.njmh.common.core.excepotion.BusinessException;
import com.njmh.service.arcsoft.impl.FaceEngineServiceImpl;
import com.njmh.utils.FcFileKit;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.Optional;
/**
* 人脸认证api
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class FaceEngineApi {
private final FaceEngineServiceImpl faceEngineService;
private final FaceEngineProperties faceEngineProperties;
/**
* 本地人脸检测
*/
public boolean detectLocalFace(String imagePath) {
log.info("检测人脸:{}", imagePath);
// 将图片url转换为文件字节
byte[] authImageBytes = FcFileKit.imagePathToBytes(imagePath);
Optional.ofNullable(authImageBytes).orElseThrow(() -> new BusinessException("文件读取异常"));
// 人脸检测
FaceEngineR faceEngineR = faceEngineService.detectFace(authImageBytes);
if (faceEngineR.getCode() != 0) {
log.info("认证失败:[code] {} [msg] {}", faceEngineR.getCode(), faceEngineR.getMsg());
throw new BusinessException(faceEngineR.getMsg());
}
log.info("检测通过");
return true;
}
/**
* 人脸检测
*/
public boolean detectFace(String imageUrl) {
log.info("检测人脸:{}", imageUrl);
// 将图片url转换为文件字节
byte[] authImageBytes = FcFileKit.imageUrlToBytes(imageUrl);
Optional.ofNullable(authImageBytes).orElseThrow(() -> new BusinessException("文件读取异常"));
// 人脸检测
FaceEngineR faceEngineR = faceEngineService.detectFace(authImageBytes);
if (faceEngineR.getCode() != 0) {
log.info("认证失败:[code] {} [msg] {}", faceEngineR.getCode(), faceEngineR.getMsg());
throw new BusinessException(faceEngineR.getMsg());
}
log.info("检测通过");
return true;
}
/**
* 本地人脸对比认证
*
* @param authImagePath 待认证的人脸
* @param localImagePath 人脸库中的人脸
* @return 认证结果
*/
public boolean compareLocalFace(String authImagePath, String localImagePath) {
log.info("认证人脸:{}", authImagePath);
log.info("人脸库人脸:{}", localImagePath);
// 将图片path转换为文件字节
byte[] authImageBytes = FcFileKit.imagePathToBytes(authImagePath);
Optional.ofNullable(authImageBytes).orElseThrow(() -> new BusinessException("文件读取异常"));
byte[] localImageBytes = FcFileKit.imagePathToBytes(localImagePath);
Optional.ofNullable(localImageBytes).orElseThrow(() -> new BusinessException("人脸库文件读取异常"));
log.info("相识度阀值:{}", faceEngineProperties.getFaceSimilarScore());
log.info("RGB活体检测阀值:{}", faceEngineProperties.getRgbThreshold());
log.info("IR活体检测阀值:{}", faceEngineProperties.getIrThreshold());
FaceEngineR faceEngineR = faceEngineService.compareFace(authImageBytes, localImageBytes,
faceEngineProperties.getFaceSimilarScore(),
faceEngineProperties.getRgbThreshold(),
faceEngineProperties.getIrThreshold());
if (faceEngineR.getCode() != 0) {
log.info("认证失败:[code] {} [msg] {}", faceEngineR.getCode(), faceEngineR.getMsg());
throw new BusinessException(faceEngineR.getMsg());
}
log.info("认证通过");
return true;
}
/**
* 人脸对比认证
*
* @param authImageUrl 待认证的人脸
* @param localImageUrl 人脸库中的人脸
* @return 认证结果
*/
public boolean compareFace(String authImageUrl, String localImageUrl) {
log.info("认证人脸:{}", authImageUrl);
log.info("人脸库人脸:{}", localImageUrl);
// 将图片url转换为文件字节
byte[] authImageBytes = FcFileKit.imageUrlToBytes(authImageUrl);
Optional.ofNullable(authImageBytes).orElseThrow(() -> new BusinessException("文件读取异常"));
byte[] localImageBytes = FcFileKit.imageUrlToBytes(localImageUrl);
Optional.ofNullable(localImageBytes).orElseThrow(() -> new BusinessException("人脸库文件读取异常"));
log.info("相识度阀值:{}", faceEngineProperties.getFaceSimilarScore());
log.info("RGB活体检测阀值:{}", faceEngineProperties.getRgbThreshold());
log.info("IR活体检测阀值:{}", faceEngineProperties.getIrThreshold());
FaceEngineR faceEngineR = faceEngineService.compareFace(authImageBytes, localImageBytes,
faceEngineProperties.getFaceSimilarScore(),
faceEngineProperties.getRgbThreshold(),
faceEngineProperties.getIrThreshold());
if (faceEngineR.getCode() != 0) {
log.info("认证失败:[code] {} [msg] {}", faceEngineR.getCode(), faceEngineR.getMsg());
throw new BusinessException(faceEngineR.getMsg());
}
log.info("认证通过");
return true;
}
}
import com.arcsoft.face.*;
import com.arcsoft.face.enums.ErrorInfo;
import com.arcsoft.face.toolkit.ImageInfo;
import com.njmh.common.arcsoft.FaceEngineFactory;
import com.njmh.common.arcsoft.FaceEngineR;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import static com.arcsoft.face.toolkit.ImageFactory.getRGBData;
@Slf4j
@Component
@RequiredArgsConstructor
public class FaceEngineServiceImpl {
private final FaceEngineFactory faceEngineFactory;
/**
* 人脸认证
* <p>
* 建议待检测的图像人脸角度上、下、左、右转向小于30度;
* 图片中人脸尺寸不小于50 x 50像素;
* 图片大小小于10MB;
*
* @param authImageBytes 认证的图片字节
* @param localImageBytes 人脸库的图片字节
* @param faceSimilarScore 人脸对比阀值(范围为[0~1],生活照推荐:0.80,证件照推荐:0.82)
* @param rgbThreshold RGB活体检测阀值(范围为[0~1],推荐:0.5)
* @param irThreshold IR活体检测阀值 (范围为[0~1],推荐:0.7)
* @return 认证结果
*/
public FaceEngineR compareFace(byte[] authImageBytes, byte[] localImageBytes, float faceSimilarScore, float rgbThreshold, float irThreshold) {
// 获取引擎
FaceEngine faceEngine = faceEngineFactory.getFaceEngine();
int errorCode = 0; // 错误码
//人脸检测
ImageInfo imageInfo = getRGBData(authImageBytes);
List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
log.info("人脸检测数据:{}", faceInfoList);
log.info("[errorCode] = {}", errorCode);
if (errorCode == ErrorInfo.MERR_ASF_EX_INVALID_FACE_INFO.getValue()) {
log.info("无效的脸部信息:[errorCode] = {}", errorCode);
return FaceEngineR.failed("未检测到人脸");
} else if (errorCode != ErrorInfo.MOK.getValue()) {
log.info("人脸检测异常:[errorCode] = {}", errorCode);
return FaceEngineR.failed("人脸检测异常:[errorCode] = " + errorCode);
}
//特征提取
FaceFeature faceFeature = new FaceFeature();
errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature);
log.info("人脸特征值大小:{}", faceFeature.getFeatureData().length);
if (errorCode != ErrorInfo.MOK.getValue()) {
log.info("人脸特征提取异常:[errorCode] = {}", errorCode);
return FaceEngineR.failed("人脸特征提取异常:[errorCode] = " + errorCode);
}
//人脸检测2
ImageInfo imageInfo2 = getRGBData(localImageBytes);
List<FaceInfo> faceInfoList2 = new ArrayList<FaceInfo>();
errorCode = faceEngine.detectFaces(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(), imageInfo2.getImageFormat(), faceInfoList2);
log.info("人脸库人脸检测数据:{}", faceInfoList2);
log.info("[errorCode] = {}", errorCode);
if (errorCode == ErrorInfo.MERR_ASF_EX_INVALID_FACE_INFO.getValue()) {
log.info("人脸库无效的脸部信息:[errorCode] = {}", errorCode);
return FaceEngineR.failed("人脸库未检测到人脸");
} else if (errorCode != ErrorInfo.MOK.getValue()) {
log.info("人脸库人脸检测异常:[errorCode] = {}", errorCode);
return FaceEngineR.failed("人脸库人脸检测异常:[errorCode] = " + errorCode);
}
//特征提取2
FaceFeature faceFeature2 = new FaceFeature();
errorCode = faceEngine.extractFaceFeature(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(), imageInfo2.getImageFormat(), faceInfoList2.get(0), faceFeature2);
log.info("人脸库特征值大小:{}", faceFeature2.getFeatureData().length);
if (errorCode != ErrorInfo.MOK.getValue()) {
log.info("人脸库人脸特征提取异常:[errorCode] = {}", errorCode);
return FaceEngineR.failed("人脸库人脸特征提取异常:[errorCode] = " + errorCode);
}
//特征比对
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);
log.info("相似度:{}", faceSimilar.getScore());
if (errorCode != ErrorInfo.MOK.getValue()) {
log.info("人脸特征对比异常:[errorCode] = {}", errorCode);
return FaceEngineR.failed("人脸特征对比异常:[errorCode] = " + errorCode);
}
//相识度分数对比
if (faceSimilar.getScore() < faceSimilarScore) {
return FaceEngineR.failed("人脸对比未通过");
}
//设置活体测试
errorCode = faceEngine.setLivenessParam(rgbThreshold, irThreshold);
if (errorCode != ErrorInfo.MOK.getValue()) {
log.info("活体测试异常:[errorCode] = {}", errorCode);
return FaceEngineR.failed("活体测试异常:[errorCode] = " + errorCode);
}
//人脸属性检测
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);
if (errorCode != ErrorInfo.MOK.getValue()) {
log.info("人脸属性检测异常:[errorCode] = {}", errorCode);
return FaceEngineR.failed("人脸属性检测异常:[errorCode] = " + errorCode);
}
//3D信息检测
List<Face3DAngle> face3DAngleList = new ArrayList<Face3DAngle>();
errorCode = faceEngine.getFace3DAngle(face3DAngleList);
log.info("3D角度:{}", face3DAngleList.get(0).getPitch() + ",{}", face3DAngleList.get(0).getRoll() + ",{}", face3DAngleList.get(0).getYaw());
if (errorCode != ErrorInfo.MOK.getValue()) {
log.info("3D信息检测异常:[errorCode] = {}", errorCode);
return FaceEngineR.failed("3D信息检测异常:[errorCode] = " + errorCode);
}
//活体检测
List<LivenessInfo> livenessInfoList = new ArrayList<LivenessInfo>();
errorCode = faceEngine.getLiveness(livenessInfoList);
if (errorCode != ErrorInfo.MOK.getValue()) {
log.info("活体检测异常:[errorCode] = {}", errorCode);
return FaceEngineR.failed("活体检测异常:[errorCode] = " + errorCode);
}
log.info("活体:{}", livenessInfoList.get(0).getLiveness());
if (livenessInfoList.get(0).getLiveness() != 1) {
return FaceEngineR.failed("未检测到活体");
}
return FaceEngineR.ok("人脸认证通过");
}
/**
* 人脸认证
*
* @param authImageBytes 认证的图片字节
*/
public FaceEngineR detectFace(byte[] authImageBytes) {
// 获取引擎
FaceEngine faceEngine = faceEngineFactory.getFaceEngine();
int errorCode = 0; // 错误码
//人脸检测
ImageInfo imageInfo = getRGBData(authImageBytes);
List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
log.info("人脸检测数据:{}", faceInfoList);
if (errorCode != ErrorInfo.MERR_ASF_EX_INVALID_FACE_INFO.getValue()) {
log.info("无效的脸部信息:[errorCode] = {}", errorCode);
return FaceEngineR.failed("未检测到人脸");
} else if (errorCode != ErrorInfo.MOK.getValue()) {
log.info("人脸检测异常:[errorCode] = {}", errorCode);
return FaceEngineR.failed("人脸检测异常:[errorCode] = " + errorCode);
}
//特征提取
FaceFeature faceFeature = new FaceFeature();
errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature);
log.info("特征值大小:{}", faceFeature.getFeatureData().length);
if (errorCode != ErrorInfo.MOK.getValue()) {
log.info("人脸特征提取异常:[errorCode] = {}", errorCode);
return FaceEngineR.failed("人脸特征提取异常:[errorCode] = " + errorCode);
}
return FaceEngineR.ok(faceFeature.getFeatureData().length, "人脸检测通过");
}
}
6. 运行测试
编写单元测试来验证集成是否正确。确保已经下载并配置了虹软SDK,并且系统能够正确加载所需的库文件。
通过以上步骤,可以成功地将虹软人脸识别SDK集成到Java项目中,并实现人脸检测和比对功能。如果在集成过程中遇到任何问题,可以参考虹软的官方文档或联系他们的技术支持。