基于VC++的视频采集系统的开发

更新时间:2024-01-11 16:25:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

基于VC++的视频采集系统的开发

杂基于VC++的视频采集系统的开发

摘要:

2010年,“ 谷歌退出中国”事件引起了全世界的哗然,虽然在最后,单方面宣布的“退出”事件所表现出来实乃谷歌的一闹剧,但给数以亿的中国的网民的思考是深刻的,给许多的中国互联网络公司是具有极大的挑战意义。现在,科技发展突飞猛进,计算机网络技术也是高速发展,带给中国国际互联网软件公司极大的发展机遇,也给中国许多的计算机软件公司发展的巨大空间。 关键词: VC 视频 采集 系统

在世界金融危机过后,各国尤其是中国人民生活水平的不断提高,以前那种只靠简单的文字、声音进行交流的方式已经不能满足当今许多网民的要求,以可视电话、视频会议、网络监控、视频广播等技术为代表的多媒体技术蓬勃发展起来,成为当今社会的研究热点。这其中的很重要的一项技术就是把静态和动态的图像以原始状态捕捉下来——视频采集。

视频采集系统的应用领域越来越广泛,视频采集以其直观、方便、信息内容丰富而广泛应用于许多场合。银行,酒店,停车场、车站,十字路口,小区门口等等都应用到了这一项技术。实时、高品质的图像和视频给使用者带来了更直观、更感性的认识。因此视频采集技术的重要性渐渐体现出来。随着社会的快速发展,视频技术在以后的生产生活中的运用会更加广泛。 一、基于VC++的视频采集系统的开发原理及分析

基于VC++的视频采集系统的开发系统应用软件的底层,需要极好的兼容性和稳定性。对于广大用户而言,与系统的交互是通过应用程序实现的,因此,如

何设计出运行效率高、界面友好、稳定性高的视频采集系统的应用程序是至关重要的因素。

(一)、基于VC++的视频采集系统的开发实现原理

基于VC++的视频采集系统的开发,首先要用函数capCreateCaptureWindowA创建一个视频采集窗口,然后向视频采集窗口发送相应的消息,实现视频设备的连接、回调函数设置、预览比例和速率设置、预览和叠加模式的设置、图像文件设置等操作。如果以上操作成功,就可以通过视频设备采集图像了。回调函数由程序员编写,用于特殊的视频采集中,例如,在视频会议中用回调函数将采集的视频和音频实时地传递到远程计算机中。

在VC++中,头文件VFW.H中不仅包含了AVICAP.DLL中函数的原型定义,还定义了与视频采集有关的数据结构、消息和发送消息的宏。利用这些函数、数据结构、消息和发送消息的宏可以方便地编写图像采集程序,如果要对采集的图像实时处理,可以通过编写回调函数实现。

(二)、基于VC++的视频采集系统的开发的实例分析

为了说明实现的方法和技巧,采用USB接口的摄像头作为视频采集设备,在VC++中以实现采集一副图像为例说明。 在VC++中创建一个基于MFC的单文档应用程序,工程名为“Video”,按照以下步骤完成: (1)在VideoView.h的首部加入语句:#include \ (2)打开“Project Settings”对话框,选择“Link”选项卡,在“Object/library modules”中输入“vfw32.lib”。

(3)在VideoView.h中对类CVideoView加入私有成员变量Hwndcap: private: //视频采集窗口的句柄,HWND Hwndcap。

(4)在Resources面板中单击“Menu”,双击“IDR_MAINFRAME”,添加菜单项“采集”。在“采集”下加入子菜单项“采集图像”和“保存BMP”,它们的ID分别设为“ID_CAP_BMP”和“ID_SAVE_BMP”。

(5)在MFC ClassWizard中,选择“Message Map”选项卡,在下拉列表框“Class name”中选择“CVideoView”,在列表框“Object IDs”中选择“ID_CAP_BMP”,在列表框“Messages”中选择“Command”,单击“Add Function”按钮添加成员函数OnCapBmp(),按照同样方法为“ID_SAVE_BMP”响应消息“Command”添加成员函数OnSaveBmp()。再按照同样方法为“CVideoView”响应消息“WM_SIZE” 添加成员函数OnSize()。 (6)在类“CVideoView”的构造函数中加入:Hwndcap=NULL; (7)在类“CVideoView”的成员函数OnCapBmp()中加入以下代码: CRect WRect; //取得主窗口客户区域的位置和大小 GetClientRect(&WRect); //创建视频采集窗口

Hwndcap=capCreateCaptureWindow( LPSTR) \采集图像\ WS_CHILD|WS_VISIBLE, 0,2WRect.Width(),WRect.Height(), AfxGetMainWnd()->m_hWnd,

(int)0); if(Hwndcap) //连接视频采集设备

if(capDriverConnect(Hwndcap,0)) //设置视频预览图像的大小 capPreviewScale(Hwndcap,1); //设置视频预览的速率 capPreviewRate(Hwndcap,66); //设置视频以预览模式显示 (8)在类“CVideoView”的成员函数OnSaveBmp ()中加入以下代码: if(Hwndcap) //将当前帧保存为位图文件 capFileSaveDIB(Hwndcap,\

(9)在类“CVideoView”的成员函数OnSize中加入以下代码: CRect WRect; //取得主窗口客户区域的位置和大小 GetClientRect(&WRect); //设置视频采集窗口的位置和大小 以上各步完成后,经过编译和连接生成可执行文件“Video.exe”。运行“Video.exe”,单击菜单项“采集/采集图像”,程序中的capDriverConnect

