Java使用虹软SDK实现人脸检测、特征提取、比对

最近公司有个业务场景是需要用到人脸识别功能的,正好趁此机会写下这篇文章,以巩固自己不精的技能~

话不多说,开干!

1.环境准备:JDK1.8 + SpringBoot + Maven

2.下载虹软SDK

前往虹软开发者中心

新建应用--填写一些基本信息,完成后如下图

点击下载,然后解压文件,你会得到下图

我们主要是需要libs文件夹下的文件

3.引入jar包

        虹软并没有为spring boot 提供 maven 的引入方式,所以你需要手动将他的jar包集成到本地

        3.1src 同级目录下创建libs 文件夹,将虹软的jar包放到这个文件中

        3.2其次在 pom.xml 文件中将这个jar包引入到项目中

<dependency>
	<groupId>com.arcsoft.face</groupId>
	<artifactId>arcsoft-sdk-face</artifactId>
	<version>3.0.0.0</version>
	<scope>system</scope>
	<systemPath>${basedir}/libs/arcsoft-sdk-face-3.0.0.0.jar</systemPath>
</dependency>

        3.3允许你的项目在打包发布后仍然可以调用本地路径下的jar包

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
			<configuration>
                <!-- 加入下面这一行 -->
				<includeSystemScope>true</includeSystemScope>
			</configuration>
		</plugin>
	</plugins>
</build>

4.集成到项目

4.1application.yml配置

arcsoft:
  appid: *********#你注册应用后所对应的APP_ID
  sdkkey: ********#你注册应用后所对应的SDK_KEY
  libpath: *******#libs目录下的dll文件夹路径,如D:\\libs\\WIN64
  engine-configuration:       #引擎配置
    detectMode: IMAGE
    detectFaceOrientPriority: ASF_OP_ALL_OUT
    detectFaceScale: 32
    detectFaceMaxNum: 8
  function-configuration:     #功能配置
    supportAge: true
    supportFace3dAngle: true
    supportFaceDetect: true
    supportFaceRecognition: true
    supportGender: true
    supportLiveness: true
    supportIRLiveness: true

4.2引擎类

@Data
@ConfigurationProperties(prefix = "arcsoft.engine-configuration")
public class EngineConfigurationProperty {
    private String detectMode;
    private String detectFaceOrientPriority;
    private Integer detectFaceScale;
    private Integer detectFaceMaxNum;
}

4.3功能类

@Data
@ConfigurationProperties(prefix = "arcsoft.function-configuration")
public class FunConfigurationProperty {
    private boolean supportFace3dAngle = true;
    private boolean supportFaceDetect = true;
    private boolean supportFaceRecognition = true;
    private boolean supportGender = true;
    private boolean supportAge = true;
    private boolean supportLiveness = true;
    private boolean supportIRLiveness = true;
}

4.4初始化配置类

@Data
@Configuration
@ConfigurationProperties(prefix = "arcsoft")
@EnableConfigurationProperties({ FunConfigurationProperty.class,EngineConfigurationProperty.class})
public class ArcSoftConfig {

    @Autowired
    private FunConfigurationProperty funConfigurationProperty;

    @Autowired
    private EngineConfigurationProperty engineConfigurationProperty;

    private String appid;
    private String sdkkey;
    private String libpath;

    @Bean
    public FaceEngine faceEngine(){
        FaceEngine faceEngine = new FaceEngine(libpath);
        int errorCode = faceEngine.activeOnline(appid, sdkkey);
        if (errorCode != ErrorInfo.MOK.getValue() &&
                errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue())
            throw new RuntimeException("引擎注册失败");
        EngineConfiguration engineConfiguration = getFaceEngineConfiguration();
        //初始化引擎
        errorCode = faceEngine.init(engineConfiguration);
        if (errorCode != ErrorInfo.MOK.getValue())
            throw new RuntimeException("初始化引擎失败");
        return faceEngine;
    }

    /**
     * 初始化引擎配置
     * @return
     */
    private EngineConfiguration getFaceEngineConfiguration() {
        EngineConfiguration engineConfiguration = new EngineConfiguration();
        //配置引擎模式
        if ("IMAGE".equals(engineConfigurationProperty.getDetectMode()))
            engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
        else
            engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_VIDEO);

