海康威视+虹软人脸识别

虹软人脸识别

简介

最近公司项目新需求需要做视频监控+陌生人告警,产品经理和项目经理商量了一周,敲定试用海康威视摄像头+虹软人脸识别进行开发。

刚刚接手需求的时候,都不知道这两个大神是啥东西,百度了一上午,了解了一下两家公司和自己需要的一些技术文档。

首先,这篇文章我们先讲讲虹软人脸识别吧。

虹软科技股份有限公司提供计算机视觉行业算法服务及解决方案,致力于视觉技术的研发和应用,坚持以原创技术为核心驱动力,在全球范围内为智能手机、智能汽车、物联网等智能设备提供一站式视觉解决方案。

image-20211117092854420

准备工作

注册用户

首先,我们要注册一个虹软的账号,申请一个应用。

创建应用

image-20211117094553963

创建应用成功之后,我们需要添加SDK,这里我们已免费版的为例,后续介绍付费版

image-20211117094649622

添加SDK

因为我们的开发环境是windows,服务器环境也是windows,所以这里我选择的是windows平台,这里可以自行进行选择,应该只是库文件的不同。

image-20211117094733272

到这里,我们就能看到 APP_IDSDK_KEY 两个值,后续需要这两个值进行虹软激活

image-20211117094947416

SDK文档

image-20211117095221914

SDK文档:https://ai.arcsoft.com.cn/product/arcface.html

我们下载SDK文档和Java案例之后能看到如下文件

image-20211117093655849

libs目录文件:

image-20211117094137246

  • doc目录里面存放着虹软sdk的接口文档,我们在调用SDK时方便查阅
  • libs目录存放了SDK jar包还有依赖的必要库文件
  • samplecode目录存放了简单的示例代码

添加库文件

对windows操作系统熟悉的朋友,就知道其他程序依赖第三方库文件,需要配置到系统环境变量中。

在Path变量中添加库文件的路径即可

image-20211117095725291

到这里,我们前期工作就差不多完成了

开发环境搭建

引入SDK

首先我们要引入虹软的jar包,因为他是第三方的jar包,没有存放到共有的Maven库中,我们需要手动导入到项目中去。

image-20211117100302043

在Maven中引用

        <!--虹软人脸识别sdk-->
        <dependency>
            <groupId>com.arcsoft.face</groupId>
            <artifactId>arcsoft-sdk-face</artifactId>
            <version>3.0.0.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/resources/lib/arcsoft-sdk-face-3.0.0.0.jar</systemPath>
        </dependency>

虹软配置类

@Configuration
public class FaceEngineConfig {

    @Value("${config.freesdk.app-id}")
    private String appId;

    @Value("${config.freesdk.sdk-key}")
    private String sdkKey;

    @Bean
    public FaceEngine getFaceEngineInstance() {
        FaceEngine mFaceEngine = new FaceEngine();
        // 激活引擎
        //在线激活
        int activeCode = mFaceEngine.activeOnline(appId, sdkKey);
        System.out.println("code======>" + activeCode);
        if (activeCode != ErrorInfo.MOK.getValue() && activeCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
            System.out.println("引擎激活失败");
        } else {
            System.out.println("引擎激活成功");
        }
        // 引擎配置
        EngineConfiguration engineConfiguration = new EngineConfiguration();
        engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
        engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_0_ONLY);
        // 功能配置,这些配置可以查阅SDK文档,根据自己的需要进行修改
        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);
        // 初始化引擎
        int initCode = mFaceEngine.init(engineConfiguration);

        if (initCode != ErrorInfo.MOK.getValue()) {
            System.out.println("000000=-----初始化引擎失败");
        }
        return mFaceEngine;
    }

}

这里我们使用的是在线激活人脸引擎的方式,这里需要我们把刚刚申请到的appId和sdkKey输入进去

int activeCode = mFaceEngine.activeOnline(appId, sdkKey)

我们也可以查阅SDK文档,这里我们就已激活SDK为例。

image-20211117101028051

image-20211117101040814

到这里,我们就已经把虹软SDK 的bean导入进行了,方便我们后续的操作。

简单使用接口->单个人脸信息

