在C#中利用ActiveX控件进行视频采集
在VS6.0年代,微软提供了VFW(Video For Window) 这样强大而方便的库来支持视频捕获和回放。但是无论是在。NET v1.0还是在.NET v2.0框架中,都没有提供相应的类库来支持视频捕获和回放。解决这个问题有很多种方法,比如利用平台调用P/Invoke对VFW中的功能函数进行封 装,然后再C#中进行调用。这样效率很低并且太复杂。还可以利用第三方提供的ActiveX控件来实现这个功能,这有什么好处呢?简单!!!!这也就足够 了。并且往往第三方提供的控件功能更强大。但是世界上没有免费的午餐——这种控件往往是要收费的。在这里肯定有的朋友会想到:“不是还可以利用 DX(DirectX)来实现吗,微软也提供了Manager DX托管代码的SDK”。的确,利用DX来实现视频捕获和回放是一个很好的方法,无论从效率还是效果来说都是上上之选。不幸的是:微软虽然提供了D3D、 DirectDraw、DirectSound、DirectPlayer......但是唯独没有我们感兴趣的,可以实现视频捕获的 DirectShow的SDK。据我所知,国外有开源的代码对DirectShow进行了封装,我也用过,个人感觉还不错,有兴趣的朋友可以查找一下这方 面的资料,这里我就不多说了。
言归正传,要利用ActiveX在C#中实现视频捕获,先要做好以下准备工作:
首先是要有VS2003或者VS2005的开发环境,这个我就不多说,相信地球人都知道。
其次是要安装好摄像头的驱动程序,也就是说你在QQ或者MSN视频聊天时能看到你自己摄像头的图像。
然 后是最重要的了:安装支持视频捕获的ActiveX控件!什么控件?Pegasus CapturePro。哪里下载?下载地址:http://www.cncode.com/downinfo/3504.html 这个地址应该是可以下载的,我刚刚又测试了一次。但是我不能保证它一直有效。这个控件是收费的,网上有它的评估版,相信大家也有办法,实在不行,那么给我 发Email吧,我来告诉你怎么办。安装时一直"Next"下去后就可以了。
然后再窗体上放一个Button控件,在该控件的单击事件中添加以下代码:
view plaincopy to clipboardprint?
private void butConnect_Click(object sender, System.EventArgs e)
...{
axCap.Connect (0); // 连接到设备
axCap.Preview = true; // 开始预览
}
private void butConnect_Click(object sender, System.EventArgs e)
...{
axCap.Connect (0); // 连接到设备
axCap.Preview = true; // 开始预览
}
然后编译工程,允许程序,单击按钮应该就可以看到视频图像了。
到这里就表示我们的操作成功了,最基本的功能实现了,这里对上述两行代码进行简单的解释。第一行axCap.Connect(0)表示将控件连接到设备 0。在Windows中,可以同时支持多个视频设备,每个设备都有一个编号。第一个设备编号0,第二个设备编号1,依次类推。由于我的电脑上只连接了一个 视频摄像头,所以视频设备的编号是0。这里也就可以看出Connect()函数的参数实际上就是视频设备的参数,至于怎样来确定视频设备对于得编号,下面 会有详细的说明。第二行axCap.Preview = true;表示打开预览。Preview属性为真时表示在控件上显示视频图像,当然要是该属性为false,我们就看不到视频了。
下面对一些常用的,比较重要的方法和属性进行说明:
怎样确定视频设备的编号:首先利用属性axCap .NumDevices来获取Windows中可用视频设备的数目,然后利用方法axCap .ObtainDeviceName (i)来获取该设备的名称字符串。其中参数i同Connect()函数一样,表示视频设备编号。具体的方法和实现过程可以参考以下代码:
view plaincopy to clipboardprint?
//判断有没用可用的捕获设备
if(axCap .NumDevices <0)
{
//没有找到可用的视频设备则报错,并退出程序
MessageBox.Show ("没有发现可用的设备!","错误",MessageBoxButtons.OK ,MessageBoxIcon.Error );
cobDevice.Items .Add("未发现可用视频设备");
cobDevice.SelectedIndex =0;
}
else
{
//找到则枚举所以设备,并初始化设备组合框
try
{
for(int i=0;i<axCap .NumDevices ;i++)
{
cobDevice.Items .Add (axCap .ObtainDeviceName (i));
}
cobDevice.SelectedIndex =0; //设置默认设备
}
catch
{
MessageBox.Show ("初始化设备失败!","错误",MessageBoxButtons.OK ,MessageBoxIcon.Error );
cobDevice.Items .Add("未发现可用视频设备");
cobDevice.SelectedIndex =0;
}
}
//判断有没用可用的捕获设备
if(axCap .NumDevices <0)
{
//没有找到可用的视频设备则报错,并退出程序
MessageBox.Show ("没有发现可用的设备!","错误",MessageBoxButtons.OK ,MessageBoxIcon.Error );
cobDevice.Items .Add("未发现可用视频设备");
cobDevice.SelectedIndex =0;
}
else
{
//找到则枚举所以设备,并初始化设备组合框
try
{
for(int i=0;i<axCap .NumDevices ;i++)
{
cobDevice.Items .Add (axCap .ObtainDeviceName (i));
}
cobDevice.SelectedIndex =0; //设置默认设备
}
catch
{
MessageBox.Show ("初始化设备失败!","错误",MessageBoxButtons.OK ,MessageBoxIcon.Error );
cobDevice.Items .Add("未发现可用视频设备");
cobDevice.SelectedIndex =0;
}
}
怎样修改摄像头参数:每个摄像头都有很多参数,如亮度、对比度、灰度等。有的摄像还可能提供很多特效效果,比如像框,黑白等。这些参数和效果都可通过调用底层的视频设备属性对话框来修改,具体方法请参考以下代码:
view plaincopy to clipboardprint?
private void butSet_Click(object sender, System.EventArgs e)
{
//调用DrawShow设置对话框
if (axCap .HasFilterPropertyPage (CAPTUREPRO3Lib.FILTERPROPTYPE .FILTERPROP_VIDEO_DEVICE ))
{
axCap .ShowFilterPropertyPage (CAPTUREPRO3Lib.FILTERPROPTYPE .FILTERPROP_VIDEO_DEVICE, "");
}
}
private void butSet_Click(object sender, System.EventArgs e)
{
//调用DrawShow设置对话框
if (axCap .HasFilterPropertyPage (CAPTUREPRO3Lib.FILTERPROPTYPE .FILTERPROP_VIDEO_DEVICE ))
{
axCap .ShowFilterPropertyPage (CAPTUREPRO3Lib.FILTERPROPTYPE .FILTERPROP_VIDEO_DEVICE, "");
}
}
怎样录像:首先要设置录像文件,可以通过axCap.StreamFile属性来设置录像文件路径,该属性指的是录像文件的完整路径。然后可以设置 Preview = true属性来打开预览。然后调用方法axCap.StartCapture ()来开始录像。停止录像很简单只需要调用函数axCap.EndCapture ()就可以了。可以参考以下代码:
view plaincopy to clipboardprint?
private void butStartCap_Click(object sender, System.EventArgs e)
...{
if(saveFile.FileName !="") //如果设置了路径则执行操作 否则报错
...{
if(radCapFarme.Checked ) //执行帧捕获操作
...{
if(!flagCapingFarmes) //如果当前没有执行其它捕获
...{
if(!axCap.Preview ) //打开自动预览
...{
axCap.Visible =true;
axCap.Preview =true;
txtBack.Visible =false;
butCaptureImg.Enabled =true;
butPreview.Text ="停止预览";
}
if(chkAutoSave.Checked )
...{
//如果自动保存为真则设置周期
axCap.Interval =Convert.ToInt32 (txtTime.Text ,10); //先设置自动保存时间
}
axCap.AutoSave =chkAutoSave.Checked; //处理自动保存
axCap.AutoIncrement =chkAutoRename.Checked; //处理自动改文件名
axCap.FrameFile =saveFile.FileName ; //设置保存路径
butStartCap.Text ="停止捕获";
flagCapingFarmes=true; //设置工作进行标志 标志忙
axCap.CaptureFrame (); //开始捕获帧
}
else //如果当前正在进行其它捕获工作
...{
axCap.AutoSave =false; //关自动保存
axCap.Interval =0; //自动保存周期置0
butStartCap.Text ="开始捕获";
flagCapingFarmes=false; //置工作空闲标志
DisConnect(); //断开连接 关闭捕获
}
}
else //执行流捕获
...{
if(!flagCapingStream )
...{
axCap.VideoCompressorIndex =cobVicomp.SelectedIndex ;
axCap.AudioDeviceIndex =comAudioDevice.SelectedIndex ;
axCap.AudioCompressorIndex =comAudioComp.SelectedIndex ;
axCap.StreamFile =saveFile.FileName ;
butStartCap.Text ="停止捕获";
flagCapingStream=true;
if(!axCap.Preview ) //打开自动预览
...{
axCap.Visible =true;
axCap.Preview =true;
txtBack.Visible =false;
butCaptureImg.Enabled =true;
butPreview.Text ="停止预览";
}
try
...{
axCap.StartCapture ();
}
catch
...{
MessageBox.Show ("视频编码器不可用,请重新连接设备");
cobVicomp.Items.Clear ();
butStartCap.Text ="开始捕获";
flagCapingStream=false;
axCap.Preview =false;
mnuDisableLink.Enabled =false;
mnuLink.Enabled =true;
cobColor.Enabled =false;
cobPix.Enabled =false;
cobColor.Text =null;
cobColor.Items.Clear ();
cobPix.Text =null;
cobPix.Items .Clear ();
txtBack.Visible =true;
chkAdvCap.Enabled =false;
butPreview.Enabled =false;
butSet.Enabled =false;
butDeviceSet.Enabled =false;
butVideoFormat.Enabled =false;
butCaptureImg.Enabled =false;
chkData.Enabled =false;
chkTime.Enabled =false;
txtLable.Enabled =false;
butPreview.Text ="开始预览";
butLink.Text ="连接设备";
if(chkAdvCap.Checked )
chkAdvCap.CheckState =CheckState.Unchecked ;
visableControl(false,3);
}
}
else
...{
if(axCap.Preview )
...{
axCap.Preview =false;
axCap.Visible =false;
txtBack.Visible =true;
butCaptureImg.Enabled =false;
butPreview.Text ="开始预览";
}
butStartCap.Text ="开始捕获";
flagCapingStream=false;
axCap.EndCapture ();
}
}
}
else
...{
MessageBox.Show ("请先设置要存储的文件!","错误",MessageBoxButtons.OK ,MessageBoxIcon.Error );
}
}
private void butStartCap_Click(object sender, System.EventArgs e)
...{
if(saveFile.FileName !="") //如果设置了路径则执行操作 否则报错
...{
if(radCapFarme.Checked ) //执行帧捕获操作
...{
if(!flagCapingFarmes) //如果当前没有执行其它捕获
...{
if(!axCap.Preview ) //打开自动预览
...{
axCap.Visible =true;
axCap.Preview =true;
txtBack.Visible =false;
butCaptureImg.Enabled =true;
butPreview.Text ="停止预览";
}
if(chkAutoSave.Checked )
...{
//如果自动保存为真则设置周期
axCap.Interval =Convert.ToInt32 (txtTime.Text ,10); //先设置自动保存时间
}
axCap.AutoSave =chkAutoSave.Checked; //处理自动保存
axCap.AutoIncrement =chkAutoRename.Checked; //处理自动改文件名
axCap.FrameFile =saveFile.FileName ; //设置保存路径
butStartCap.Text ="停止捕获";
flagCapingFarmes=true; //设置工作进行标志 标志忙
axCap.CaptureFrame (); //开始捕获帧
}
else //如果当前正在进行其它捕获工作
...{
axCap.AutoSave =false; //关自动保存
axCap.Interval =0; //自动保存周期置0
butStartCap.Text ="开始捕获";
flagCapingFarmes=false; //置工作空闲标志
DisConnect(); //断开连接 关闭捕获
}
}
else //执行流捕获
...{
if(!flagCapingStream )
...{
axCap.VideoCompressorIndex =cobVicomp.SelectedIndex ;
axCap.AudioDeviceIndex =comAudioDevice.SelectedIndex ;
axCap.AudioCompressorIndex =comAudioComp.SelectedIndex ;
axCap.StreamFile =saveFile.FileName ;
butStartCap.Text ="停止捕获";
flagCapingStream=true;
if(!axCap.Preview ) //打开自动预览
...{
axCap.Visible =true;
axCap.Preview =true;
txtBack.Visible =false;
butCaptureImg.Enabled =true;
butPreview.Text ="停止预览";
}
try
...{
axCap.StartCapture ();
}
catch
...{
MessageBox.Show ("视频编码器不可用,请重新连接设备");
cobVicomp.Items.Clear ();
butStartCap.Text ="开始捕获";
flagCapingStream=false;
axCap.Preview =false;
mnuDisableLink.Enabled =false;
mnuLink.Enabled =true;
cobColor.Enabled =false;
cobPix.Enabled =false;
cobColor.Text =null;
cobColor.Items.Clear ();
cobPix.Text =null;
cobPix.Items .Clear ();
txtBack.Visible =true;
chkAdvCap.Enabled =false;
butPreview.Enabled =false;
butSet.Enabled =false;
butDeviceSet.Enabled =false;
butVideoFormat.Enabled =false;
butCaptureImg.Enabled =false;
chkData.Enabled =false;
chkTime.Enabled =false;
txtLable.Enabled =false;
butPreview.Text ="开始预览";
butLink.Text ="连接设备";
if(chkAdvCap.Checked )
chkAdvCap.CheckState =CheckState.Unchecked ;
visableControl(false,3);
}
}
else
...{
if(axCap.Preview )
...{
axCap.Preview =false;
axCap.Visible =false;
txtBack.Visible =true;
butCaptureImg.Enabled =false;
butPreview.Text ="开始预览";
}
butStartCap.Text ="开始捕获";
flagCapingStream=false;
axCap.EndCapture ();
}
}
}
else
...{
MessageBox.Show ("请先设置要存储的文件!","错误",MessageBoxButtons.OK ,MessageBoxIcon.Error );
}
}
Pegasus CapturePRO 控件是一个功能非常强大的控件,由于篇幅和时间关系这里就不一一叙述了,该控件所有的属性、方法、事件在它的帮助文档中都有详细的说明,大家在使用的时候 可以仔细阅读。我写了一个比较详细的Demo程序,该程序使用了绝大多数功能,下面我将软件的界面和源代码给出,希望对大家有所帮助。