基于DirectShow的证件图像采集设计与实现*

2010-05-11 03:48李宇谭洪舟
自动化与信息工程 2010年3期
关键词:视频流预览静态

李宇 谭洪舟

1 引言

在Windows下开发视频采集系统时,通常有3种视频采集的方法。分别为基于VFW(Video for Windows)、基于DirectX的DirectShow部件和基于视频采集设备提供的SDK(Software Development Kit,软件开发包)。

VFW 是微软公司于 1992年推出的专门针对Windows平台上视频处理的软件包,它不依赖于专用的硬件设备,提供了通用的数字视频开发方案。使用VFW的优点是它随从Windows操作系统一起安装,可执行文件不需要附带额外的库文件就可以运行。文献1用VFW实现了视频图像叠加与播放。目前新的采集设备通常使用WDM(Windows Driver Model)驱动模型,而VFW无法支持这种驱动模型,因而无法驱动相应的采集设备。这大大限制了VFW在视频多媒体采集中的应用。此外,VFW的工作效率不高,这对于采集视频质量日渐提高、数据量突飞增长的新设备来说明显不吻合。

SDK是采集卡厂家提供的开发视频监控系统的一组库函数,使用SDK库函数,用户可以在不了解视频压缩、回放、网络与存盘操作等技术的前提下,进行视频程序开发(SDK中通常包含了这些技术的实现)。但是不同厂商提供的采集卡SDK通常无法兼容,因此编写的程序无法移植到新的环境中。而且对于常见的摄像头,则不一定会有提供相应的SDK。

DirectShow是基于Windows平台的流媒体处理开发包,它与DirectX一起发布。DirectShow对流媒体的捕捉、回放提供了强大的支持,使用它还可以在基于WDM驱动的采集卡上进行数据捕捉。使用DirectShow能够简单、高效地对流媒体进行处理,降低处理的复杂性。不过,运行基于DirectShow开发出来的应用程序要求PC机系统中安装有DirectX模块。一般情况下Windows操作系统中都捆绑了对应版本的DirectX,使得用户使用起来非常方便。相对前两种方法,DirectShow简单易用,比较适合于Windows环境下的开发图像采集系统。

2 DirectShow捕捉原理

DirectShow是一套完全基于组件对象模型(Component Object Model,COM)的应用系统。图1是 DirectShow的系统图[2]。图中央最大的一块即为DirectShow系统。虚线以下是Ring 0特权级别的硬件设备,虚线以上是Ring 3特权级别的应用层。DirectShow系统位于应用层中。它使用一种叫做Filter Graph的模型来管理整个数据流的处理过程;参与数据处理的各个功能模块叫做Filter;各个Filter在Filter Graph中按一定的顺序连接成一条“流水线”协同工作[3]。

图1 DirectShow系统图

DirectShow通过Filter与各式各样的设备,包括本地文件系统、TV调谐器、视频采集卡、编解码器、显示器、声卡等进行通信。因此DirectShow将应用程序与设备之间的多样性和复杂性隔离开[4]。

按照功能来分,Filter大致分为3类:Source Filter,Transform Filters和Rendering Filters。Source Filters主要负责获取数据,数据源可以是文件、Internet计算机里的采集卡(WDM驱动的或VFW 驱动的)、数字摄像机等,然后将数据往下传输;Transform Filters主要负责数据的格式转换分离/合成,解码/编码等,然后将数据继续往下传输;Rendering Filters主要负责数据的最终去向——将数据送给显卡、声卡进行多媒体的演示,或者输出到文件进行存储。每一个DirectShow的Filter至少有一个连接点,也称为引脚(Pin)。Filter之间的连接和媒体数据的传送正是通过Pin的连接得以实现的。

3 基于DirectShow图像采集中的类设计

Filter是DirectShow应用程序数据处理的基本单元,各个 Filter在 Filter Graph中按一定的顺序连接成一条“流水线”协同工作。DirectShow使用一种叫做 Filter Graph的模型来管理整个数据流的处理过程。基于面向对象程序设计的思想,我们的图像采集模块中设计了下面三个类对数据和操作进行封装:CVGraph类,CVSampleGrabberCB类及CVCaptureGraph类。整个捕捉模块的UML类框图如图2所示。

图2 图像采集模块类框图

3.1 CVGraph类和CVGraphEventHandle类

CVGraph类主要是实现一些对所有与 Filter Graph相关的应用中所必需的操作的封装,通常作为其他针对特定领域应用的Filter Graph类的父类。如与采集应用相关的CVCaptureGraph即是继承于该类。

这个类主要记录一些维护与 Filter Graph相关的一些接口的指针,如图2中所示的:m_pGraph、m_pBuild、m_pControl和m_pEvent;还有视频预览显示窗口句柄及事件通告窗口句柄,如 m_hVidWin (视频窗口句柄,可以为NULL,表示不显示)和m_hWnd(事件窗口句柄,通常不为NULL)。

