失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > java 集成虹软人脸识别 SDK 实现人脸识别认证功能

java 集成虹软人脸识别 SDK 实现人脸识别认证功能

时间:2023-01-15 12:52:14

相关推荐

java 集成虹软人脸识别 SDK 实现人脸识别认证功能

系列文章目录

引入本地 jar 包教程: /demo_yo/article/details/132495029

文章目录

系列文章目录前言一、SDK 下载二、SDK 集成1、jar 依赖包2、dll 链接文件 三、API 集成1、yaml 配置2、Properties 配置类3、Factory 工厂类4、Service 服务类5、服务类响应实体6、API 方法类7、文件工具类

前言

本文详细介绍了 java 集成免费虹软人脸识别的详细流程,从 SDK 下载到 SDK 的集成,以及 API 的封装策略。

一、SDK 下载

进入虹软开发者中心:/ucenter/resource/build/index.html#/index

选择免费SDK:

创建应用:

下载SDK:

二、SDK 集成

1、jar 依赖包

将将压缩包中的 jar 包,放置在 resource 文件夹下的 lib 文件夹中。

在 pom.xml 中引入本地依赖:

<dependency><groupId>com.arcsoft</groupId><artifactId>json</artifactId><version>1.0</version><scope>system</scope><systemPath>${project.basedir}/src/main/resources/lib/arcsoft-sdk-face-3.0.0.0.jar</systemPath></dependency>

关于本地 jar 包的引用方式说明,请转 引入本地 jar 包教程 /demo_yo/article/details/132495029

2、dll 链接文件

将压缩包中的 WIN64 dll 动态链接文件,放置在项目根目录下创建的 lib 文件夹下。

将在人脸识别引擎工厂类中引用改路径,用于引擎加载。如下:

// 加载引擎FaceEngine faceEngine = new FaceEngine(System.getProperty("user.dir") + File.separator + "lib" + File.separator + "WIN64");

三、API 集成

1、yaml 配置

# 人脸认证引擎配置face-engine:# 应用idapp-id: xxxxxxxxxxxxxxxxx# sdk密匙sdk-key: xxxxxxxxxxxxxxxxx# 人脸对比阀值(建议0.8)face-similar-score: 0.8# RGB活体检测阀值(建议0.5)rgb-threshold: 0.5# IR活体检测阀值(建议0.7)ir-threshold: 0.7

2、Properties 配置类

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;}

3、Factory 工厂类

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.whitemeen.magic.modules.demo.faceengine.config.FaceEngineProperties;import lombok.RequiredArgsConstructor;import lombok.extern.slf4j.Slf4j;import org.ponent;import javax.annotation.PostConstruct;import java.io.File;import java.util.concurrent.ConcurrentHashMap;@Slf4j@Component@RequiredArgsConstructorpublic 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<>(); // 引擎Beanprivate ConcurrentHashMap<String, FunctionConfiguration> functionConfigurationMap = new ConcurrentHashMap<>(); // 引擎配置private final FaceEngineProperties faceEngineProperties;/*** 在bean初始化后进行引擎初始化*/@PostConstructpublic void init() {log.info("进入人脸引擎初始化");// 加载引擎FaceEngine faceEngine = new FaceEngine(System.getProperty("user.dir") + File.separator + "lib" + File.separator + "WIN64");// 激活引擎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;}// 将引擎放入mapfaceEngineMap.put(FACE_ENGINE_KEY, faceEngine);// 将引擎配置放入mapfunctionConfigurationMap.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);}}

4、Service 服务类

