基于虹软人脸识别,实现RTMP直播推流追踪视频中所有人脸信息(C#)
前言
大家应该都知道几个很常见的例子,比如在张学友的演唱会,在安检通道检票时,通过人像识别系统成功识别捉了好多在逃人员,被称为逃犯克星;人行横道不遵守交通规则闯红灯的路人被人脸识别系统抓拍放在大屏上以示警告;参加某次活动通过人脸进行签到来统计实时人流量等等, 我现在也来做一个通过电视直播,追踪画面中所有人脸信息,并捕获我需要的目标人物。
具体思路及流程
基于虹软人脸识别,对直播画面中的每一帧图片进行检测,得到图片中所有人脸信息。可以添加目标人物的照片,用目标人物的人脸特征值与直播画面帧图片中人脸信息列表中的每一个特征值进行比对。如果有匹配到目标人物,把直播画面抓拍。具体流程如下:
项目结构
播放地址我们可以在网上搜索一下电视直播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);
else
LogHelper.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;
}
之前只实现了从多张人脸中获取一张最大尺寸的人脸作为比较对象,这样视频中也就只能对一张人脸进行画框标记了,现在是把所有提取到的人脸均进行标记,并把各自特征值存在列表中,以便与目标人脸特征值进行匹配。
这样也就粗略的实现了人脸识别追踪,并对目标人物进行抓拍的功能了。
基于虹软人脸识别,实现RTMP直播推流追踪视频中所有人脸信息(C#)的更多相关文章
- 基于GPUImage的多滤镜rtmp直播推流
之前做过开源videocore的推流改进:1)加入了美颜滤镜; 2) 加入了librtmp替换原来过于简单的rtmpclient: 后来听朋友说,在videocore上面进行opengl修改,加入新的 ...
- day122:MoFang:OSSRS流媒体直播服务器&基于APICloud的acLive直播推流模块实现RTMP直播推流
目录 1.docker安装OSSRS流媒体直播服务器 2.基于APICloud的acLive直播推流模块实现RTMP直播推流 3.直播流管理 1.docker安装OSSRS流媒体直播服务器 1.OSS ...
- Android流媒体开发之路二:NDK开发Android端RTMP直播推流程序
NDK开发Android端RTMP直播推流程序 经过一番折腾,成功把RTMP直播推流代码,通过NDK交叉编译的方式,移植到了Android下,从而实现了Android端采集摄像头和麦克缝数据,然后进行 ...
- jQuery 人脸识别插件,支持图片和视频
jQuery Face Detection 是一款人脸检测插件,能够检测到图片,视频和画布中的人脸坐标.它跟踪人脸并输出人脸模型的坐标位置为一个数组.我们相信,面部识别技术能够给我们的 Web 应用带 ...
- EasyRTMP+EasyRTSPClient实现的多路(支持断线重连)RTSP转RTMP直播推流工具
本文转自EasyDarwin开源团队成员Kim的博客:http://blog.csdn.net/jinlong0603/article/details/73441405 介绍 EasyRTMP是Eas ...
- 不用任何第三方,写一个RTMP直播推流器
2016年是移动直播爆发年,不到半年的时间内无数移动直播App掀起了全民直播的热潮.然而个人觉得直播的门槛相对较高,从推流端到服务端器到播放端,无不需要专业的技术来支撑,仅仅推流端就有不少需要学习的知 ...
- Python人脸识别最佳教材典范,40行代码搭建人脸识别系统!
Face Id是一款高端的人脸解锁软件,官方称:"在一百万张脸中识别出你的脸."百度.谷歌.腾讯等各大企业都花费数亿来鞭策人工智能的崛起,而实际的人脸识别技术是否有那么神奇? 绿帽 ...
- 简单机器学习人脸识别工具face-recognition python小试,一行代码实现人脸识别
摘要: 1行代码实现人脸识别,1. 首先你需要提供一个文件夹,里面是所有你希望系统认识的人的图片.其中每个人一张图片,图片以人的名字命名.2. 接下来,你需要准备另一个文件夹,里面是你要识别的图片.3 ...
- EasyRTMP结合海康HCNetSDK获取海康摄像机H.264实时流并转化成为RTMP直播推流(附源码)
最近一家深耕于南方电网的科技公司同事找到我们,咨询关于调用海康HCNetSDK取流,并进行互联网转化的方案,经过反复的沟通以及自身在EasyDSS和EasyNVR方面的经验,我们推荐了海康HCNetS ...
随机推荐
- 跨端开发技术 | 拼团商城项目同时开发app和小程序的要点
此项目为拼团商城类型,主要功能包括商品分类.商品详情.商品搜索.拼团.订单管理等. 项目源码在 https://github.com/apicloudcom/group-ec 仓库的 widget 目 ...
- 攻防世界 reverse Newbie_calculations
Newbie_calculations Hack-you-2014 题目名百度翻译成新手计算,那我猜应该是个实现计算器的题目.... IDA打开程序,发现一长串的函数反复调用,而且程序没有输入,只有输 ...
- Python的多进程和多线程
进程和线程 进程是系统进行资源分配的最小单位,线程是系统进行调度执行的最小单位: 一个应用程序至少包含一个进程,一个进程至少包含一个线程: 每个进程在执行过程中拥有独立的内存空间,而一个进程中的线程之 ...
- 手把手教你如何使用Charles抓包
一.为什么使用charles 前几天因为需要通过抓包定位问题,打开了尘封已久的fiddler,结果打开软件后什么也干不了,别说手机抓包了,打开软件什么请求也抓不到. 很多时候都是如此,如果一个方案不行 ...
- 图像Resize方式对深度学习模型效果的影响
在基于卷积神经网络的应用过程中,图像Resize是必不可少的一个步骤.通常原始图像尺寸比较大,比如常见监控摄像机出来的是1080P高清或者720P准高清画面,而网络模型输入一般没有这么大,像Yolo系 ...
- ubuntu系统编译安装OpenCV 4.4
内容转载自我的博客 目录 前言 1. 下载源码 2. 安装各种依赖 3. 开始编译安装 4. 配置C++开发环境 5. 程序执行时加载动态库*.so 6. 测试cpp文件 7. 配置python3的o ...
- 让你的程序炫起来!少有人知道但超酷的 Python 进度条开源库
本文适合有 Python 基础的朋友 本文作者:HelloGitHub-Anthony HelloGitHub 推出的<讲解开源项目>系列,本期介绍让你快速拥有完美进度条的 Python ...
- python 开发环境安装(最全最完整)
一.下载安装包 Windows64 位电脑安装 Python,浏览器的地址栏访问: https://www.python.org/ftp/python/3.7.9/python-3.7.9-amd64 ...
- BUAA_OO_第四单元
一.UML解析器设计 先看下题目:第四单元实现一个基于JDK 8带有效性检查的UML(Unified Modeling Language)类图,顺序图,状态图分析器 MyUmlInteractio ...
- Java(1-24)【前言、入门程序、常量、变量、类型转换】
如何输出规定结果,利用String.format System.out.println(String.format("%.2f", f)); 编译:是指将我们编写的Java源文件翻 ...