Java 虹软人脸识别SDK:基于虹软人脸识别SDK的Java项目集成指南

基于虹软人脸识别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项目中,并实现人脸检测和比对功能。如果在集成过程中遇到任何问题,可以参考虹软的官方文档联系他们的技术支持

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值