首页 > 编程语言 >Java 虹软人脸识别SDK:基于虹软人脸识别SDK的Java项目集成指南

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

时间:2024-09-06 09:53:46浏览次数:7  
标签:info 人脸识别 Java log 虹软 errorCode 人脸 import return

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

标签:info,人脸识别,Java,log,虹软,errorCode,人脸,import,return
From: https://blog.csdn.net/qq_44711486/article/details/141822429

相关文章

  • 基于Java的信息发布与管理系统设计与开发-计算机毕业设计源码+LW文档
    摘要在互联网高度发展的今天,人们已经习惯利用网络来填充生活中的碎片时间,如听歌、看视频、浏览信息等。然而,遇到喜欢的内容时,由于时间限制,可能无法一次性看完。此外,各种信息内容分布在不同的平台,给用户查找带来了不便。针对这一问题,Java的信息发布与管理系统应运而生,它有效地解决......
  • Java面试——基础篇
    基本数据类型与包装类基本数据类型与引用数据类型区别存储方式:基本数据类型直接存储值,而引用数据类型存储的是对象的引用(内存地址)内存分配:基本数据类型在栈上分配内存,引用数据类型在堆上分配内存(具体内容存放在堆中,栈中存放的是其具体内容所在内存的地址)。栈上的分配速度......
  • JavaWeb - Spring Boot - 请求参数
    @RequestMapping从注解名称上我们可以看到,@RequestMapping注解的作用就是将请求和处理请求的控制器方法关联起来,建立映射关系。SpringMVC接收到指定的请求,就会来找到在映射关系中对应的控制器方法来处理这个请求。@RequestMapping标识一个类:设置映射请求的请求路径的初始信......
  • Java工程师多年之后看指针
      指针是基本数据类型,占用4个字节。Int类型的数据计算机处理语言中是处中间层。使用图形化方式可以这样更形象直观。   计算机对二进制处理数据的方式比较敏感。现人们的大脑计数方式是通过十进制的方式计算日常和工作中需要的业务。操作符的限制,才增加了十六进制......
  • Java泛型-类型参数化
    一.泛型解决支持多类型参数的方案:1,重载:在同一个类中,方法名相同,参数不同不足之处:代码过于重复publicclassTool{  publicStringarrToStr(String[]arr,Stringsymbol){    Stringstr="";    for(Stringv:arr){      str+=s......
  • Java开发初学:认识Java的基本知识
    Java的基础知识等进行介绍Java的发展史与Java体系Java是sun(StanfordUniversityNetwork)公司,1982年成立,java的主要设计者是JamesGosling,来源一个为电子消费产品项目Green。95年,Sun发布JDK1.t098年,JDK1.2,更名为Java2后续JDK1.3、1.4JDK1.5,更名为Java5.0我们使用jdk1......
  • Java毕业设计基于SpringBoot的超市在线销售系统(源码+文档+调试+讲解)
    文末获取资源,收藏关注不迷路文章目录项目介绍技术介绍项目界面关键代码目录项目介绍该超市在线销售系统采用B/S架构、并采用java语言以及springboot框架进行开发。该系统主要设计并完成了管理过程中的用户注册登录、个人信息修改、用户、普通管理员、商品信息、留言......
  • 基于java语言的点击方块小游戏
    游戏玩法目标:玩家需要在限时内点击尽可能多的方块。规则:游戏启动后,屏幕上会随机出现一个移动的方块;玩家点击方块得分,方块会重新随机出现在另一个位置;游戏限时为30秒,时间结束时显示总分。代码importjavax.swing.*;importjava.awt.*;importjava.awt.event.*;import......
  • Java使用gdal更改shp要素的字段属性值
    文章目录前言一、GDAL和Java版本二、代码1.引入gdal,设置gdal环境2.修改要素属性值3.测试使用总结前言昨天实现了gdal对shp文件进行属性字段的重命名,Java使用gdal重命名shp属性字段。对于gdb的话也是类似的思路,只不过gdb有多个图层,以后有涉及到再写。今天试了下gda......
  • Java毕业设计基于SpringBoot的毕业设计管理系统(源码+文档+调试+讲解)
    文末获取资源,收藏关注不迷路文章目录项目介绍技术介绍项目界面关键代码目录项目介绍本论文主要完成不同用户的权限划分,不同用户具有不同权限的操作功能,在学生模块,主要有学生进行注册和登录,学生可以查看开题报告、中期检查、论文提交、论文指导、毕业答辩等,还能......