人脸识别技术是随着技术发展而产生的生物识别技术,目前已广泛应用于安防领域,主要用于身份验证和身份识别。视频监控是安防系统常见的一种表现形式,需要部署各种摄像头,包括网络摄像头IPC,可以通过流媒体如RTSP视频流的方式供第三方系统集成。

虹软是计算机视觉行业领先的算法服务提供商及解决方案供应商,提供免费、离线的人脸识别SDK,主要包含人脸检测、性别检测、年龄检测、人脸识别、图像质量检测、RGB活体检测、IR活体检测等能力。支持主流Windows、Linux、Android、iOS等平台及Java、C++等开发语言。

本文基于虹软免费人脸识别SDK,从IPC提供的RTSP视频流抓帧进行人脸识别。主要技术方案是通过JavaCV定时抓取视频帧保存为图像,然后针对图像通过虹软SDK提取特征,同特征库里面的人脸进行比较,超过设定的阈值就认为识别到。       本文基于虹软免费人脸识别SDK,从IPC提供的RTSP视频流抓帧进行人脸识别。主要技术方案是通过JavaCV定时抓取视频帧保存为图像,然后针对图像通过虹软SDK提取特征,同特征库里面的人脸进行比较,超过设定的阈值就认为识别到。

2 项目环境 介绍项目中主要使用到的开发库及开发工具。

  • 虹软人脸识别SDK。提供人脸识别相关开发接口。本文使用Windows X64 Java版本,ArcSoft_ArcFace_Java_Windows_x64_V3.0。
  • 下载地址:虹软官网开发者中心( https://ai.arcsoft.com.cn)

  • JavaCV。是一款基于JavaCPP调用方式(JNI的一层封装),提供了在计算机视觉领域的封装库,封装了包含FFmpeg、OpenCV、tensorflow、caffe、tesseract、libdc1394、OpenKinect、videoInput和ARToolKitPlus等在内的计算机视觉领域的常用库和实用程序类。本文使用javacv-platform-1.5.1-bin版本。
  • 下载地址:github( https://github.com/bytedeco/javacv)也可以通过Maven的方式下载必要的jar包。

  • Eclipse。一个开放源代码的、基于Java的可扩展开发平台。用于Java项目的工程化组织。本文使用Oxygen Release (4.7.0)。
  • 下载地址:Eclipse官网( https://www.eclipse.org/downloads/)

  • JDK。提供Java开发环境。本文使用jdk-8u181-windows-x64版本。
  • 下载地址:Oracle官网( https://www.oracle.com/java/)

    3 整体流程

    整体流程包括各种初始化,启动RTSP视频流监测线程,启动人脸识别任务,如下图所示: 在这里插入图片描述 4 工程概况

    创建一个常规的Java项目,引入必要的第三方jar包。

  • 引入虹软人脸识别jar包。
  • arcsoft-sdk-face-3.0.0.0.jar

  • 引入JavaCV必要的jar包。
  • artoolkitplus.jar

    ffmpeg.jar

    ffmpeg-windows-x86_64.jar

    flandmark.jar

    flycapture.jar

    javacpp.jar

    javacv.jar

    leptonica.jar

    libdc1394.jar

    libfreenect.jar

    libfreenect2.jar

    librealsense.jar

    openblas.jar

    opencv.jar

    tesseract.jar

    videoinput.jar

  • 引入log4j相关jar包。
  • slf4j-api-1.7.25.jar

    slf4j-log4j12-1.7.25.jar

    log4j-1.2.17.jar

    Java工程结构如下图所示:

    运行的时候,需要将虹软SDK核心DLL拷到jar包所在目录。

    5 效果展示 工程以常规java项目运行,通过日志观察识别效果。打印识比对分值和人脸库的文件名。如下图所示:

    6 核心代码说明

    6.1 配置文件

    #人脸识别相关参数

    config.FaceAppId = 3D9hF3f4uNxgDGRkRr9PD6P7CbuSC1GrPe5dBnxxxxx

    config.FaceSdkKey = 2aSheKNE4aMokrkRmn5qJ7kvPirhZM7YpDLx

    config.FaceThreshold = 0.75

    #人脸库图片所在路径

    config.FaceLibPath = d:/facelib/

    #rtsp视频流地址

    config.RtspUrl = rtsp://192.168.0.100:554/live/camera

    #执行任务的线程数量

    config.ThreadNum = 16

    AppId和SdkKey根据虹软开发者中心实际应用情况配置。配置项通过ConfigMgr类加载。

    6.2 虹软人脸识别接口封装类

    主要对核心方法进行封装,包括初始化、特征提取、特征比对,是对虹软SDK提供的接口进行封装。

    初始化引擎代码:

    public static boolean init(String _sAppID, String _sSdkKey)
           m_oFaceEngine = new FaceEngine();
           // 引擎激活
           int iFaceActiveCode = m_oFaceEngine.activeOnline(_sAppID, _sSdkKey);
           if (iFaceActiveCode != ErrorInfo.MOK.getValue() &&
                         iFaceActiveCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue())
               logger.error("人脸识别引擎在线激活失败!({})", iFaceActiveCode);
               return false;
           // 引擎配置
           EngineConfiguration oEngineConfiguration = new EngineConfiguration();
           oEngineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
           oEngineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_0_ONLY);
           // 功能配置
           FunctionConfiguration oFunctionConfiguration = new FunctionConfiguration();
           oFunctionConfiguration.setSupportFaceDetect(true);
           oFunctionConfiguration.setSupportFaceRecognition(true);
           oFunctionConfiguration.setSupportAge(false);
           oFunctionConfiguration.setSupportGender(false);
           oEngineConfiguration.setFunctionConfiguration(oFunctionConfiguration);
           // 初始化引擎
           int iFaceInitCode = m_oFaceEngine.init(oEngineConfiguration);
           if (iFaceInitCode != ErrorInfo.MOK.getValue())
                  logger.error("人脸识别引擎初始化失败!({})", iFaceInitCode);
                  return false;
        return true;
    
      提取特征代码:
    public static FaceFeature getFaceFeature(byte[] _abyImageData)
               ImageInfo oImageInfo = ImageFactory.getRGBData(_abyImageData);
               List<FaceInfo> lstFaceInfo = new ArrayList<FaceInfo>();
               int iCode = m_oFaceEngine.detectFaces(oImageInfo.getImageData(), oImageInfo.getWidth(), oImageInfo.getHeight(), ImageFormat.CP_PAF_BGR24, lstFaceInfo);
               if (iCode != ErrorInfo.MOK.getValue())
                   logger.error("检测人脸失败({})", iCode);
                   return null;
               if (lstFaceInfo.isEmpty())
                   logger.error("检测人脸为空({})", iCode);
                   return null;
               FaceFeature oFaceFeature = new FaceFeature();
               iCode = m_oFaceEngine.extractFaceFeature(oImageInfo.getImageData(), oImageInfo.getWidth(), oImageInfo.getHeight(), ImageFormat.CP_PAF_BGR24, lstFaceInfo.get(0), oFaceFeature);
               if (iCode != ErrorInfo.MOK.getValue())
                      logger.error("提取人脸特征失败({})", iCode);
                      return null;
               return oFaceFeature;
           catch (Exception e)
                  logger.error(e.getMessage());
                  return null;
           特征比对代码:
    public static float compare(FaceFeature _oFaceFeature1, FaceFeature _oFaceFeature2)
           float fSimilarity = 0.0f;
               FaceSimilar oFaceSimilar = new FaceSimilar();
               int iCode = m_oFaceEngine.compareFaceFeature(_oFaceFeature1, _oFaceFeature2, oFaceSimilar);
               if (iCode != ErrorInfo.MOK.getValue())
                      logger.error("人脸比对失败({})", iCode);
                      return fSimilarity;
               fSimilarity = oFaceSimilar.getScore();
           catch (Exception e)
                  logger.error(e.getMessage());
           return fSimilarity;
    

    6.3 任务调度封装类

         主要是通过JDK提供的线程池ScheduledExecutorService对程序中任务执行进行调度。

          主要代码如下:
    
    private ScheduledExecutorService svc;
    private boolean init;
    private TaskMgr()
    svc = null;
        init = false;
     * 初始化
    public void init(int _iThreadNum)
    svc = Executors.newScheduledThreadPool(_iThreadNum);
        init = true;
    public void destroy()
    if (init)
               svc.shutdown();
    * 增加一个任务
    * @param _task 任务对象,实现Runnable接口
    public void pushTask(Runnable _task)
    svc.schedule(_task, 0, TimeUnit.MILLISECONDS);
    

    6.4 人脸库管理封装类

    加载指定目录下的图片,提取特征保存到内存中形成人脸库,供1:N识别时进行遍历。

    初始化代码:

    public void init(String _faceLibPath)
    File fileDir = new File(_faceLibPath);
    if (fileDir.exists() && fileDir.isDirectory())
          String[] children = fileDir.list();
          for (int i = 0; i < children.length; i++)
    File fileImage = new File(fileDir, children[i]);
    FaceFeature faceFeature = ArcfaceApi.getFaceFeature(fileImage);
          if (faceFeature != null)
    myFaceFeatureList.add(new MyFaceFeature(children[i], faceFeature));
    logger.info("face lib size:{}", myFaceFeatureList.size());
    

    6.5 RTSP视频流抓帧线程类

    该线程启动时一直运行,通过JavaCV定时抓帧,得到的图片启动一个任务提交到线程池,调用人脸库管理封装类进行识别。

    BufferedImage bi = java2DFrameConverter.getBufferedImage(frame); byte[] bytes = imageToBytes(bi, "jpg"); if (bytes != null && bytes.length > 0) // 人脸检测 TaskMgr.getInstance().pushTask(new FrameHandleTask(bytes)); catch (Exception e) logger.error(e.getMessage()); if (grabber != null) grabber.stop(); catch (FrameGrabber.Exception ex) logger.error("grabber stop exception: " + ex.getMessage()); finally grabber = null; Thread.sleep(100); catch (InterruptedException e) logger.error(e.getMessage());

    6.6 工程启动

       在Main方法中进行初始化,并启动线程。
    
    public class ArcfaceRtspDemo
    private final static Logger logger = LoggerFactory.getLogger(ArcfaceRtspDemo.class);
           public static void main(String[] args)
           // 加载配置文件
           ConfigMgr.getInstance().init();
           // 任务初始化
           TaskMgr.getInstance().init(ConfigMgr.getInstance().getThreadNum());
           // 人脸初始化
           boolean bRet = ArcfaceApi.init(ConfigMgr.getInstance().getFaceAppId(), ConfigMgr.getInstance().getFaceSdkKey());
           if (bRet)
             logger.info("Init Face success");
            MyFaceMgr.getInstance().init(ConfigMgr.getInstance().getFaceLibPath());
                  logger.error("Init Face error");
           RtspFrameGrabberThread thread = new RtspFrameGrabberThread(ConfigMgr.getInstance().getRtspUrl());
           thread.start();
     

    本文所介绍的方法,只是提供可行性验证,说明可以通过抓取RTSP视频帧调用虹软SDK进行人脸识别。可以作为商业项目的参考。在实际项目中,可以通过对相关参数的调整达到更好的性能。

    8 源码下载

    源码包含了完整的第三方库,所以比较大,上传到百度网盘提供下载。

    链接:https://pan.baidu.com/s/1f3crf1x_2jq8uMm9DqVcZg

    提取码:78jd

    了解更多人脸识别产品相关内容请到虹软视觉开放平台