以文本方式查看主题 - 计算机科学论坛 (http://bbs.xml.org.cn/index.asp) -- 『 C/C++编程思想 』 (http://bbs.xml.org.cn/list.asp?boardid=61) ---- VC++6.0实现视频数据实时获取的探讨 (http://bbs.xml.org.cn/dispbbs.asp?boardid=61&rootid=&id=72389) |
-- 作者:卷积内核 -- 发布时间:2/27/2009 2:29:00 PM -- VC++6.0实现视频数据实时获取的探讨 摘要 在VC++6.0中利用VFW技术实现视频数据实时获取的过程中,针对回调函数的处理中所碰到的问题、图像采集中原始数据的获取以及捕获窗口的建立的问题进行了详细的讨论,并给出了具体的解决办法。 关键词 VFW 图像采集 回调函数 以光学为基础,融光电子学、计算机技术、激光技术、图像处理技术等现代科学技术为一体的图像测量技术在测量领域中形成了新的测量技术,基于数字图像处理技术的图像测量系统目前已广泛应用于几何量的测量、航空等遥感测量、精密复杂零件的微尺寸测量和外观测量,以及光波干涉图、应力应变场状态分布等和图像有关的技术领域中。在基于数字图像处理技术的图像测量系统中,必须解决的问题就是图像采集,即图像数据的获取,采集的图像数据用于后期的图像处理。 视频图像捕获一般来讲有两种方法,一种是利用视频捕获卡所附带的SDK开发工具,这种捕获方法的实现是与设备有关的,依赖于视频捕获卡与摄像头的类型,不利于灵活应用;另外一种捕获方法是Microsoft的Visual C++自从4.0版就开始支持Video for Windows(简称VFW),这给视频捕获编程带来了很大的方便,利用VFW技术的可以提高视频捕获的灵活性,减少了对视频设备的依赖。在VC++6.0中,含有MCIAVI、DRAWDIB、AVIFILE和AVICAP等组件。通过它们之间的协调工作,可以完成播放、编辑、文件管理和视频捕获等功能,为视频图像处理和分析带来非常大的便利,本文就利用VFW进行视频数据的实时采集中的碰到的几个实际问题进行探讨。 VFW库函数简介 视频数据的实时采集主要是通过调用AVICap32.dll创建AVICap窗口类 ,由AVICap窗口类中的消息、宏函数、结构以及回调函数来完成。 AVICap在捕获视频方面具有明显的优势,它能直接访问视频缓冲区,不需要生成中间文件,实时性很高,它也可将数字视频保存到事先建好的文件中。实际应用表明,通过这种方法,提高了视频采集的效果和程序运行的效率,同时也减少了对硬件的依赖性,提高了程序的兼容性和移植性。 VFW的视频采集功能主要包括捕获视频流至AVI文件(capCaptureSequence)、捕获视频流至缓存(capCaptureSequenceNofile)、捕获视频流至AVI文件(capCaptureSingleFrame)、本地预览(capPreview/capOverlay)和捕获单帧预览(capGrabFrame/capGrabFrameNoStop)等。VFW还提供了回调函数 ,允许应用程序精确控制视频流的捕获、检测错误、监控状态变化 ,以及在捕获两帧数据的空隙和每捕获新帧时对实时数据进行处理。 |
-- 作者:卷积内核 -- 发布时间:2/27/2009 2:29:00 PM -- 几个实际问题的探讨 1、回调函数处理的问题 回调函数是至今为止最有用的编程机制之一。在Windows中,回调函数更是窗口过程、钩子过程、异步过程调用所必需的,在整个回调过程中自始至终地使用回调方法。人们可以注册回调方法以获得加载/卸载通知,未处理异常通知,数据库/窗口状态修改通知,文件系统修改通知,菜单项选择,完成的异步操作通知,过滤一组条目等等。在VFW中有几条这样的宏函数,如用于设置在发生某事件后能作出反应的回调函数的宏函数,它和中断服务机制很相似,条件一满足,程序会自动进入相应的回调函数体中,该函数究竟要做些什么,全由开发者借助其参数自行编制程序来确定。利用VFW获取实时视频数据通常可以运用视频处理的回调机制(call-backmechanism) 获得实时数据缓冲区的首址和长度并对图像数据进行处理,同时也可以进行视频数据的直接传输,在这一方面很多文章都作了具体的介绍。但是按照大多数文章的介绍,在具体的应用过程中,对回调函数作如下定义时,程序总是无法通过编译:
{ (1) 不使用成员函数,直接使用普通C函数,为了实现在C函数中可以访问类的成员变量,可以使用友元操作符(friend),在C++中将该C函数说明为类的友元即可。这种处理机制与普通的C编程中使用回调函数一样。 (2) 使用静态成员函数,静态成员函数不使用this指针作为隐含参数,这样就可以作为回调函数了。静态成员函数具有两大特点:其一,可以在没有类实例的情况下使用;其二,只能访问静态成员变量和静态成员函数,不能访问非静态成员变量和非静态成员函数。由于在C++中使用类成员函数作为回调函数的目的就是为了访问所有的成员变量和成员函数,如果作不到这一点将不具有实际意义。解决的办法也很简单,就是使用一个静态类指针作为类成员,通过在类创建时初始化该静态指针,如pThis=this,然后在回调函数中通过该静态指针就可以访问所有成员变量和成员函数了。这种处理办法适用于只有一个类实例的情况,因为多个类实例将共享静态类成员和静态成员函数,这就导致静态指针指向最后创建的类实例。为了避免这种情况,可以使用回调函数的一个参数来传递this指针,从而实现数据成员共享。这种方法稍稍麻烦,这里就不再赘述。 因此,可以对回调函数作如下定义: |
-- 作者:卷积内核 -- 发布时间:2/27/2009 2:30:00 PM -- 2、图像采集中的问题 视频数据的采集是整个应用的关键,根据应用的不同可以将视频帧采集到的文件或采集的缓存直接加以处理。利用VFW获取实时视频数据通常可以运用视频处理的回调机制(call-backmechanism) 获得实时数据缓冲区的首址和长度并对图像数据进行实时处理,但是在这个过程中图像处理程序不能太长,否则视频显示不流畅。另外,在实际采集过程中,有些图像采集卡驱动程序对通过回调机制所获取的数据进行了压缩,比如DC10,而在图像测量系统高精度的要求,压缩后的图像数据直接影响以后的图像处理工作。通过采用以下两种典型技术可以实现将没有压缩的视频帧的图像数据的采集。 (1) 通过研究发现,尽管图像采集卡驱动程序对通过回调机制所获取的数据进行了压缩,但是利用VFW中的capEditCopy( )宏函数将帧图像缓冲区中的图像数据拷贝到剪贴板上时,并没有压缩图像数据,因此可以不采用回调机制而直接利用capGrabFrameNoStop()捕获一帧图像,然后将数据拷贝拷贝到剪贴板上,再通过DIB(Device Independent Bitmap)操作获取内存中图像数据首地址,进行后续的图像数据处理。具体的代码片段如下: //获得capEditCopy( )拷贝到剪贴板中的图像数据句柄,通过CF_DIB参数指定数据 (2) 利用capFileSaveDIB将缓冲区中的图像数据转化为DIB位图直接保存为文件,需要处理时,再读取位图中的图像数据到内存进行后续的处理。这种方式因为有一个文件存储和读取的延迟,对于实时的图像处理来说,响应速度比前者要稍慢,经过多次实验证明,只要图像处理算法的计算量不是很大,仍然可以保证比较好的实时性。 3、图像采集窗口建立的问题 但是在实际应用过程中,应用程序可能会基于单文档(SDI)、多文档或者是基于对话框的界面,由于三种类型的不同,捕获窗的具体创建应根据具体要求而有所区别。不管是采用哪种类型,根据实时视频的显示的具体要求,关键是如何获取捕获窗口的父窗口句柄。通常捕获窗口的创建可以如下两种方式: (1)获取动态创建的父窗口的句柄,动态的创建捕获窗口。具体的代码片段如下: CFrameWnd m_wndSource; (2)获取显示的实时视频窗口的句柄,静态的创建捕获窗口。具体的代码片段如下: m_hCapWnd = capCreateCaptureWindow((LPSTR)TEXT("视频捕捉测试程序"),WS_CHILD|WS_VISIBLE, 结束语 利用VFW技术实现视频数据实时获取,提高了视频采集的效果和程序运行的效率,同时也减少了对硬件的依赖性,提高了程序的兼容性和移植性。在很多基于数字图像处理技术的图像测量系统中都使用了这种方法。本文就具体应用中所碰到的实际问题进行了详细的讨论,并给出了具体的解决办法。 |
-- 作者:beckson -- 发布时间:4/27/2009 10:09:00 PM -- thanks!~~~~~~~~~~~~ |
-- 作者:秋十三 -- 发布时间:6/9/2009 11:31:00 PM -- 不错哦!!!!! |
W 3 C h i n a ( since 2003 ) 旗 下 站 点 苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》 |
46.875ms |