        //配置人脸角度 全角度 ASF_OP_ALL_OUT 不够准确且检测速度慢
        switch (engineConfigurationProperty.getDetectFaceOrientPriority()){
            case "ASF_OP_0_ONLY":
                engineConfiguration
                        .setDetectFaceOrientPriority(DetectOrient.ASF_OP_0_ONLY);
                break;
            case "ASF_OP_90_ONLY":
                engineConfiguration
                        .setDetectFaceOrientPriority(DetectOrient.ASF_OP_90_ONLY);
                break;
            case "ASF_OP_270_ONLY":
                engineConfiguration
                        .setDetectFaceOrientPriority(DetectOrient.ASF_OP_270_ONLY);
                break;
            case "ASF_OP_180_ONLY":
                engineConfiguration
                        .setDetectFaceOrientPriority(DetectOrient.ASF_OP_180_ONLY);
                break;
            case "ASF_OP_ALL_OUT":
                engineConfiguration
                        .setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
                break;
            default:
                engineConfiguration
                        .setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
        }
        //设置识别的最小人脸比
        engineConfiguration
                .setDetectFaceScaleVal(engineConfigurationProperty.getDetectFaceScale());
        engineConfiguration
                .setDetectFaceMaxNum(engineConfigurationProperty.getDetectFaceMaxNum());
        //功能配置
        initFuncConfiguration(engineConfiguration);
        return engineConfiguration;
    }

    /**
     * 功能配置
     * @param engineConfiguration
     */
    private void initFuncConfiguration(EngineConfiguration engineConfiguration){
        FunctionConfiguration functionConfiguration = new FunctionConfiguration();
        //是否支持年龄检测
        functionConfiguration.setSupportAge(funConfigurationProperty.isSupportAge());
        //是否支持3d 检测
        functionConfiguration
                .setSupportFace3dAngle(funConfigurationProperty.isSupportFace3dAngle());
        //是否支持人脸检测
        functionConfiguration
                .setSupportFaceDetect(funConfigurationProperty.isSupportFaceDetect());
        //是否支持人脸识别
        functionConfiguration
                .setSupportFaceRecognition(funConfigurationProperty.isSupportFaceRecognition());
        //是否支持性别检测
        functionConfiguration
                .setSupportGender(funConfigurationProperty.isSupportGender());
        //是否支持活体检测
        functionConfiguration
                .setSupportLiveness(funConfigurationProperty.isSupportLiveness());
        //是否至此IR活体检测
        functionConfiguration
                .setSupportIRLiveness(funConfigurationProperty.isSupportIRLiveness());
        engineConfiguration.setFunctionConfiguration(functionConfiguration);
    }
}

4.5对图片对象封装的工具类

public class ArcSoftUtils {

    /**
     * 处理 File 的图片流
     * @param img
     * @return
     */
    public static ImageInfoMeta packImageInfoEx(File img){
        ImageInfo imageInfo = getRGBData(img);
        return packImageInfoMeta(imageInfo);
    }

    /**
     * 处理 byte[] 的图片流
     * @param img
     * @return
     */
    public static ImageInfoMeta packImageInfoMeta(byte[] img){
        ImageInfo imageInfo = getRGBData(img);
        return packImageInfoMeta(imageInfo);
    }

    /**
     * 处理 InpuStream 的图片流
     * @param img
     * @return
     */
    public static ImageInfoMeta packImageInfoMeta(InputStream img){
        ImageInfo imageInfo = getRGBData(img);
        return packImageInfoMeta(imageInfo);
    }


    /**
     * 打包生成 ImageInfoMeta
     * @param imageInfo
     * @return
     */
    private static ImageInfoMeta packImageInfoMeta(ImageInfo imageInfo){
        ImageInfoMeta imageInfoMeta = new ImageInfoMeta(imageInfo);
        return imageInfoMeta;
    }

    /**
     * 对imageInfo 和 imageInfoEx 的打包对象
     * @return
     */
    @Data
    public static class ImageInfoMeta{
        private ImageInfo imageInfo;
        private ImageInfoEx imageInfoEx;

        public ImageInfoMeta(ImageInfo imageInfo) {
            this.imageInfo = imageInfo;
            imageInfoEx = new ImageInfoEx();
            imageInfoEx.setHeight(imageInfo.getHeight());
            imageInfoEx.setWidth(imageInfo.getWidth());
            imageInfoEx.setImageFormat(imageInfo.getImageFormat());
            imageInfoEx.setImageDataPlanes(new byte[][]{imageInfo.getImageData()});
            imageInfoEx.setImageStrides(new int[]{imageInfo.getWidth() * 3});
        }
    }

}

