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

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

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

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

2 项目环境

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

1) 虹软人脸识别SDK。提供人脸识别相关开发接口。本文使用Windows X64 Java版本,ArcSoft_ArcFace_Java_Windows_x64_V3.0。

下载地址:虹软官网开发者中心( https://ai.arcsoft.com.cn )。

2) 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包。

3) Eclipse。一个开放源代码的、基于Java的可扩展开发平台。用于Java项目的工程化组织。本文使用Oxygen Release (4.7.0)。

下载地址:Eclipse官网( https://www.eclipse.org/downloads/

4) JDK。提供Java开发环境。本文使用jdk-8u181-windows-x64版本。

下载地址:Oracle官网( https://www.oracle.com/java/

3 整体流程

整体流程包括各种初始化,启动RTSP视频流监测线程,启动人脸识别任务,如下图所示:

4 工程概况

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

1)    引入虹软人脸识别jar包。

#人脸识别相关参数

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

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 ;

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;

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 );

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());

grabber = FFmpegFrameGrabber . createDefault (rtspUrl);

grabber.setFrameRate(frameRate);

grabber.setVideoBitrate(bitRate);

grabber.setImageWidth(frameWidth);

grabber.setImageHeight(frameHeight);

grabber.start();

catch ( Exception e)

logger .error(e.getMessage());

private void startGrabber()

Java2DFrameConverter java2DFrameConverter = new Java2DFrameConverter ();

while ( true )

if (grabber == null )

logger .info("连接rtsp:" + rtspUrl + ",开始创建grabber");

createGrabber();

Frame frame = grabber.grabImage();

if (frame != null )

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());

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();

7 结论

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

8 源码下载

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