胡章平,汪维华
(重庆文理学院计算机学院,重庆 永川 402160)
在图像处理、电视视频监控、视频会议、可视电话等视频处理应用中,根据应用需求获取数字视频的某一关键帧是前提条件.因此,视频帧的抓取是图像处理与视频处理的关键技术之一.很多视频播放软件或视频编辑软件都提供了抓帧功能,利用这类软件,视频工作者可以很轻松地将一部电影某一时刻的帧抓取出来并保存为图片文件,然后进行相应的加工处理.然而,这类软件却不能很好地与我们的应用程序融合为一体,只能在应用程序与视频播放软件或视频编辑软件之间进行手工协调,大大降低了处理的速度和有效性.因此,需要自己编写程序实现视频的抓帧功能,目前关于这方面的研究比较多.
文献[1-6]介绍了基于 VFW(Video for Windows)技术与VC++平台下的视频捕获与抓帧的应用与实现.VFW是Microsoft公司推出的关于数字视频的一个软件开发包,其核心是AVI(Audio Video Interleave)文件标准.围绕AVI文件标准,VFW包含了一整套完整的视频采集、压缩、解压、回放和编辑的应用程序编程接口(后简称 API)[1].
DirectShow是微软公司在 ActiveMovie和Video for Windows的基础上推出的新一代基于COM(Component Object Model)的流媒体处理的开发包,与DirectX开发包一起发布.它广泛地支持各种媒体格式,包括 asf、mpeg、avi、dv、mp3、wave等等,使得多媒体数据的回放变得轻而易举.另外,DirectShow还集成了DirectX其它部分(比如DirectDraw、DirectSound)的技术,直接支持DVD的播放,视频的非线性编辑,以及与数字摄像机的数据交换.
Directshow是基于模块化的,每个功能模块都采取COM组件方式,称为Filter,各个Filter在Filter Graph中按一定的顺序连接成一条“流水线”协同工作.按照功能来分,Filter大致分为3类:Source Filters、Transform Filters和 Rendering Filters.Source Filters主要负责取得数据,数据源可以是文件、因特网或者计算机里的采集卡、数字摄像机等,然后将数据往下传输;Transform Fitlers主要负责数据的格式转换和传输;Rendering Filtes主要负责数据的最终去向.
利用DirectShow实现视频的抓帧功能有许多方法[11]:
1)使用 Sample Grabber Filter方法,该方法灵活但是复杂,对程序开发人员要求较高,文献[11]详细讨论了该方法的使用.
2)使用IBasicVideo::GetCurrentImage接口方法:
HRESULT GetCurrentImage(long* pBuffer-Size,long*pDIBImage);
目前部分企业的管理模式落后,而抄核收的各项环节都紧密相关,前项工作的错误就将造成整个工作出现误差。因为管理模式落后,各项环节抄表、核算以及收费等没有统一的标准,并且不能对存在的数据进行核对,导致电力营销工作效率下降。管理人员应该有所针对,着重对薄弱环节进行加强,例如,优化用户耗电数据的总结环节,依据实际情况,辅之合理的梯度抄核收标准,规范各项工作的管理流程,改变落后管理模式的现状。
其中:pBufferSize为缓冲区大小;pDIBImage为指向存储DIB格式图像缓冲区的指针.
如果使用传统的VideoRenderer,那么使用GetCurrentImage方法抓图将是不可靠的.因为如果VideoRenderer使用 DirectDraw加速,这个函数调用会失败;而且调用这个函数时,Video Renderer必须处于暂停状态.但如果使用VMR9,则没有上述这些限制[11].
3)最简单的方法是直接抓屏或是使用DirectX中的 Media Detector(MediaDet)对象.本文将详细探讨该方法的抓帧功能的实现原理与具体方法.
MediaDet对象可以从媒体源文件中获取媒体的格式信息,也可以从视频源中抓取所有的视频帧,如果这个文件是可以搜索的,那么可以根据特征信息获取该文件中任意帧图像.
Media Detector不是一个过滤器,应用程序不需要使用过滤图形管理器或者创建过滤图形,可以通过调用CoCreateInstance来创建Media Detector对象.在Media Detector内部,它会创建一个包含了Sample Grabber过滤器的过滤图形.为了得到图形,Media Detector会搜索和暂停过滤图形,然后从Sample Grabber过滤器中获得一幅BMP图像.
应用程序和Media Detector通讯是通过IMediaDet接口来实现的.通过IMediaDet接口接收媒体文件的数据流以及每个流的媒体类型、持续时间和帧率等信息.该接口也包含了从视频流中抓取视频帧在内的方法,常用的方法如表1所示.
表1 IMediaDet接口常用方法
视频帧的捕获功能流程图如图1所示.
图1 捕获流程
为了能在CJHJ开发平台下利用IMediaDet接口获取媒体文件信息与实现视频帧抓取,首先必须引入命名空间DexterLib,即using DexterLib.
为了打开视频流,需创建一个MediaDet对象,并通过对象的文件名同多媒体文件关联,语句如下:
IMediaDet mediaDet=new MediaDetClass();mediaDet.Filename=videoFile;
由于媒体类型比较多,因此在获取媒体流之前必须首先要知道所需要的媒体类型.媒体类型的获取是通过MediaDet对象的StreamMediaType实现的,如:
利用MediaDet的GetBitmapBits方法能够截取某一时间的图片,该方法没有直接提供获取某帧的图像,因此主要是利用视频流的总体播放时间及其播放速度,求出第i帧的时间位置,进而抓取该帧图片.计算总帧数如(1)式所示.
其中:
streamLength——MediaDet对象属性,描述整个视频的播放时间(单位秒);
FrameRate——MediaDet对象属性,描述播放速度(单位是帧/秒);
第i帧的播放时间如(2)式.
抓取第i帧的方法为:GetBitmapBits(iTime,ref bufferSize,ref*frameBuffer,Width,Height).其中参数的含义为:
bufferSize—缓冲区大小;
frameBuffer—保存位图的缓冲区;
Width—位图的宽度;
Height—位图的高度;
得到第i帧图片后,为了保存或者是加工图片,需要知道帧的宽度、高度等基本信息.使用Marshal.PtrToStructure方法可以获取媒体基本信息,包括:视频流的数据速率、帧的平均显示时间、位图基本信息等.获取帧信息的代码如下:
其中,VIDEOINFOHEADER结构如下:
本文分析研究了传统的VFW技术与VC++平台下的视频捕获,讨论了新技术DirectShow的视频捕获方法,重点探讨利用IMediaDet接口在CJHJ平台中实现视频捕获的技术,并利用该技术实现了一个视频抓取与回放系统,通过程序还能够控制播放的速度,达到了很好的效果.
[1]易小波,周海伟.VC平台下视频捕获的实现[J].衡阳师范学院学报,2006,27(6):75-77.
[2]李国芳.在 VC++6.0中实现视频捕获编程[J].教育信息化,2009(9):2-4.
[3]于晓康,柴乔林.基于VC++的可控视频回放系统[J].计算机应用,2003,23(12):326-328.
[4]彭凯,卢益民.VC++实现远程监控系统中视频捕捉[J].电视技术,2001,234(12):86-87.
[5]郭新军.用VC++实现视频监控录像[J].微电子学与计算机,2004,21(4):58-59,87.
[6]龚伟.基于VFW的远程专家会诊系统中的实时音视频捕获[J].计算机科学,2007,34(11):127-128.
[7]倪绪能,胡涛,张志刚.利用VC++实现基于Direct-Show的视频捕获[J].电视技术,2003,256(10):15-17.
[8]许晓勇,唐小妹,王飞雪.基于分段相关-视频积累方法的伪码串行捕获优化设计[J].信号处理,2009,25(9):1338-1341.
[9]王国富,陈良益,何俊华.星载光电仪器捕获跟踪视频处理系统设计[J].传感器与仪器仪表,2007,23(8-1):139-141.
[10]陈昱,王博亮,谢杰镇.基于DirectShow的眼前节图像采集系统的设计[J].厦门大学学报:自然科学版,2005,44(4):503-506.