import com.arcsoft.face.*;import com.arcsoft.face.enums.ErrorInfo;import com.arcsoft.face.toolkit.ImageInfo;import com.whitemeen.magic.modules.demo.faceengine.factory.FaceEngineFactory;import com.whitemeen.magic.modules.demo.faceengine.model.FaceEngineR;import lombok.RequiredArgsConstructor;import lombok.extern.slf4j.Slf4j;import org.ponent;import java.util.ArrayList;import java.util.List;import static com.arcsoft.face.toolkit.ImageFactory.getRGBData;@Slf4j@Component@RequiredArgsConstructorpublic class FaceEngineService {private final FaceEngineFactory faceEngineFactory;/*** 人脸认证* <p>* 建议待检测的图像人脸角度上、下、左、右转向小于30度;* 图片中人脸尺寸不小于50 x 50像素;* 图片大小小于10MB;** @param authImageBytes 认证的图片字节* @param localImageBytes 人脸库的图片字节* @param faceSimilarScore 人脸对比阀值(范围为[0~1],生活照推荐:0.80,证件照推荐:0.82)* @param rgbThresholdRGB活体检测阀值(范围为[0~1],推荐:0.5)* @param irThresholdIR活体检测阀值(范围为[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);}//人脸检测2ImageInfo 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);}//特征提取2FaceFeature 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 = pareFaceFeature(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, "人脸检测通过");}}

5、服务类响应实体

import lombok.Data;import java.io.Serializable;@Datapublic 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;}}

6、API 方法类

import com.mon.core.exception.FcApiException;import com.mon.core.fc.kit.FcFileKit;import com.whiemeen.magic.modules.dome.faceengine.config.FaceEngineProperties;import com.whiemeen.magic.modules.dome.faceengine.model.FaceEngineR;import com.whiemeen.magic.modules.dome.faceengine.service.FaceEngineService;import lombok.RequiredArgsConstructor;import lombok.extern.slf4j.Slf4j;import org.ponent;import java.util.Optional;/*** 人脸认证api*/@Slf4j@Component@RequiredArgsConstructorpublic class FaceEngineApi {private final FaceEngineService faceEngineService;private final FaceEngineProperties faceEngineProperties;/*** 本地人脸检测*/public boolean detectLocalFace(String imagePath) {log.info("检测人脸:{}", imagePath);// 将图片url转换为文件字节byte[] authImageBytes = FcFileKit.imagePathToBytes(imagePath);Optional.ofNullable(authImageBytes).orElseThrow(() -> new FcApiException("文件读取异常"));// 人脸检测FaceEngineR faceEngineR = faceEngineService.detectFace(authImageBytes);if (faceEngineR.getCode() != 0) {log.info("认证失败:[code] {} [msg] {}", faceEngineR.getCode(), faceEngineR.getMsg());throw new FcApiException(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 FcApiException("文件读取异常"));// 人脸检测FaceEngineR faceEngineR = faceEngineService.detectFace(authImageBytes);if (faceEngineR.getCode() != 0) {log.info("认证失败:[code] {} [msg] {}", faceEngineR.getCode(), faceEngineR.getMsg());throw new FcApiException(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 FcApiException("文件读取异常"));byte[] localImageBytes = FcFileKit.imagePathToBytes(localImagePath);Optional.ofNullable(localImageBytes).orElseThrow(() -> new FcApiException("人脸库文件读取异常"));log.info("相识度阀值:{}", faceEngineProperties.getFaceSimilarScore());log.info("RGB活体检测阀值:{}", faceEngineProperties.getRgbThreshold());log.info("IR活体检测阀值:{}", faceEngineProperties.getIrThreshold());FaceEngineR faceEngineR = pareFace(authImageBytes, localImageBytes,faceEngineProperties.getFaceSimilarScore(),faceEngineProperties.getRgbThreshold(),faceEngineProperties.getIrThreshold());if (faceEngineR.getCode() != 0) {log.info("认证失败:[code] {} [msg] {}", faceEngineR.getCode(), faceEngineR.getMsg());throw new FcApiException(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 FcApiException("文件读取异常"));byte[] localImageBytes = FcFileKit.imageUrlToBytes(localImageUrl);Optional.ofNullable(localImageBytes).orElseThrow(() -> new FcApiException("人脸库文件读取异常"));log.info("相识度阀值:{}", faceEngineProperties.getFaceSimilarScore());log.info("RGB活体检测阀值:{}", faceEngineProperties.getRgbThreshold());log.info("IR活体检测阀值:{}", faceEngineProperties.getIrThreshold());FaceEngineR faceEngineR = pareFace(authImageBytes, localImageBytes,faceEngineProperties.getFaceSimilarScore(),faceEngineProperties.getRgbThreshold(),faceEngineProperties.getIrThreshold());if (faceEngineR.getCode() != 0) {log.info("认证失败:[code] {} [msg] {}", faceEngineR.getCode(), faceEngineR.getMsg());throw new FcApiException(faceEngineR.getMsg());}log.info("认证通过");return true;}}

7、文件工具类

import cn.hutool.core.img.Img;import cn.hutool.core.io.FileUtil;import java.io.ByteArrayOutputStream;import java.io.InputStream;import .HttpURLConnection;import .URL;import java.nio.file.Files;import java.nio.file.Paths;public class FcFileKit {/*** 本地文件path转化为二进制文件** @param imagePath 本地文件path* @return 二进制文件*/public static byte[] imagePathToBytes(String imagePath) {try {return 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;}}}

如果觉得《java 集成虹软人脸识别 SDK 实现人脸识别认证功能》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。