大家应该都知道几个很常见的例子,比如在张学友的演唱会,在安检通道检票时,通过人像识别系统成功识别捉了好多在逃人员,被称为逃犯克星;人行横道不遵守交通规则闯红灯的路人被人脸识别系统抓拍放在大屏上以示警告;参加某次活动通过人脸进行签到来统计实时人流量等等, 我现在也来做一个通过电视直播,追踪画面中所有人脸信息,并捕获我需要的目标人物。

具体思路及流程

基于虹软人脸识别,对直播画面中的每一帧图片进行检测,得到图片中所有人脸信息。可以添加目标人物的照片,用目标人物的人脸特征值与直播画面帧图片中人脸信息列表中的每一个特征值进行比对。如果有匹配到目标人物,把直播画面抓拍。具体流程如下:

项目结构

播放地址我们可以在网上搜索一下电视直播RTMP地址,在程序中可进行播放

private void PlayVideo()
{videoCapture = new VideoCapture(rtmp);if (videoCapture.IsOpened()){videoInfo.Filename = rtmp;videoInfo.Width = (int)videoCapture.FrameWidth;videoInfo.Height = (int)videoCapture.FrameHeight;videoInfo.Fps = (int)videoCapture.Fps;myTimer.Interval = videoInfo.Fps == 0 ? 300 : 1000 / videoInfo.Fps;IsStartPlay = true;myTimer.Start();}else{MessageBox.Show("视频源异常");}
}private void MyTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{try{if (IsStartPlay){lock (LockHelper){var frame = videoCapture.RetrieveMat();if (frame != null){if (frame.Width == videoInfo.Width && frame.Height == videoInfo.Height)this.SetVideoCapture(frame);elseLogHelper.Log($"bad frame");}}}}catch(Exception ex){LogHelper.Log(ex.Message);}
}
Bitmap btm = null;
private void SetVideoCapture(Mat frame)//视频捕获
{try{btm = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(frame);pic_Video.Image = btm;}catch(Exception ex){LogHelper.Log(ex.Message);}
}

以上这些就是在OpenCv中通过VideoCaptrue类对视频进行读取操作,然后把图像渲染到PictureBox控件上。在PictureBox的Paint事件中进行人脸识别与比对操作。

