directshow、 Emgucv入门
时间:2022-04-22
本文章向大家介绍directshow、 Emgucv入门,主要内容包括一、directshow的介绍、2. 初始化directshow相关的接口、3. 找到摄像头设备、4. 增加摄像头、视频处理过滤器、5. 设置摄像头显示参数、预览参数、 设置保存的尺寸信息、6. 绑定以pictruebox控件上,以及运行、二、emgucv的介绍、2. 打开摄像头、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
本示例主要测试了directshow、Emgucv的视频流采集功能,其中Emgucv还实现了人脸的识别。示例源码下载
一、directshow的介绍
实现原理:directshow可以将摄像头的数据流以事件的方式实时传递给程序,程序在此事件中拿到流后可以保存为图片(流可以经过多个filterGraph2对象)。directshow提供将数据绑定到picturebox控件上。以下为打开一个摄像头的步骤:
1. 引入directshow.net控件
此控件可以在网上搜索,即好下载,名称为DirectShowLib-2005,它是directshow的.net版本的封装.
2. 初始化directshow相关的接口
代码如下:
int hr = 0;
this.filterGraph2 = (IFilterGraph2)new FilterGraph();
this.captureGraphBuilder2 = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
this.mediaControl = (IMediaControl)this.filterGraph2;
this.videoWindow = (IVideoWindow)this.filterGraph2;
DsError.ThrowExceptionForHR(hr);
说明:
- filterGraph2:流过滤器
- captureGraphBuilder2:视频设备处理
- mediaControl:视频控制,如:开启或关闭等
- videoWidow:视频显示在窗体上的一些信息设置类
- filterGraph2会被附加到captureGraphBuilder2对象.
3. 找到摄像头设备
int hr = 0;
IEnumMoniker classEnum = null;
IMoniker[] moniker = new IMoniker[1];
object source = null;
ICreateDevEnum devEnum = (ICreateDevEnum)new CreateDevEnum();
hr = devEnum.CreateClassEnumerator(FilterCategory.VideoInputDevice, out classEnum, 0);
DsError.ThrowExceptionForHR(hr);
Marshal.ReleaseComObject(devEnum);
if (classEnum == null)
throw new Exception("classEnum is null");
if (classEnum.Next(moniker.Length, moniker, IntPtr.Zero) == 0)
{
Guid iid = typeof(IBaseFilter).GUID;
moniker[0].BindToObject(null, null, ref iid, out source); //moniker绑定以 ibasefilter和object上
}
Marshal.ReleaseComObject(moniker[0]);
Marshal.ReleaseComObject(classEnum);
return (IBaseFilter)source;
找到视频摄像头,将转换为一个IBaseFilter对象。
4. 增加摄像头、视频处理过滤器
将IBaseFilter对象加入到filterGraph2对象上,作为第一层视频的过滤,后面会放到picturebox控件上。然后再加入SampleGrabber对象,用于捕获每一帧的视频数据。
5. 设置摄像头显示参数、预览参数、 设置保存的尺寸信息
此步代码较多,就不在贴代码,后面给出源码下载地址.
6. 绑定以pictruebox控件上,以及运行
int hr = 0;
hr = this.videoWindow.put_Owner(this.pictureBox.Handle);
DsError.ThrowExceptionForHR(hr);
hr = this.videoWindow.put_WindowStyle(WindowStyle.Child);
DsError.ThrowExceptionForHR(hr);
hr = this.videoWindow.put_Visible(OABool.True);
DsError.ThrowExceptionForHR(hr);
System.Drawing.Rectangle rc = this.pictureBox.ClientRectangle;
hr = this.videoWindow.SetWindowPosition(0, 0, 640, 480);
DsError.ThrowExceptionForHR(hr);
二、emgucv的介绍
emgucv是opencv的.net版本封装,并且opencv获取视频流的方式也是采用的directshow。由于进行了封装,打开和识别人像就极为简单了。
1. 下载emgucv并安装,然后在系统环境变量中添加其安装路径.
至此,还需复制相关的dll到开发项目中:
2. 打开摄像头
private VideoCapture capture;
private Mat mat;
private Common.DetectFace detectFace;
public Form1()
{
InitializeComponent();
CvInvoke.UseOpenCL = false;
detectFace = new Common.DetectFace();
}
private void Form1_Load(object sender, EventArgs e)
{
capture = new Emgu.CV.VideoCapture();
capture.ImageGrabbed += Capture_ImageGrabbed;
capture.Start();
}
private void Capture_ImageGrabbed(object sender, EventArgs e)
{
if (capture != null && capture.Ptr != IntPtr.Zero)
{
mat = new Mat();
capture.Retrieve(mat, 0);
var ls = detectFace.Detect(mat);
foreach(var face in ls)
{
CvInvoke.Rectangle(mat, face, new Bgr(Color.Red).MCvScalar, 2);
}
imageBox1.Image = mat;
}
}
说明:
- Capture_ImageGrabbed捕获到的就是实时的视频流,在此处就可以做相关的处理。
- 此处加入了对人脸的识别,并用红框表示出来。
- 【Go 语言社区】Go语言条件变量的两个例子
- mysqlimport导入报错的排查(r10笔记第58天)
- 【Go 语言社区】POJ 1047 Round and Round We Go 循环数新解
- 【Go 语言社区】删除redis所有KEY
- 【Go 语言社区】Golang 动态实例化结构体
- 【Go 语言社区】Go 错误处理
- 【Go 语言社区】Go 语言范围(Range)
- 【Go 语言社区】JS 相关---Window Location
- 【Go 语言社区】Go 语言Map(集合)
- 【Go 语言社区】JavaScript Date(日期)对象
- UWP基础教程 - XAML类型转换器
- Oracle 12c Data Guard搭建(一) (r10笔记第57天)
- 【Go 语言社区】Go语言 Cookie的使用
- 【Go 语言社区】HTML5 Geolocation(地理定位)-转
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 使用OPCache提升PHP的性能
- 克隆图
- LeetCode 03无重复字符的最长子串(滑动窗口)
- elasticSearch学习(五)
- MySQL进阶:索引与优化
- CentOS7搭建Zabbix4.2系统
- vue项目更换favicon.ico
- 一种O(n)的排序——计数排序引发的围观风波
- LeetCode 04寻找两个正序数组的中位数(困难)二分法
- Java程序员面试必备:Volatile全方位解析
- HTTP协议基础及发展历史
- Vi 和 Vim 的使用
- k8s删除Terminating状态的命名空间
- CentOS7下vsftpd over SSL/TLS加密传输配置实践
- Xargs Sh -c Skipping the First Argument