我的需求是拿到海康威视的视频流然后逐帧拿到图片,获取到图片中人脸的信息,这里我们就以获取单个人脸特征信息为例

 /**
     * 抽取单个人脸特征
     *
     * @param f         人脸信息
     * @param imageInfo 人脸图片信息
     * @return 人脸特征
     */
    public byte[] extractFaceFeatureList(FaceInfo f, ImageInfo imageInfo) {
        FaceEngine faceEngine = null;
        try {
            // 获取引擎对象
            faceEngine = imgFaceObjectPool.borrowObject();
            FaceFeature faceFeature = new FaceFeature();
            // 提取人脸特征
            int code = faceEngine.extractFaceFeature(imageInfo.getRgbData(), imageInfo.getWidth(), imageInfo.getHeight(),
                    ImageFormat.CP_PAF_BGR24, f, faceFeature);
            if (code != 0) {
                logger.error("FACE:" + f.getFaceId() + "人脸特征抽取结果不可信" + code);
                //return null;
            }
            return faceFeature.getFeatureData();
        } catch (Exception e) {
            logger.error("人脸特征抽取异常", e);
        } finally {
            if (faceEngine != null) {
                // 释放引擎对象
                imgFaceObjectPool.returnObject(faceEngine);
            }
        }
        return null;
    }

此接口获取到的人脸信息是一个二进制流的形式,我后续是把他存到数据库,项目启动的时候读到缓存中,方便进行人脸比对

faceFeature.getFeatureData()

int code = faceEngine.extractFaceFeature(imageInfo.getRgbData(), imageInfo.getWidth(), imageInfo.getHeight(),ImageFormat.CP_PAF_BGR24, f, faceFeature);

示例代码

在正式开发前也可以用示例代码进行一些简单的测试,看看满不满足你的需求

import com.arcsoft.face.*;
import com.arcsoft.face.enums.*;
import com.arcsoft.face.toolkit.ImageInfo;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import com.arcsoft.face.toolkit.ImageInfoEx;

import static com.arcsoft.face.toolkit.ImageFactory.getGrayData;
import static com.arcsoft.face.toolkit.ImageFactory.getRGBData;


public class FaceEngineTest {


    public static void main(String[] args) {

        //从官网获取
        String appId = "";
        String sdkKey = "";


        FaceEngine faceEngine = new FaceEngine("D:\\arcsoft_lib");
        //激活引擎
        int errorCode = faceEngine.activeOnline(appId, sdkKey);

        if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
            System.out.println("引擎激活失败");
        }