等是头文件“Vfw.h”中定义的宏,这些宏实质是向视频采集窗口发送相应的消息。

在VC++中利用AVICAP.DLL实现图像采集简单,编程代码量少,程序员编写回调函数可以实现特殊需求的图像采集,不过,对于一般要求的图像采集不需要编写回调函数。http://www.yjlww.com 二、 基于VC++的视频采集系统的开发步骤

VFW是Microsoft推出的关于数字视频的一个软件开发包,在VC++开发环境中调用VFW和使用其它开发包没有什么不同,只是需要将VFW32.lib文件加入工程中。

VFW为开发人员提供了很多的接口,开发人员可以使用这些接口在视频采集过程中抓取图片、在采集窗口中预览采集的视频、设置采集参数及显示视频源、视频格式、压缩格式的设置对话框。 (一)、创建视频窗口

视频窗口与视频采集的驱动程序关联,它接收各种视频采集相关的消息,并根据这些消息控制视频采集设备的各种操作。后续的所有视频采集消息全部发送给视频采集窗口。要创建视频采集窗口可以通过调用capCreateCaptureWindow函数实现。

我们可以通过在MFC的View类中增加一个窗口句柄成员变量来保存capCreateCaptureWindow函数返回的采集窗口句柄,然后在View类的OnCreate函数中添加以下语句。m_caphwnd = capCreateCaptureWindow(_T(\Window\。 (二)、连接采集驱动

创建采集窗口后,需要将采集窗口与采集驱动程序关联起来。为了验证当前PC机上是否安装的视频采集设备,可以在关联驱动程序之前调用

capGetDriverDescription函数枚举一下系统中的采集驱动,代码如下:

int i = 0;

wchar_t sdriver[50];//驱动信息 wchar_t sver[50];//版本信息 CString m_driverInfo(\for ( i = 0; i < 10; i++ )

{if( capGetDriverDescription(i,sdriver,50,sver,50) ) } m_driverInfo += sdriver; m_driverInfo += \m_driverInfo += sver; m_driverInfo += \

memset(sdriver,0,50 * sizeof(wchar_t)); memset(sver,0,50 * sizeof(wchar_t));

if ( !m_driverInfo.IsEmpty() ) //显示驱动程序信息 AfxMessageBox(m_driverInfo);

else {AfxMessageBox(_T(\

确认当前系统中安装有采集设备后,可以使用capDriverConnect宏向视频采集窗口发送连接采集驱动的消息,代码如下://关联第一个驱动 capDriverConnect(m_caphwnd,0)。

视频采集摄像头:(如下图所示,品牌-奥家; 像素-800万;免驱动) (三)、设置采集参数

在视频采集之前,可以通过capCaptureGetSetup宏取得视频采集参数,然后通过capCaptureSetSetup宏将新设定的采集参数传递到采集窗口,http://www.yjlww.com由采集窗口控制采集驱动程序。代码如下: CAPTUREPARMS s;

capCaptureGetSetup(m_caphwnd,&s,sizeof(CAPTUREPARMS));//取得采集参数

s.dwRequestMicroSecPerFrame = 33333;//采集一帧花费1/30秒 s.fAbortLeftMouse = FALSE;//压下鼠标左键不终止采集 s.fAbortRightMouse = FALSE;//压下鼠标右键不终止采集 s.fCaptureAudio = TRUE;//c采集音频

s.fYield = TRUE;//使用一个独立的线程来采集视频,不使用View窗口线程 capCaptureSetSetup(m_caphwnd,&s,sizeof(CAPTUREPARMS));//设定采集参数 还可以通过capGetVideoFormat宏取得视频格式,然后通过capSetVideoFormat设定视频格式。参考代码如下: LPBITMAPINFO bitmapinfo;

DWORD bit_info_size = 0;//取得视频格式信息的大小 bit_info_size = capGetVideoFormatSize(m_caphwnd);

bitmapinfo=(LPBITMAPINFO)GlobalAlloc(GHND,bit_info_size);//取得视频格式信息

capGetVideoFormat(m_caphwnd,bitmapinfo,bit_info_size);//设置视频格式信息

bitmapinfo->bmiHeader.biCompression = BI_RLE4;//设置压缩格式为JPEG bitmapinfo->bmiHeader.biWidth = 640;//设置解压缩后的水平像素为640 bitmapinfo->bmiHeader.biHeight = 480;//设置解压缩后的垂直像素为480 capSetVideoFormat(m_caphwnd,bitmapinfo,bit_info_size); //设置视频格式 注意,如果驱动程序不支持以上参数,以上设定是无效的,驱动程序还是使用默认的设置参数。

(四)、开始/结束视频采集

我们可以在菜单中添加一个视频采集开始的菜单项,在此菜单项的响应函数中使用capCaptureSequence宏开始视频采集。

同样,我们也可以添加视频结束的菜单项,在此菜单项的响应函数中使用capCaptureStop宏终止采集操作,然后使用capFileSaveAs宏将采集的视频保存到指定的文件中,如果不指定文件,默认保存到C盘CAPTURE.AVI文件中。也可以在采集窗口中预览采集的视频,http://www.yjlww.com预览终止后,视频并不保存到文件中。预览的代码如下: //开始预览 capPreview(m_caphwnd,TRUE); //结束预览 capPreview(m_caphwnd,FALSE); (五)、图片抓取

可以使用capGrabFrameNoStop宏抓取图片,然后使用capFileSaveDIB宏将采集的图片保存为DIB文件,因为DIB文件的大小比JPEG或PNG文件大很多,我们可以使用CImage类将DIB文件转换成JPEG文件或PNG文件。 1、显示视频源对话框

可以使用capDlgVideoSource宏显示视频源对话框。视频源对话框可以设置视频源设备的一些设置,视频源对话框一般是下面的样子,但设备不同,对话框显示的内容肯能会有所不同。显示视频源对话框的代码如下: capDlgVideoSource(m_caphwnd); 2、显示视频格式对话框

可以使用capDlgVideoFormat宏显示视频格式设定对话框。这个对话框可以设定采集视频的格式。代码如下: capDlgVideoFormat(m_caphwnd); 3、 显示压缩设定窗口

可以通过capDlgVideoCompression宏显示压缩设定窗口。通过这个窗口可以设定视频的压缩格式。代码如下:

capDlgVideoCompression(m_caphwnd);http://www.yjlww.com 三、基于VC++的视频采集系统的开发的实现

如何实现VC进行视频采集的方法呢?VFW提供的函数可以让应用程序去处理视频数据。 VFW 在16位Windows的时候就被引入了。它的许多重要功能已经被DirectX取代了。下面讲介绍VFW的视频捕获:可以使用windows的AVICap 类轻松地完成视频捕获。AVICap 提供给应用程序一个简单的、基于消息的接口去访问视频设备和录音设备,并且可以控制处理视频流捕获。 1、关于视频捕获

AVICap支持实是视频流捕获和实时单帧图像捕获。另外,AVICap 提供了对视频源的控制(MCI媒体控制接口设备),因此使用者可以通过应用程序控制一个视频源开始和结束的位置,并且可以加大对帧捕获的控制。视频捕获将数字化一个视频流和音频数据,并且将他们保存在硬盘和其他存储设备上。

这里将描述如何在应用程序中简单地应用视频捕获,它通过三个代码实现。它还介绍了如何通过发送消息给视频捕获窗口来结束或中断一个视频会话。 AVICap 捕获窗口可以把捕获的音视频信息写入一个AVI文件中。应用程序可以自由地处理这个AVI文件、管理缓存区的音视频数据、还可以在底层访问音视频设备的驱动器。AVICap为应用程序提供了一个灵活的接口。应用程序创建AVICap捕获窗口,并和视频设备建立连接后。创建的这个捕获窗口就准备捕获数据了。这时,可以通过发送WM_CAP_SEQUENCE消息(或capCaptureSequence 宏)开始对数据进行捕获。

WM_CAP_SEQUENCE将使用默认设置,开始对视频和音频进行捕获,并把数据放在一个CAPTURE.AVI的文件中,捕获动作将一直持续。在应用程序中,可以通过发送WM_CAP_STOP命令(或capCaptureStop)给捕获窗口,让它停止向文件写数据。还可以通过发送WM_CAP_ABORT命令(或capCaptureAbort)给捕获窗口,让它中断捕获操作。

可以让用户按这几种方法退出一个捕获会话,按键盘上的一个键或几个组合键、或者按鼠标的左键或者是右键。如果用户退出一个实时的捕获会话,那么捕

获文件中的内容将被系统丢弃掉。如果用户退出一个步帧(step-frame)捕获的会话,捕获文件将保存到退出时刻前的所有数据。可以通过发

WM_CAP_GET_SEQUENCE_SETUP消息(或capCaptureGetSetup宏)给捕获窗口,来获得捕获退出的设置信息。当前的退出按钮设置保存在CAPTUREPARMS结构的vKeyAbort 成员中,当前的退出鼠标设置保存在fAbortLeftMouse和 fAbortRightMouse成员中。

通过使用CAPTUREPARMS结构的fLimitEnabled http://www.yjlww.com和wTimeLimit成员,可以去限定一个捕获操作的时间周期。fLimitEnabled 表示是否要对捕获操作限定时间, wTimeLimit 用于指定限定时间的最大值。发WM_CAP_GET_SEQUENCE_SETU消息(capCaptureGetSetup宏)给捕获窗口,就可以得到fLimitEnabled 和 wTimeLimit的值。 FLimitEnabled为TRUE表示要指定时间周期。WTimeLimit单位为秒。修改完成后,可以发

WM_CAP_SET_SEQUENCE_SETU(或capCaptureSetSetup宏)给你的捕获窗体,来刷新CAPTUREPARMS 结构。

2、建立捕获窗口到捕获设备的连接

可以动态地连接或断开捕获窗口与设备间的链接。通过使用

WM_CAP_DRIVR_CONNECT消息(或capDriverConnect宏),可以实现捕获窗体与设备驱动间的连接。当捕获窗体和捕获设备驱动连接后,就可以发送针对设备的消息给该窗体了。

如果系统安装了多个捕获设备,可以通过在发送WM_CAP_DRIVER_CONNECT消息时,设置wPrarm参数(integer)。来指定捕获窗口与那个具体的视频捕获设备相连接。WPrarm参数是一个整数,它表示一个系统已经安装的视频捕获设备列表的索引(注册表中或这System.ini [drivers]中的信息)。该列表的索引从0开始。、

通过capGetDriverDescription函数可以获得安装的捕获驱动程序的名称和版本。你的应用程序可以使用这个函数列举除安装的所有捕获设备,让用户可以选择其中一个去与捕获窗口相联。通过发送WM_CAP_DRIVER_GET_NAME消息(capDriverGetName宏),可以获得与指定窗体连接的捕获设备的名称。通过发送 WM_CAP_DRIVER_GET_VERSION(capDriverGetVersion宏)

http://www.yjlww.com,可以获得与指定窗体连接的捕获设备的版本。通过发送WM_CAP_DRIVER_DISCONNECT(capDriverGetDisconnect宏),可以断开连接。当捕获窗体销毁后,任何连接的视频捕获设备都将自动断开。 3、捕获和音频驱动器 。

视频捕获可以做这几个方面的工作:访问 视频源、显示选项、格式和压缩选项。音频捕获包括指定音频格式和选择压缩方式。一是不捕获驱动性能。通过发送WM_CAP_DRIVER_GET_CAPS消息(capDriverGetCaps宏),可以获得当前连接的捕获设备的性能。发送该消息后,会返回一个CAPDRIVERCAPS结构的对象。设备的性能信息,就在这个对象中。二是不视频对话框(Video Dialog Boxes)。每个捕获设备的驱动程序都可以为控制视频信号和捕获处理和视频压缩提供4个对话框。这些对话框中的内容都是视频捕获驱动程序定义的。视频源对话框(Video Source dialog box)用于选择视频输入通道和视频图像的动态参数。它可以列举出当前连接视频设备的信号类型(SVHS和复合类型),并且可以通过该对话框去修改图像的色调、亮度、饱和度。你可以通过使用

WM_CAP_DLG_VIDEOSOURCE 消息(或 capDlgVideoSource 宏)来显示和刷新这个窗口。视频格式对话框(Video Format dialog box)用于选择数字视频的框架大小和视频图像的色深,以及捕获视频图像的压缩格式。你可以通过使用WM_CAP_DLG_VIDEOFORMAT消息 (或 capDlgVideoFormat宏)来显示和刷新这个窗口。视频显示对话框(Video Display dialog box)用于控制视频外观。在该对话框上进行了修改只是对视频显示起作用,对于实际的视频数据是不会造成改变

的。比如,可以改变显示的颜色,你可以通过使用WM_CAP_DLG_VIDEODISPLAY消息(或 capDlgVideoDisplay宏)来显示和刷新这个窗口。视频压缩对话框(Video Compression dialog box)用于设置视频压缩的格式。通过使用WM_CAP_DLG_VIDEOCOMPRESSION消息 (或

http://www.yjlww.comcapDlgVideoCompression宏)来显示和刷新这个窗口。

4、预览和覆盖模式 。

一般,一个捕获驱动提供两种方式来观看输入的视频流:预览模式和覆盖模式。如果捕获驱动可以提供上面两种模式,那么用户就可以选择其中的模式来使用。预览模式从捕获设备硬件传输数据帧到系统的内存中,并且在捕获窗口中使用GDI函数来显示这些数据帧。当捕获窗口的父窗体失去焦点的时候,在应用程序的视频预览的数据将变慢,如果父窗体获的焦点后,将对预览显示进行加速。因为预览处理的这种处理方式将大大提高整个系统的效率。

当预览和缩放比例属性都打开后,那么视频将被缩放到和捕获窗口尺寸一样大。打开预览模式后,系统将自动关闭覆盖模式。覆盖模式,将不占用CPU的处理资源,直接在显示器上显示视频内容。所用的处理是有捕获设备硬件来完成。发送WM_CAP_SET_OVERLAY消息(或capOverlay宏)给捕获窗口,可以打开覆盖模式。打开覆盖模式后,将自动关闭预览格式。无论是预览模式还是覆盖模式,都可以通过发送WM_CAP_SETSCROLL消息(capSetScroollPos宏),可以设置图像的在整个视频帧的滚动位置(scroll position)。 5、捕获文件和缓存区

如果用户想保存捕获数据,把数据存到另外一个文件中。可以使用WM_CAP_FILE_SAVEAS消息(capFileSaveAs宏) 。这个消息不能改变捕获文件的名称和内容。你必须去指定新建的文件名,因为捕获文件将保留原来的文件名称。在捕获操作前,先在磁盘上为捕获文件建一个指定大小的文件。预分配空间将减

少数据保存时的处理时间。可以通过WM_CAP_FILE_ALLOCATE消息(capFileAlloc宏)来预分配一个捕获文件。

要预分配足够大的磁盘空间去保存预计最大的捕获文件。预分配磁盘空间没有限定捕获文件的大小。如果捕获的数据大于了分配的空间,文件尺寸将自动变大。对一个捕获文件进行重写数据,将对文件的已经分配的磁盘空间进行重写。 通过对捕获文件进行磁盘碎片整理可以提高捕获性能。要对文件进行碎片整理,可以使用一个碎片整理工具来完成,比如Disk Defragmenter。通过使用没压缩的磁盘来保存数据,同样可以提高性能。因为在捕获期间压缩数据将对磁盘的吞吐量进行限制。

四、基于VC++的视频采集系统的分析

视频采集是开发视频监控系统的首要步骤,它关系到采集视频数据的质量,因此,视频采集会影响到其后的各种操作(包括视频预览、视频录像、视频回放、图像识别等)。本章将从VFW(Video For Windows,Windows视频)、DirectShow和SDK(Software Development Kit,软件开发包) 3个方面介绍视频采集的解决方案。

在开发视频监控系统时,通常有3种视频采集的方法。分别为VFW、DirectShow和SDK。其中,VFW是一种较老的视频采集方法,它是Microsoft提供的数字视频软件包,提供了一组库函数,能够实现视频捕捉、影像压缩及影像播放等功能。使用VFW的优点是它随从Windows操作系统一起安装,可执行文件不需要附带额外的库文件就可以运行,但是许多监控卡不支持VFW,因此,在开发专业的监控系统时很少使用VFW技术。DirectShow是Microsoft推出的流媒体开发包,使用它可以在支持WDM驱动的各种监控卡上采集数据,因此,使用DirectShow可以开发通用的视频监控程序。DirectShow支持ASF、MPEG、AVI、MP3、WAV等多种媒体格式,使得它很容易实现媒体数据的采集、回放。SDK是监控卡厂家提供的开发视频监控系统的一组库函数,使用SDK库函数,用户可以在不了解视频压

缩、回放、网络传输等技术的前提下,进行视频程序开发(SDK中通常都包含了这些技术的实现)。但是,由于不同厂家提供的监控卡SDK并不兼容,因此编写的应用程序无法移植到新的环境中。 (一)、VFW视频采集方案

VFW是Microsoft推出的数字视频软件包,它不依赖于专用的硬件设备,提供了通用的数字视频开发方案。VFW主要由AVICap.dll、MSVideo.dll、http://www.yjlww.comMCIAvi.drv、AVIFile.dll、vfw32.lib等库文件组成,这些库提供了相关视频、音频、AVI文件的函数,本节将介绍如何利用这些函数进行视频采集。 1、开发流程分析

VFW使用的视频函数被封装在vfw32.lib库文件中,该库文件默认情况下没有被连接到MFC工程中,因此使用VFW进行视频开发的第一步是导入vfw32.lib库文件。方法如下:

(1)引用vfw.h头文件。 #include \

(2)导入vfw32.lib库文件。

#pragma comment (lib,\,这里也可以在通过工程选项窗口的连接选项卡进行设置。

在导入vfw32.lib库文件后便可以使用视频函数了。首先调用

capCreateCaptureWindow函数创建具有WS_POPUP风格的视频捕捉窗口。然后调用capDriverConnect函数连接驱动程序,设置视频捕捉窗口的大小、显示位置。最后调用capPreviewRate函数设置预览速率,调用capPreview函数进行视频预览。

总结上述流程分析,VFW视频捕捉开发流程具体步骤如下:(1)引用“vfw.h”头文件并导入vfw32.lib库。(2)创建一个线程,在线程函数中调用

capCreateCaptureWindow创建视频捕捉窗口。(3)调用capDriverConnect连接驱动程序,设置视频捕捉窗口风格、大小及父窗口。(4)调用capPreviewRate函数设置预览速度,调用capPreview函数开始预览。 2、 视频窗口创建

在进行视频程序开发时,第一步需要创建一个视频预览窗口。在程序中可以使用capCreateCaptureWindow函数来创建视频预览窗口,该函数语法如下: HWND VFWAPI capCreateCaptureWindow(LPCSTR lpszWindowName, DWORD dwStyle, int x,

int y, int nWidth, int nHeight, HWND hWnd, int nID); 参数说明:

lpszWindowName:表示视频捕捉窗口的名称。

dwStyle:表示视频捕获窗口的风格,一般包含有WS_CHILD 和 WS_VISIBLE风格。

x、y:表示视频捕捉窗口的左上角坐标。

nWidth、nHeight:表示视频捕捉窗口的宽度和高度。 hWnd:表示视频捕捉窗口父窗口的句柄。 nID:表示视频捕捉窗口标识。

在创建视频捕捉窗口之后,需要将其显示在对话框中的适当位置。可以在对话框中预先放置一个静态文本控件,调整其大小和位置,然后将视频捕捉窗口放置在该控件的位置处就可以了。 3、 视频预览实现

在开发视频应用程序时,第一步需要实现的功能便是视频预览。下面以一个具体实例来说明VFW视频预览的实现过程。 程序设计步骤如下:

实例位置:光盘\\mr\\2\\2.2\\2.2.3\\01

(1)创建一个基于对话框的工程,在对话框中添加Picture控件, (2)在类向导的“Member Variables”选项卡中为Picture控件命名, (3)在对话框的头文件中引用“vfw.h”头文件,然后链接“vfw32.lib”库文件。

(4)在对话框中定义一个视频预览窗口的句柄。 HWND m_hWndVideo; //视频显示窗口

(5)在对话框初始化时创建视频预览窗口,连接视频驱动程序,设置预览帧率,开始视频预览。 4、捕捉参数设置

在进行视频捕捉时,通常需要设置视频捕捉参数。VFW提供了capCaptureSetSetup函数用于设置视频捕捉参数,该函数语法如下: BOOL capCaptureSetSetup(HWND hwnd, LPCAPTUREPARMS psCapParms,UINT wSize ); 参数说明:

hwnd:表示视频捕捉窗口句柄。

psCapParms:表示视频捕捉参数,该参数是CAPTUREPARMS结构指针。 在进行视频捕捉时,通常会根据实际需要设置捕捉参数。例如,在视频录像时,通常会将fYield成员设置为TRUE,启动后台线程来进行视频录像,这样,前台用户依然可以进行其他界面有关操作。 (二)、 回调函数设计

在开发视频应用程序时,可以为视频捕捉窗口设计一些回调函数,这样,当视频应用程序的某些状态改变时,可以在回调函数中进行处理。VFW提供了如下的函数进行回调函数注册。

( 1)capSetCallbackOnCapControl

该函数提供了视频捕捉时精确地控制捕捉开始和结束的时间。语法如下:BOOL capSetCallbackOnCapControl(HWND hwnd, CAPCONTROLCALLBACK fpProc ); 参数说明:

hwnd:表示视频捕捉窗口句柄。

fpProc:表示视频捕捉回调函数指针,其定义如下:typedef LRESULT (CALLBACK* CAPCONTROLCALLBACK)(HWND hWnd, int nState); 其中,hWnd表示视频捕捉窗口句柄,nState参数如果设置为CONTROLCALLBACK_PREROLL,表示将要开启视频源,为

CONTROLCALLBACK_CAPTURING,表示应用程序允许通过返回FALSE去结束视频捕捉。

( 2)capSetCallbackOnError

该函数用于为客户端应用程序设置错误处理的回调函数。语法:BOOL capSetCallbackOnError(HWND hwnd, CAPERRORCALLBACKA fpProc); 参数说明:

hwnd:表示视频捕捉窗口句柄。

fpProc:表示错误处理的回调函数指针,其定义如下:typedef LRESULT (CALLBACK* CAPERRORCALLBACKA) (HWND hWnd, int nID, LPCSTR lpsz); 其中,hWnd表示视频捕捉窗口句柄,nID表示消息ID,lpsz表示消息文本描述。

(3)capSetCallbackOnFrame

该函数用于设置预览回调函数,回调函数在预览帧之前调用。语法如下:BOOL capSetCallbackOnFrame(HWND hwnd, CAPVIDEOCALLBACK fpProc ); 参数说明:

hwnd:表示视频捕捉窗口句柄。

fpProc:表示预览回调函数指针,其定义如下:typedef LRESULT (CALLBACK* CAPVIDEOCALLBACK) (HWND hWnd, LPVIDEOHDR lpVHdr);

其中, hWnd表示视频捕捉窗口句柄,lpVHdr是一个VIDEOHDR结构指针,表示视频数据头。

(4)capSetCallbackOnStatus

该函数用于在程序中设置一个状态回调函数。语法如下:BOOL capSetCallbackOnStatus(HWND, CAPSTATUSCALLBACKA fpProc ); 参数说明:

hwnd:表示视频捕捉窗口句柄。

fpProc:表示回调函数指针,当应用程序的状态改变时将调用该函数。其定义如下:typedef LRESULT (CALLBACK* CAPSTATUSCALLBACKA) http://www.yjlww.com(HWND hWnd, int nID, LPCSTR lpsz);

其中, hWnd表示视频捕捉窗口句柄,nID表示状态码,lpsz表示状态文本描述。 (5)capSetCallbackOnVideoStream

该函数用于注册一个回调函数,使得视频缓冲区被填充时调用回调函数。语法如下:BOOL capSetCallbackOnVideoStream(HWND hwnd, CAPVIDEOCALLBACK fpProc ); 参数说明:

hwnd:表示视频捕捉窗口句柄。

fpProc:表示回调函数指针,当视频缓冲区被填充时调用回调函数,其定义与capSetCallbackOnFrame函数的fpProc参数相同。 (6)capSetCallbackOnWaveStream

该函数用于注册一个回调函数,使得音频缓冲区被填充时调用回调函数。语法如下:BOOL capSetCallbackOnWaveStream (HWND hwnd, CAPWAVECALLBACK fpProc );

参数说明:

hwnd:表示视频捕捉窗口句柄。

fpProc:表示回调函数指针,当音频缓冲区被填充时调用回调函数。其定义如下: typedef LRESULT (CALLBACK* CAPWAVECALLBACK) (HWND hWnd, LPWAVEHDR lpWHdr);

其中, hWnd表示视频捕捉窗口句柄,lpWHdr是一个WAVEHDR结构指针,表示音频数据头。

(7)capSetCallbackOnYield

该函数用于注册一个回调函数,使得在每一次捕捉视频帧时调用一次回调函数。语法如下:

BOOL capSetCallbackOnYield(HWND hwnd, fpProc ); 参数说明:

hwnd:表示视频捕捉窗口句柄。

fpProc:表示回调函数指针,其定义如下:typedef LRESULT (CALLBACK* CAPYIELDCALLBACK) (HWND hWnd);

其中, hWnd表示视频捕捉窗口句柄。通常,该函数由消息循环构成。 VFW的回调函数在视频预览、视频录像、视频压缩等多个地方被广泛使用。 (三)视频录像设计方案

在VFW中,可以有3种方式实现视频录像。其中,最简单的方式是调用capFileSetCaptureFile函数和capCaptureSequence函数。该种方式存在许多缺点,例如,在录像时无法响应用户界面,无法实现视频压缩等。第二种方式是调用capCaptureSetSetup函数,将CAPTUREPARMS结构的fYield成员设置为TRUE,启动后台线程来实现录像,然后调用capDlgVideoCompression函数让用户选择压缩器进行压缩,最后调用capFileSetCaptureFile函数和

capCaptureSequence函数开始录像。第二种方式的缺点是每次录像时都需要弹

出一个对话框,让用户选择一种压缩器。第三种方式是注册回调函数

capSetCallbackOnVideoStream,在回调函数中压缩数据并写入AVI文件。相对于前两种方式,第三种方式更为灵活和实用,因此在进行视频录像时,通常采用该种方式实现。具体实现过程如下:

(1)定义一个回调函数,该回调函数实现数据压缩,并将压缩的数据写入文件流中。

(2)调用capSetCallbackOnVideoStream注册回调函数。

(3)调用ICOpen函数打开一个压缩器,并调用ICCompressBegin函数开始压缩。 (4)调用AVIFileOpen函数打开一个AVI文件,并调用AVIFileCreateStream函数创建文件流。

(5)调用capCaptureSequenceNoFile函数开始录像。 五、基于VC++的视频采集系统的开发问题的几个探讨 (一)、回调函数处理的问题

回调函数是至今为止最有用的编程机制之一。在Windows中,回调函数更是窗口过程、钩子过程、异步过程调用所必需的,在整个回调过程中自始至终地使用回调方法。人们可以注册回调方法以获得加载/卸载通知,未处理异常通知,数据库/窗口状态修改通知,文件系统修改通知,菜单项选择,完成的异步操作通知,过滤一组条目等等。在VFW中有几条这样的宏函数http://www.yjlww.com,如用于设置在发生某事件后能作出反应的回调函数的宏函数,它和中断服务机制很相似,条件一满足,程序会自动进入相应的回调函数体中,该函数究竟要做些什么,全由开发者借助其参数自行编制程序来确定。利用VFW获取实时视频数据通常可以运用视频处理的回调机制(call-backmechanism) 获得实时数据缓冲区的首址和长度并对图像数据进行处理,同时也可以进行视频数据的直接传输,在这一方面很多文章都作了具体的介绍。但是按照大多数文章的介绍,在具体的应用过程中,对回调函数作如下定义时,程序总是无法通过编译:

{

LRESULT CALLBACK FrameCallbackProc(HWND ghWnd,LPVIDEOHDR

lpVData)

unsigned char *data;

data=lpVData->lpData;//获得视频数据首地址,并将数据存入data

数组中以便处理

} 通过研究,发现根本原因是回调函数是基于C编程的Windows SDK的技术,不是针对C++的,可以将一个C函数直接作为回调函数,但是如果试图直接使用C++的成员函数作为回调函数将发生错误,甚至编译就不能通过。其错误是普通的C++成员函数都隐含了一个传递函数作为参数,亦即“this”指针,C++通过传递一个指向自身的指针给其成员函数从而实现程序函数可以访问C++的数据成员。这也可以理解为什么C++类的多个实例可以共享成员函数但是确有不同的数据成员。由于this指针的作用,使得将一个CALLBACK型的成员函数作为回调函数安装时就会因为隐含的this指针使得函数参数个数不匹配,从而导致回调函数安装失败。要解决这一问题的关键就是不让this指针起作用,通过采用以下两种典型技术可以解决在C++中使用回调函数所遇到的问题。这种方法具有通用性,适合于任何C++。

1、 不使用成员函数,直接使用普通C函数,为了实现在C函数中可以访问类的成员变量,可以使用友元操作符(friend),在C++中将该C函数说明为类的友元即可。这种处理机制与普通的C编程中使用回调函数一样。

2、 使用静态成员函数,静态成员函数不使用this指针作为隐含参数,这样就可以作为回调函数了。静态成员函数具有两大特点:其一,可以在没有类实例的情况下使用;其二,只能访问静态成员变量和静态成员函数,不能访问非静态成员变量和非静态成员函数。由于在C++中使用类成员函数作为回调函数的目的就是为了访问所有的成员变量和成员函数,如果作不到这一点将不具有实际意义。解决的办法也很简单,就是使用一个静态类指针作为类成员,通过在类创建时初始化该静态指针,如pThis=this,然后在回调函数中通过该静态指针就可以访

问所有成员变量和成员函数了。这种处理办法适用于只有一个类实例的情况,因为多个类实例将共享静态类成员和静态成员函数,这就导致静态指针指向最后创建的类实例。为了避免这种情况,可以使用回调函数的一个参数来传递this指针,从而实现数据成员共享。这种方法稍稍麻烦,这里就不再赘述。 因此,可以对回调函数作如下定义:http://www.yjlww.com

static LRESULT CALLBACK FrameCallbackProc(HWND ghWnd,LPVIDEOHDR

lpVData)

{

unsigned char *data;

data=lpVData->lpData;//获得视频数据首地址,并将数据存入data

数组中以便处理

} (二)、图像采集中的问题

视频数据的采集是整个应用的关键,根据应用的不同可以将视频帧采集到的文件或采集的缓存直接加以处理。利用VFW获取实时视频数据通常可以运用视频处理的回调机制(call-backmechanism) 获得实时数据缓冲区的首址和长度并对图像数据进行实时处理,但是在这个过程中图像处理程序不能太长,否则视频显示不流畅。另外,在实际采集过程中,有些图像采集卡驱动程序对通过回调机制所获取的数据进行了压缩,比如DC10,而在图像测量系统高精度的要求,压缩后的图像数据直接影响以后的图像处理工作。通过采用以下两种典型技术可以实现将没有压缩的视频帧的图像数据的采集。

1、 通过研究发现,尽管图像采集卡驱动程序对通过回调机制所获取的数据进行了压缩,但是利用VFW中的capEditCopy( )宏函数将帧图像缓冲区中的图像数据拷贝到剪贴板上时,并没有压缩图像数据,因此可以不采用回调机制而直接利用capGrabFrameNoStop()捕获一帧图像,然后将数据拷贝拷贝到剪贴板上,再通过DIB(Device Independent Bitmap)操作获取内存中图像数据首地址,进行后续的图像数据处理。具体的代码片段如下:

//获得capEditCopy( )拷贝到剪贴板中的图像数据句柄,通过CF_DIB参数指定

数据

HANDLE hData;

::GlobalFree ((HGLOBAL)hData);

hData=(HANDLE)CopyHandle(::GetClipboardData(CF_DIB));http://www.yjl

ww.com 2、利用capFileSaveDIB将缓冲区中的图像数据转化为DIB位图直接保存为文件,需要处理时,再读取位图中的图像数据到内存进行后续的处理。这种方式因为有一个文件存储和读取的延迟,对于实时的图像处理来说,响应速度比前者要稍慢,经过多次实验证明,只要图像处理算法的计算量不是很大,仍然可以保证比较好的实时性。

(三)、图像采集窗口建立的问题

在视频捕获之前需要创建一个捕获窗,所有的捕获操作及其设置都以它为基础。一个AVICap视窗口句柄描述了声频与视频流的细节,这样就使程序员的应用程序从AVI文件格式,声频视频缓冲管理,低层声频视频驱动访问等解脱出来。AVICap即是预定义的Windows窗口类,利用该窗口类创建的子窗口可以与视频采集设备的驱动程序相联系,该子窗口的客户区用来显示采集设备捕获的实时视频图像。

但是在实际应用过程中,应用程序可能会基于单文档(SDI)、多文档或者是基于对话框的界面,由于三种类型的不同,捕获窗的具体创建应根据具体要求而有所区别。不管是采用哪种类型,根据实时视频的显示的具体要求,关键是如何获取捕获窗口的父窗口句柄。通常捕获窗口的创建可以如下两种方式:

1、获取动态创建的父窗口的句柄,动态的创建捕获窗口。具体的代码片段如下:

CFrameWnd m_wndSource;

if(!m_wndSource.CreateEx(WS_EX_TOPMOST,NULL,\

(100,100,150,180),NULL,0))

return -1;

m_wndSource.ShowWindow(SW_HIDE);

m_WndCap=capCreateCaptureWindow((LPSTR)\视频捕捉测试程序

\

2、获取显示的实时视频窗口的句柄,静态的创建捕获窗口。具体的代码片段如下:

m_hCapWnd = capCreateCaptureWindow((LPSTR)TEXT(\视频捕捉测试程

序\

0,0,768,576,this->m_hWnd,0);http://www.yjlww.com 六、结束语

应用VC++建立良好的视频采集系统,以便于各种底层控制参数的设置和读取。VC++下与数据库建立连接,实现底层上传数据的存储和维护。对数据库中数据进行按条件统计、分类以及报表显示。利用VFW技术实现视频数据实时获取,提高了视频采集的效果和程序运行的效率,同时也减少了对硬件的依赖性,提高了程序的兼容性和移植性。在很多基于数字图像处理技术的开发系统中都使用了这种方法,随着科技的进步与技术全融入到我们的生活中,视频采集技术渐渐与我们的生活密不可分,这就需要我们积极努力地探索,完善开发好各项技术,以便更好的服务于社会。 文献资料

[1] Thomas Fromherz, Peter Stucki, Martin Bichsel. A Survey of Face Recognition. MML Technical Report, No 97.01, Dept. of Computer Science, University of Zurich, 1997.

[2] R.C.K Hua, L.C. De Silva, P. Vadakkepat. Detection and Tracking of Faces in Real-Time Environments. International Workshop on Recognition, Analysis, and Tracking of Faces and Gestures in Real-Time Systems,Sep. 26 - 27, 1999, p.96

[3] Do-Joon Jung, Chang-Woo Lee, Yeon-Chul Lee, Sang-Yong Bak, Jong-Bae Kim, Hyun Kang, Hang-Joon Kim. PCA-Base Real-Time Face Detection and Tracking. International Technical Conference on Circuits/Systems,

Computers and Communications (ITC-CSCC'02), Jul, Phuket, Thailand, Jul. 16-19, 2002, Vol. 1, p.615-618

[4] James L. Crowley, Francois Berard. Multi-Modal Tracking of Faces for Video Communications. Proceedings of the 1997 Conference on Computer Vision and Pattern Recognition (CVPR '97), 1997, p.640

[5] Vladimir Vezhnevets, Vassili Sazonov, Alla Andreeva. A Survey on Pixel-Based Skin Color Detection Techniques. Graphics,Media Laboratory. [6] Rein-Lien Hsu, Mohamed Abdel-Mottaleb, Anil K. Jain. Face Detection in Color Images. IEEE Trans. Pattern Analysis and Machine Intelligence, May 2002, vol. 24, no. 5, p. 696-706http://www.yjlww.com

[7] Ming-Hsuan Yang, David J. Kriegman, Narendra Ahuja. Detecting Faces in Images: A Survey. IEEE Transactions on Pattern Analysis and Machine Intelligence, 2002,VOL. 24, NO. 1

[8] Microsoft. Microsoft DirectX Media SDK Document. Redmond wash - ington : Microsoft press ,2000.http://www.yjlww.com

[9] 徐慧,《Visual C++数字图像实用工程案例精选》,人民邮电出版社,2004 [10] 胡晓军,邓波,高宏伟等《Visual C++高级开发范例解析》,电子工业出版社,2002

本文来源:https://www.bwwdw.com/article/57ko.html

Top