/// <summary>
/// 比对函数,将每一帧抓拍的照片和目标人物照片进行比对
/// </summary>
/// <param name="bitmap"></param>
/// <param name="e"></param>
/// <returns></returns>
private void CompareImgWithIDImg(Bitmap bitmap, PaintEventArgs e)
{if (bitmap != null){//保证只检测一帧,防止页面卡顿以及出现其他内存被占用情况if (isLock == false){isLock = true;Graphics g = e.Graphics;float offsetX = (pic_Video.Width * 1f / bitmap.Width);float offsetY = (pic_Video.Height * 1f / bitmap.Height);//根据Bitmap 获取人脸信息列表List<FaceInfoModel> list = FaceUtil.GetFaceInfos(pImageEngine, bitmap);foreach (FaceInfoModel sface in list){//异步处理提取特征值和比对,不然页面会比较卡ThreadPool.QueueUserWorkItem(new WaitCallback(delegate{try{//提取人脸特征float similarity = CompareTwoFeatures(sface.feature, imageTemp);if (similarity > threshold){this.pic_cutImg.Image = bitmap;this.Invoke((Action)(() =>{this.lbl_simiValue.Text = similarity.ToString();}));}}catch (Exception ex){Console.WriteLine(ex.Message);}}));MRECT rect = sface.faceRect;float x = rect.left * offsetX;float width = rect.right * offsetX - x;float y = rect.top * offsetY;float height = rect.bottom * offsetY - y;//根据Rect进行画框g.DrawRectangle(pen, x, y, width, height);trackUnit.message = "年龄:" + sface.age.ToString() + "\r\n" + "性别:" + (sface.gender == 0 ? "男" : "女");g.DrawString(trackUnit.message, font, brush, x, y + 5);}isLock = false;}}
}

单张图片可能包含多张人脸,我们用FaceInfoModel 人脸信息实体类,把人脸信息放在此类中。

public class FaceInfoModel
{/// <summary>/// 年龄/// </summary>public int age { get; set; }/// <summary>/// 性别/// </summary>public int gender { get; set; }public ASF_Face3DAngle face3dAngle { get; set; }/// <summary>/// 人脸框/// </summary>public MRECT faceRect { get; set; }/// <summary>/// 人脸角度/// </summary>public int faceOrient { get; set; }/// <summary>/// 单人脸特征/// </summary>public IntPtr feature { get; set; }
}

多人脸实体类存放单人脸信息列表

public class MultiFaceModel : IDisposable
{/// <summary>/// 多人脸信息/// </summary>public ASF_MultiFaceInfo MultiFaceInfo { get; private set; }/// <summary>/// 单人脸信息List/// </summary>public List<ASF_SingleFaceInfo> FaceInfoList { get; private set; }/// <summary>/// 人脸信息列表/// </summary>/// <param name="multiFaceInfo"></param>public MultiFaceModel(ASF_MultiFaceInfo multiFaceInfo) {this.MultiFaceInfo = multiFaceInfo;this.FaceInfoList = new List<ASF_SingleFaceInfo>();FaceInfoList = PtrToMultiFaceArray(multiFaceInfo.faceRects, multiFaceInfo.faceOrients, multiFaceInfo.faceNum);}/// <summary>/// 指针转多人脸列表/// </summary>/// <param name="faceRect"></param>/// <param name="faceOrient"></param>/// <param name="length"></param>/// <returns></returns>private List<ASF_SingleFaceInfo> PtrToMultiFaceArray(IntPtr faceRect, IntPtr faceOrient, int length){List<ASF_SingleFaceInfo> FaceInfoList = new List<ASF_SingleFaceInfo>();var size = Marshal.SizeOf(typeof(int));var sizer = Marshal.SizeOf(typeof(MRECT));for (var i = 0; i < length; i++){ASF_SingleFaceInfo faceInfo = new ASF_SingleFaceInfo();MRECT rect = new MRECT();var iPtr = new IntPtr(faceRect.ToInt32() + i * sizer);rect = (MRECT)Marshal.PtrToStructure(iPtr, typeof(MRECT));faceInfo.faceRect = rect;int orient = 0;iPtr = new IntPtr(faceOrient.ToInt32() + i * size);orient = (int)Marshal.PtrToStructure(iPtr, typeof(int));faceInfo.faceOrient = orient;FaceInfoList.Add(faceInfo);}return FaceInfoList;}public void Dispose(){Marshal.FreeCoTaskMem(MultiFaceInfo.faceRects);Marshal.FreeCoTaskMem(MultiFaceInfo.faceOrients);}
}

然后获取所有人脸信息,放在列表中备用

/// <summary>
/// 获取人脸信息列表
/// </summary>
/// <param name="pEngine"></param>
/// <param name="bitmap"></param>
/// <returns></returns>
public static List<FaceInfoModel>GetFaceInfos(IntPtr pEngine,Image bitmap)
{List<FaceInfoModel> listRet = new List<FaceInfoModel>();try{List<int> AgeList = new List<int>();List<int> GenderList = new List<int>();//检测人脸,得到Rect框ASF_MultiFaceInfo multiFaceInfo = FaceUtil.DetectFace(pEngine, bitmap);MultiFaceModel multiFaceModel = new MultiFaceModel(multiFaceInfo);//人脸信息处理ImageInfo imageInfo = ImageUtil.ReadBMP(bitmap);int retCode = ASFFunctions.ASFProcess(pEngine, imageInfo.width, imageInfo.height, imageInfo.format, imageInfo.imgData, ref multiFaceInfo, FaceEngineMask.ASF_AGE| FaceEngineMask.ASF_GENDER);//获取年龄信息ASF_AgeInfo ageInfo = new ASF_AgeInfo();retCode = ASFFunctions.ASFGetAge(pEngine, ref ageInfo);AgeList = ageInfo.PtrToAgeArray(ageInfo.ageArray, ageInfo.num);//获取性别信息ASF_GenderInfo genderInfo = new ASF_GenderInfo();retCode = ASFFunctions.ASFGetGender(pEngine, ref genderInfo);GenderList = genderInfo.PtrToGenderArray(genderInfo.genderArray, genderInfo.num);for (int i = 0; i < multiFaceInfo.faceNum; i++){FaceInfoModel faceInfo = new FaceInfoModel();faceInfo.age = AgeList[i];faceInfo.gender = GenderList[i];faceInfo.faceRect = multiFaceModel.FaceInfoList[i].faceRect;faceInfo.feature = ExtractFeature(pEngine, bitmap, multiFaceModel.FaceInfoList[i]);//提取单人脸特征faceInfo.faceOrient = multiFaceModel.FaceInfoList[i].faceOrient;listRet.Add(faceInfo);}return listRet;//返回多人脸信息}catch {return listRet;}
}

从列表中获取到的多张人脸,在人脸上画框作出标识,也可以把提取的人脸信息,年龄、性别作出展示。接下来就是选择一张目标人物的照片,通过SDK提取目标人物的人脸特征值作为比较对象,逐一与视频中的人脸特征进行比较。如果有判断到相似度匹配的人脸,则把视频帧图像呈现出来。

/// <summary>
/// 比较两个特征值的相似度,返回相似度
/// </summary>
/// <param name="feature1"></param>
/// <param name="feature2"></param>
/// <returns></returns>
private float CompareTwoFeatures(IntPtr feature1, IntPtr feature2)
{float similarity = 0.0f;//调用人脸匹配方法,进行匹配ASFFunctions.ASFFaceFeatureCompare(pImageEngine, feature1, feature2, ref similarity);return similarity;
}

之前只实现了从多张人脸中获取一张最大尺寸的人脸作为比较对象,这样视频中也就只能对一张人脸进行画框标记了,现在是把所有提取到的人脸均进行标记,并把各自特征值存在列表中,以便与目标人脸特征值进行匹配。

这样也就粗略的实现了人脸识别追踪,并对目标人物进行抓拍的功能了。

GitHub源码已上传:https://github.com/yumaster/FaceTracking

基于虹软人脸识别,实现RTMP直播推流追踪视频中所有人脸信息(C#)相关推荐

  1. 基于GPUImage的多滤镜rtmp直播推流

    之前做过开源videocore的推流改进:1)加入了美颜滤镜; 2) 加入了librtmp替换原来过于简单的rtmpclient: 后来听朋友说,在videocore上面进行opengl修改,加入新的 ...

  2. 人脸识别之三检测视频流(摄像头)中的人脸

    完整人脸识别系统(源码+教程+环境): 开源毕业设计:基于嵌入式ARM-Linux的应用OpenCV和QT实现的人脸识别系统(源码+论文) 完全毕设教程:Linux上Opencv与Qt实现的人脸识别的 ...

  3. OpenCV视频中的人脸标志检测

    OpenCV视频中的人脸标志检测 视频中的人脸标志检测 简介 命令参数说明 源代码 视频中的人脸标志检测 简介 此应用程序使您可以检测视频中检测到的面部的地标.此应用程序首先检测当前视频帧中的面部,然 ...

  4. 魔坊APP项目-26-直播、docker安装OSSRS流媒体直播服务器、基于APICloud的acLive直播推流模块实现RTMP直播推流、直播流管理

    一.docker安装OSSRS流媒体直播服务器 在外界开发中, 如果要实现直播功能.常用的方式有: 1. 通过第三方接口来实现.可以申请阿里云,腾讯云,网易云,七牛云的直播接口,根据文档,下载集成SD ...

  5. windows下ffmpeg+nginx-rtmp环境搭建及opencv+ffmpeg+python实现拉流和rtmp直播推流

    由于工作需要最近在研究rtsp拉流与直播推流的问题,目前先在我本机上进行了实验,本博客记录学习的内容,包含windows下ffmpeg.nginx-rtmp环境搭建及opencv+ffmpeg+pyt ...

  6. 用安卓RTMP直播推流进行音频侦听时,出现播放几秒后就无法播放问题的解决方法

    Real Time Messaging Protocol(RTMP)即实时消息传输协议,是 Adobe 公司开发的一个基于 TCP 的应用层协议,目前国内的视频云服务都是以 RTMP 为主要推流协议. ...

  7. 【Android RTMP】RTMP 直播推流阶段总结 ( 服务器端搭建 | Android 手机端编码推流 | 电脑端观看直播 | 服务器状态查看 )

    文章目录 安卓直播推流专栏博客总结 一. 服务器搭建 二. 手机端推流 三. 电脑端观看直播 四. RTMP 服务器端状态 安卓直播推流专栏博客总结 Android RTMP 直播推流技术专栏 : 0 ...

  8. 【Android RTMP】RTMP 直播推流服务器搭建 ( Ubuntu 18.04.4 虚拟机 )

    文章目录 安卓直播推流专栏博客总结 一. Android RTMP 直播推流简介 二. Nginx.RTMP Module 编译环境源码准备 三. pcre.OpenSSL.zlib 函数库安装 四. ...

  9. 本系列介绍了rtmp直播推流全过程(已完结)

    本系列介绍了rtmp直播推流全过程 完整项目地址 (已完结) 以下文章是针对每一个情况,介绍音视频相关知识,以及实现的原理,总共分五章: 第一章:直播推流全过程:视频数据源之YUV(1) RGB或YU ...

最新文章

  1. mysql5.5.42指定数据库同步操作
  2. python使用方法视频-Python读取视频的两种方法(imageio和cv2)
  3. Maven学习-使用Nexus搭建Maven私服
  4. python 图片识别_python识别图片文字
  5. CentOS7安装Hadoop2.7完整流程
  6. docker中使用Mysql8+phpmyadmin
  7. VS2010 + OpenCV2.3配置 ; 在VS2010下安装配置OpenCV2.3 ; 全程截图,绝对能配置好,不能的留言!...
  8. 代码-JS之淡入淡出背景自动切换
  9. 迷你屏+OLED好屏:个性专业两手抓 华硕灵耀X 14专业好屏体验
  10. linux usb 从芯片,新人求教,怎么烧录Linux系统到一个小芯片上?
  11. OpenBSD 6.8 切换到国内镜像源的一种临时方法:声明PKG_PATH
  12. 鼠标划动网页或者窗口时进度条总是上下乱跳,有可能是你的上下按键坏掉了
  13. AngularJS 的 IE 兼容性
  14. 中文名字和英文名字正则匹配
  15. android中的长度单位介绍(dp,sp,px,in,pt,mm)
  16. 行为识别(CVPR2020南京大学腾讯) ~ TEA论文笔记 ~《TEA: Temporal Excitation and Aggregation for Action Recognition》
  17. 【Scapy】获取流量包【原创】
  18. 车载通信——CAN收发器选型(低功耗)
  19. windows中显示文件后缀名
  20. java线程高并发编程

热门文章

  1. 昆山万象汇机器人_昆山十镇,在售新盘汇总
  2. MFC项目实战(1)文件管理器--准备篇
  3. 在FC中如何获取fcdot文件
  4. JVM-并发-Java 内存模型
  5. 6 四大组件之Service
  6. 用POP动画引擎实现弹簧动画(POPSpringAnimation)
  7. python 字典操作
  8. GDB调试多进程|多线程程序
  9. 把我的爱送给你――C#3.5(这题目似乎写错了)
  10. 视频翻录_将DVD解密并复制到硬盘驱动器而无需翻录