        ActiveFileInfo activeFileInfo=new ActiveFileInfo();
        errorCode = faceEngine.getActiveFileInfo(activeFileInfo);
        if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
            System.out.println("获取激活文件信息失败");
        }

        //引擎配置
        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()) {
            System.out.println("初始化引擎失败");
        }


        //人脸检测
        ImageInfo imageInfo = getRGBData(new File("d:\\aaa.jpg"));
        List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
        errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
        System.out.println(faceInfoList);

        //特征提取
        FaceFeature faceFeature = new FaceFeature();
        errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature);
        System.out.println("特征值大小:" + faceFeature.getFeatureData().length);

        //人脸检测2
        ImageInfo imageInfo2 = getRGBData(new File("d:\\ccc.jpg"));
        List<FaceInfo> faceInfoList2 = new ArrayList<FaceInfo>();
        errorCode = faceEngine.detectFaces(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(),imageInfo.getImageFormat(), faceInfoList2);
        System.out.println(faceInfoList);

        //特征提取2
        FaceFeature faceFeature2 = new FaceFeature();
        errorCode = faceEngine.extractFaceFeature(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(), imageInfo.getImageFormat(), faceInfoList2.get(0), faceFeature2);
        System.out.println("特征值大小:" + faceFeature.getFeatureData().length);

        //特征比对
        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);

        System.out.println("相似度:" + faceSimilar.getScore());

        //设置活体测试
        errorCode = faceEngine.setLivenessParam(0.5f, 0.7f);
        //人脸属性检测
        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);


        //性别检测
        List<GenderInfo> genderInfoList = new ArrayList<GenderInfo>();
        errorCode = faceEngine.getGender(genderInfoList);
        System.out.println("性别:" + genderInfoList.get(0).getGender());

        //年龄检测
        List<AgeInfo> ageInfoList = new ArrayList<AgeInfo>();
        errorCode = faceEngine.getAge(ageInfoList);
        System.out.println("年龄:" + ageInfoList.get(0).getAge());

        //3D信息检测
        List<Face3DAngle> face3DAngleList = new ArrayList<Face3DAngle>();
        errorCode = faceEngine.getFace3DAngle(face3DAngleList);
        System.out.println("3D角度:" + face3DAngleList.get(0).getPitch() + "," + face3DAngleList.get(0).getRoll() + "," + face3DAngleList.get(0).getYaw());

        //活体检测
        List<LivenessInfo> livenessInfoList = new ArrayList<LivenessInfo>();
        errorCode = faceEngine.getLiveness(livenessInfoList);
        System.out.println("活体:" + livenessInfoList.get(0).getLiveness());


        //IR属性处理
        ImageInfo imageInfoGray = getGrayData(new File("d:\\IR_480p.jpg"));
        List<FaceInfo> faceInfoListGray = new ArrayList<FaceInfo>();
        errorCode = faceEngine.detectFaces(imageInfoGray.getImageData(), imageInfoGray.getWidth(), imageInfoGray.getHeight(), imageInfoGray.getImageFormat(), faceInfoListGray);

        FunctionConfiguration configuration2 = new FunctionConfiguration();
        configuration2.setSupportIRLiveness(true);
        errorCode = faceEngine.processIr(imageInfoGray.getImageData(), imageInfoGray.getWidth(), imageInfoGray.getHeight(), imageInfoGray.getImageFormat(), faceInfoListGray, configuration2);
        //IR活体检测
        List<IrLivenessInfo> irLivenessInfo = new ArrayList<>();
        errorCode = faceEngine.getLivenessIr(irLivenessInfo);
        System.out.println("IR活体:" + irLivenessInfo.get(0).getLiveness());

        ImageInfoEx 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});
        List<FaceInfo> faceInfoList1 = new ArrayList<>();
        errorCode = faceEngine.detectFaces(imageInfoEx, DetectModel.ASF_DETECT_MODEL_RGB, faceInfoList1);

        FunctionConfiguration fun = new FunctionConfiguration();
        fun.setSupportAge(true);
        errorCode = faceEngine.process(imageInfoEx, faceInfoList1, functionConfiguration);
        List<AgeInfo> ageInfoList1 = new ArrayList<>();
        int age = faceEngine.getAge(ageInfoList1);
        System.out.println("年龄:" + ageInfoList1.get(0).getAge());

        FaceFeature feature = new FaceFeature();
        errorCode = faceEngine.extractFaceFeature(imageInfoEx, faceInfoList1.get(0), feature);


        //引擎卸载
        errorCode = faceEngine.unInit();

    }
}

碰到的问题

在开发及上线过程中,碰到一些问题进行一些汇总

  1. 添加库文件的问题,在开发中,把代码提交到git上之后,同小组的开发人员拉代码之后因为没有添加库文件的原因报错,这时候添加了库文件没有重启idea,编译器没有及时生效,导致还是会继续报错。解决方案:重启idea
  2. 这里我们使用的是在线激活SDK的方法,查看SDK文档我们知道,在线激活需要服务器能够正常连接公网才行,但是有些项目的生产环境是无法连接公网的,这里我们就需要使用离线增值版的SDK,而虹软官网一般是100个SDK起卖的,一般的公司或者个人开发者是不需要这么大的量的。这里我解决方案就不在文档里说了,有需求的可以私聊我,我可以给你解决方案。

离线增值版激活

你在购买了之后,一般会教你怎么去激活,具体的激活是我买的那个老哥操作的,我说说我怎么配合进行操作吧

  1. 首先他会发一个生产机器激活文件的.exe文件给你,你执行之后就会生成一个文件,虹软后台会需要这个文件生成激活文档。特别注意,这个文件不要在自己的开发环境浪费了
  2. 之后他就会把这个激活文件发给你,在线的SDK和离线增值版的SDK是不一样的,我们需要把jar包进行替换,这里我是直接问那个老哥要的,没去官网找了。(毕竟我花了钱,能不干的事咱就不干),激活文件放到服务器一般不会去看的文件夹里,防止有人手痒给删了。
  3. 之后就是修改激活SDK的方式了,方法就是把激活文件的路径给它就好,如下:
String filePath = "F:\\86111149K3RK689A.dat";
int activeCode = mFaceEngine.activeOffline(filePath);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值