该类相关的成员函数都是与设置视频显示窗口,事件通告窗口,启动/停止Filter Graph相关的操作。值得注意的是该类的事件处理机制。从图2可知CVGraph依赖于类CVGraphEventHandle,在CVGraph::HandleEvent中调用了后者的成员函数。

CVGraphEventHandle是一个定义为应用程序响应DirectShow的Filter Graph事件的回调的类。它的作用为:

(1)、 在应用程序窗口类中继承该类;

(2)、调用CVGraph::SetEventWindow以设置事件响应窗口;

(3)、当应用程序从消息泵中得到CVGraph::WM_GRAPH_MESSAGE消息的时候, 以所实现的窗口类作为参数(根据C++类继承机制,这是合法的[5])调用 CVGraph::HandleEvent,其内部调用了CVGraphEventHandler::OnGraphEvent函数,根据多态性,这时即将调用在窗口类中定义的 OnGraphEvent函数。

3.2 CVSampleGrabberCB类

在本模块中,帧数据的获取采用的是DirectShow自身提供的 SampleGrabber Filter(对应的类 ID为CLSID_SampleGrabber)。使用这个Filter时需要对其回调机制进行设置,其中设置的回调参数中就有具有ISampleGrabber接口的类。我们设计的CVSampleGrabberCB类即为一例。应用程序通过SetCallback(pSampleGrabberCB,1)设置回调函数,其中参数1表示使用BufferCB这个方法进行回调。

该类还用一个枚举的类型 FUNCTIONARITY表示该SampbleGrabber Filter具有的功能:

enum FUNCTIONARITY

{ NON_FUN = NO_FUNCTION,

SNAP_ONLY = SG_SNAP,

ALIGN_ONLY = SG_ALIGN,

SNAP_ALIGN = SG_SNAP | SG_ALIGN

};

由此可见,一个SampleGrabber Filter具有SNAP(即单帧拍摄)或(和)ALIGN(对准,主要用于下一章中广角镜头畸变建模)功能。

回调的过程的流程图如图 3所示(即BufferCB接口函数的实现)。

上述过程通告给应用程序的自定义消息为:WM_CAPTURE_BITM AP_FOR_PROCESSING 3.3 CVCaptureGraph类

该类继承于CVGraph类,利用DirectShow中的ICaptureBuilder2接口提供的智能连接功能RenderStream进行Filter间互连。智能连接意即客户只需要根据不同的应用场景,添加所需要的 Source Filter,Transform Filter和 Rendering Filter,系统便会自动实现连接。

在采集图像过程中,应用程序可能提供不同的参数决定最终的工作模式,因此程序中定义了一个新的类型:

typedef unsigned long WORK_MODE;

并且使用宏定义语句定义了一些工作模式,不同模式对应的Filter Graph是不同的。如果该捕捉类以后需要进行扩展,仅需要使用类似的方法添加宏定义即可。下面列出其中的几个宏定义语句:

#define NULL_MODE (EMPTY_MODE) //空模式

图3 BufferCB回调流程图

#define PREV_WIN (PREVIEW |RENDER_WINDOW) //用户指定窗口预览模式

#define PREV_WIN_SNAP (PREVIEW |RENDER_WINDOW | SNAP) // 使用用户指定的窗口进行预览,且提供单帧捕捉功能

#define PREV_WIN_SNAP_ALIGN(PREVIEW|RENDER_WINDOW|SNAP| ALIGN) // 使用用户指定的窗口进行预览,且提供单帧捕捉、对准功能

#define PREV_WIN_SNAP_STILL (PREVIEW |RENDER_WINDOW | SNAP | STILL_PIN) // 使用用户指定的窗口进行预览,且利用静态引脚捕捉帧数据

#define PREV_NULL_RENDER_SNAP_STILL(PREVIEW|SNAP | STILL_PIN) // 不进行预览显示且利用静态引脚捕捉帧数据

RecommendedWorkMode( )根据用户所喜好的配置与及采集设备本身的硬件工作能力(如是否具有静态引脚)返回一种系统推荐的工作模式;

RenderPreview( )函数完成只有预览功能的 Filter Graph的建立;

RenderAviCapture( )函数完成将视频流采集到 AVI文件的Filter Graph的搭建,在本系统中并未使用;

RenderStillPin( )完成使用静态引脚实现单帧数据采集的Filter Graph中与静态引脚相关的子Filter Graph的搭建;

RenderWholeGraph( )根据用户设置的工作模式搭建整个Filter Graph。

4 图像帧数据采集

4.1 采集流程

从摄像头中获取帧数据最常见的办法是从预览的视频流中插入一个SampleGrabber Filter,这样由于视频流中的每一帧数据都会经过该Filter,只要让该Filter通过回调机制通告上层应用程序进行对当前帧进行处理便可实现图像采集。此外,现在的 USB摄像头都是基于WDM,并且有一些还提供了静态引脚捕获(Still Pin Capture)这种类似于相机快门的拍照接口(通常这种接口拍摄到的图片会比视频流中取出一帧的图片的质量要好)。不管是视频流中进行帧数据捕获,还是从静态引脚进行捕获,均采用回调函数的形式将帧数据的传递给应用程序,这两种情况均是通过在 Filter Graph中插入SampleGrabber Filter来实现的[6]。上层应用程序只需要按图4所示的流程进行调用即可实现所需的功能。