4.6封装的常用方法工具类

@Component
public class ArcSoftMothodUtils {

    @Autowired
    private FaceEngine faceEngine;

    /**
     * 人脸检测
     */
    public List<FaceInfo> detectFace(ImageInfoEx imageInfoEx) {
        if (imageInfoEx == null)
            return null;
        List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
        int i = faceEngine.detectFaces(imageInfoEx, DetectModel.ASF_DETECT_MODEL_RGB, faceInfoList);
        checkEngineResult(i, ErrorInfo.MOK.getValue(), "人脸检测失败");
        return faceInfoList;
    }

    /**
     * 特征提取
     */
    public FaceFeature extractFaceFeature(
            List<FaceInfo> faceInfoList, ImageInfoEx imageInfoEx) {

        if (faceInfoList == null || imageInfoEx == null)
            return null;
        FaceFeature faceFeature = new FaceFeature();
        int i = faceEngine.extractFaceFeature(imageInfoEx, faceInfoList.get(0), faceFeature);
        checkEngineResult(i, ErrorInfo.MOK.getValue(), "人脸特征提取失败");
        return faceFeature;
    }

    /**
     * 特征比对
     */
    public FaceSimilar compareFaceFeature(
            FaceFeature target, FaceFeature source, CompareModel compareModel) {
        FaceSimilar faceSimilar = new FaceSimilar();
        int i = faceEngine
                .compareFaceFeature(target, source, compareModel, faceSimilar);
        checkEngineResult(i, ErrorInfo.MOK.getValue(), "人脸特征对比失败");
        return faceSimilar;
    }

    /**
     * 错误检测
     */
    private void checkEngineResult(int errorCode, int sourceCode, String errMsg) {
        if (errorCode != sourceCode)
            throw new RuntimeException(errMsg);
    }
}


4.7测试

@RestController
@RequestMapping("/arcsoft")
public class FaceController {

    @Autowired
    private ArcSoftMothodUtils arcSoftMothodUtils;

    @GetMapping("/detectFace")
    public Result detectFace(String imgPath) {
        List<FaceInfo> faceInfo = arcSoftMothodUtils.detectFace(ArcfaceUtils.packImageInfoEx(new File(imgPath)).getImageInfoEx());
        return Result.succ(faceInfo);
    }

    @GetMapping("/extractFaceFeature")
    public Result extractFaceFeature(String imgPath) {
        List<FaceInfo> faceInfo = arcSoftMothodUtils.detectFace(ArcfaceUtils.packImageInfoEx(new File(imgPath)).getImageInfoEx());
        FaceFeature faceFeature = arcSoftMothodUtils.extractFaceFeature(faceInfo, ArcfaceUtils.packImageInfoEx(new File(imgPath)).getImageInfoEx());
        return Result.succ(faceFeature);
    }

    @GetMapping("/compareFaceFeature")
    public Result compareFaceFeature(String imgPath1,String imgPath2) {
        List<FaceInfo> faceInfo1 = arcSoftMothodUtils.detectFace(ArcfaceUtils.packImageInfoEx(new File(imgPath1)).getImageInfoEx());
        FaceFeature faceFeature1 = arcSoftMothodUtils.extractFaceFeature(faceInfo1, ArcfaceUtils.packImageInfoEx(new File(imgPath1)).getImageInfoEx());

        List<FaceInfo> faceInfo2 = arcSoftMothodUtils.detectFace(ArcfaceUtils.packImageInfoEx(new File(imgPath2)).getImageInfoEx());
        FaceFeature faceFeature2 = arcSoftMothodUtils.extractFaceFeature(faceInfo2, ArcfaceUtils.packImageInfoEx(new File(imgPath2)).getImageInfoEx());

        FaceSimilar faceSimilar = arcSoftMothodUtils.compareFaceFeature(faceFeature1, faceFeature2, CompareModel.LIFE_PHOTO);
        return Result.succ(faceSimilar);
    }



}

到这里整个流程就结束了,其实虹软的几个方法的使用有两种方式,我使用的是第二种,也就是下图红圈中的

最后,附上文档中心--虹软AI-虹软AI开放平台

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值