由此,我国当下通过“一带一路”倡议推行国际经贸合作,需要转变理念和方式,重视法律合作,适时跟上世界发展趋势,借着法律自发趋同的世界法律合作潮流开展国际经贸活动,实现“一带一路”所涉国家长久的互利共赢。该理念和方式的转变也是我国的必然选择。

图4 图像捕获模块调用流程

4.2 两种方法对比分析

由于DirectShow的视频采集与上层应用程序的工作线程逻辑上是独立的两个线程,它们按照设定的工作模式进行工作。虽然两种帧数据的获取均是通过插入Sample Grabber Filter并回调应用程序来实现,但从技术细节上看还是存在不同之处:

(1)、对于从预览视频流中获取帧数据的方式来说,摄像头硬件设备每产生一帧视频并且通告操作系统后,操作系统根据负载的情况,尽可能通过驱动程序获取该帧数据并通过设定的预览 Filter路径进行处理。但是允许在负载较重的情况下丢弃部分预览视频帧。这样,由于预览视频流源源不断地从摄像头设备处产生,按前述的回调方式,DirectShow采集线程会不断地发送消息给应用程序窗口。因而上层应用程序必须进行相应的过滤操作。

(2)、在使用静态引脚捕获帧数据时,只有用户发送了捕获命令后,才能够触发摄像头进行拍摄,在拍摄完成之后才发送消息通告应用程序窗口。因而这种情况下不存在DirectShow捕获线程频繁发送通告消息。从逻辑上讲,只有用户启动捕捉命令,DirectShow在收集完数据后才发送消息,这类似于照像机中的快门。使用静态引脚捕获帧数据非常节省系统资源,适合当系统负载较重的时候使用。

图5与图6分别描述了图形用户界面下采集模块在通过预览视频流获取帧数据和静态引脚获取帧数据的UML时序图,其中采集命令的发送都是由用户指定。

图5 预览视频流获取帧数据的UML时序图

图6 静态引脚获取帧数据的UML时序图

5 实验

本图像采集模块用于我们开发的证件信息识别系统中实现证件的图像输入。实验采用了Windows XP操作系统和Visual C++ 6.0作为开发平台,硬件为普通市面USB摄像头和Lenovo 奔腾双核CPU的启天M6900 PC机器。该识别系统具有镜头的畸变补偿功能。图7是用本图像采集模块得到的身份证原始图像。由于采集到的图像会发生桶形失真,直接对采集到的证件图像进行OCR会影响识别效果,系统要先对采集到的图像进行样条函数畸变补偿校正[8],处理后的身份证图像为图8所示。最后对身份证图像进行识别采集到证件的信息内容(图 9)。从整个采集识别情况来看,本图像采集模块能有效地实现图像的输入功能,满足证件信息识别的图像要求。

图7 桶形失真原始图像

图8 使用双线性插值法的畸变补偿效果

图9 证件采集识别效果

6 结束语

本文设计了用于图像采集的 CVGraph类,CVSampleGrabberCB类与CVCaptureGraph类,并基于这些类开发了使用USB摄像头的图像采集模块。通过自行开发的证件信息采集系统测试了该图像采集模块输入功能。采集到的图像达到了实际图像应用系统的要求。

[1] 徐从东,罗家融,王树坤.基于VFW 的视频图像叠加与播放方法[J].计算机工程与设计,2007,28(1):100-102

[2] DirectX. Documentation for C++ [EB/OL]. Microsoft Corporation,2005

[3] 陆其明.DirectShow开发指南[M]. 北京:清华大学出版社. 2003

[4] Mark D. Pesce. Programming Microsoft DirectShow for Digital Video and TV [M]. Washington: Microsoft Press. 2003.04

[5] David J.Kruglinski, Scot Wingo, George Shepherd著, 希望图书创作室译. Visual C++ 6.0技术内幕(第五版)[M] . 北京:希望电子出版社. 1999.05

[6] Eric Rudolph. How To Get Data from a Microsoft DirectShow Filter Graph [EB/OL]. http://msd n.microsoft.com/zh-cn/library/ms867162(en-us).aspx

[7] 孙鑫, 余安萍. VC++深入详解[M]. 北京:电子工业出版社.2006.06

[8] 王占斌, 赵辉, 陶卫, 唐燕. 广角镜头桶形畸变的样条函数修正方法[J]. 光电工程. 2008.35(4). 140-144

猜你喜欢
视频流预览静态
边缘实时视频流分析系统配置动态调整算法研究
最新进展!中老铁路开始静态验收
静态随机存储器在轨自检算法
新品预览
基于视频流传输中的拥塞控制研究
铁路货场智能大门集装箱全景图像采集方法研究
11月在拍电视剧预览表
美国视频流市场首现饱和征兆
油罐车静态侧倾稳定角的多体仿真计算
bauma China 2014展前预览