DirectShow视频捕获

 

引言

       随着数字影像设备的普及,如数字摄像机、数字照相机、USB摄像头等等。逐渐人们已经不能满足于由厂家提供的对视频数据的处理,越来越多人希望自己来处理设备捕获的图像数据,或者将视频捕获整合到自己的程序中。

视频的捕获与实时处理是目前图像处理中的关键一步,其采集到图像质量的好坏决定着后期处理的难易,更严重的影响到产品的成败。如果从开发相应设备的驱动出发,确实能解决此类问题。但驱动开发繁琐,需要投入大量时间,一旦开发成功后,不能更换其他芯片的设备,对将来的升级换代带来不便。微软提供了相对上层的解决方案。VFWDirectshow提供了硬件不相关的一个解决方案。

市场上设备大致支持:VFW(video for Windows)WDM(Windows Driver Model)VFW因为其功能简单,实时速度差等原因,已经趋于废弃。WDM是微软推出的前者的替代模型。WDM支持更多的特性,比如直接支持电视接收、视频会议、1394接口设备、桌面摄像机、多条视频流同时输出等等[1]

VFW虽然趋于废弃,还是有相当多的设备兼容这个模式,一般的摄像头都支持。因为VFW整体结构小,设计直接明了,一般的对捕获速度要求不高的应用还是值得考虑VFW的。比如说捕获视频流中单帧中指定的区域,在Delphi中实现相当快。加入引用的VFW SDK后几十行代码就可以完成。

DirectShow

DirectShow是一个开放性的应用框架,也是一套基于COM的编程接口。DirectShow系统功能如图(1[2]。图中一大块被DirectShow占据,它基本工作原理就是“流水线”:[2] 将单元组件—filter—串联在一起,由Filter Graph Manager统一管理。系统的输入可以是本地文件系统、硬件插卡、网络等,输出可以是声卡、显卡、本地文件系统,也可向网络发送数据。实际上,计算机应用领域中的很多模块都可以和DirectShow交互。DirectShow可以实现不同格式的媒体文件的解码播放或者格式之间的相互转换,可以从本地机器中的采集设备采集音视频数据并保存为文件,可以接收、观看模拟电视等。从网络应用角度来说,DirectShow可以实现视频点播、视频会议、视频监控等。从广义上来说,DirectShow系统适合一切流式数据的处理,这些数据可以是音频、视频这样的多媒体数据,但又不局限于多媒体数据[2]

                         

具体实现

       开发环境选的是BorlandDelphi7.0, DirectShow提供的只是一堆库文件,要在Delphi中引入,必须对其进行申明。这方面工作已经有人做了,而且还做了一定程度上的封装,对使用者来说更加简便。这个就是DspackDspack是免费的资源,在MPL 1.1下发行。

       首先,必须从http://www.progdigy.com/上下载Dspack,文中用到的是Dspack 2.3.4 。包中自带详实的例子,如果要实现的功能不复杂,完全可以参考例子快速实现。

安装Dspack

              1.添加以下路径到搜索目录

                     - (DSPackDir)/src/Directx9
                    - (DSPackDir)/src/DSPack

                操作:Delphi(菜单) Tools->Envioronment Options->Library. Library Path处添加。

              2编译DirectX9_Dx.dpr(xDelphi版本号)

           3.编译DSPack_Dx.dpr(xDelphi版本号)

           4.编译并安装DSPackDesign_Dx.dpk(xDelphi版本号)

安装完毕,就可以在Delphi控件面板上Dspack目录下看到相应的控件了。

      

       文中要实现的功能是:在USB摄像头中抓取指定区域(ROI),而且在视频流上标记出要抓取的范围。具体是对于采集进来640*480的视频流中,抓取中间320*240的区域。320*240的区域必须有标记.

具体实现:

       DirectShow提供了混合两种视频流的功能VMRVideo Mixing Renderer,标记的功能可由简单把USB设备的视频流与标记的视频流混合起来实现。

       新建一个ApplicationFile->New->Application

       从控件面板的目录下拖放若干控件: TVideoWindow 用于显示视频流;TfilterGraph Tfilter  TsampleGrabber封装了的抓图控件

   枚举设备:

       SysDev := TSysDevEnum.Create(CLSID_VideoInputDeviceCategory);

判断是否有设备连接,无连接则返回。

if SysDev.CountFilters = 0 then

   begin

      ShowMessage('请连接摄像头');

   end;

创建混合图层

//create vmrbitmap

VMRBitmap := TVMRBitmap.Create(VideoWindow);

 

连接设备并显示视频流

VideoWindow.Visible := true;

   VideoWindow.FilterGraph := FilterGraph ;

   Filter.FilterGraph := FilterGraph ;

   SampleGrabber.FilterGraph := FilterGraph ; // must or cause error

   FilterGraph.Active := false ;

   FilterGraph.ClearGraph ;

   Filter.BaseFilter.Moniker := SysDev.GetMoniker(0) ; // device index

   FilterGraph.Active := true ;

   FilterGraph.Mode := gmCapture;

   with FilterGraph as ICaptureGraphBuilder2 do

   begin

RenderStream(@PIN_CATEGORY_PREVIEW, nil, Filter as IBaseFilter,SampleGrabber as IBaseFilter, VideoWindow as IBaseFilter);

   end;

   FilterGraph.Play ;

             

标记区域

       with VMRBitmap, Canvas do

  begin

    LoadEmptyBitmap(640,480,pf24bit, clSilver);

    Source := VMRBitmap.Canvas.ClipRect;

    Options := VMRBitmap.Options + [vmrbSrcColorKey];

    ColorKey := clSilver;

    Brush.Color := clSilver;

    Font.Color := clWhite;

    Font.Style := [fsBold];

    Font.Size := 10;

    Font.Name := 'Arial';

    TextOut(319, 239, '+');  //center

    TextOut(159,119,'+');    //top left

    //DrawTo(0,0,1,1,0.5);

    TextOut(159, 359, '+');  //bottom left

    //DrawTo(0, 0, 1, 1, 0.5);

    TextOut(479,119,'+');    // top right

    //DrawTo(0,0,1,1,0.5);

    TextOut(479,359,'+');    //bottom right

    DrawTo(0,0,1,1,0.5);

end;

 

抓图

SampleGrabber.GetBitmap(bitmap)

利用API函数获取指定区域

StretchBlt(Image_original.Canvas.Handle, 0, 0 , 320 , 240,

                 bitmap.Canvas.Handle, 159, 119, 320, 240, SRCCOPY);

Image_original.Repaint;

 

  程序结束完成

小结

       Dspack下开发简单的应用可以在不太熟悉DirectShow的情况下,只参照实例就可以做出一些简单的应用。对于那些赶进度确实是不错的选择,对喜欢深挖内涵的人,研究Dspack内部代码也是不无裨益的。

参考文献

[1]  陆其明DirectShow应用——视频捕捉WDM Vs VFW

[2] 陆其明DirectShow 实物精选

[3] http://www.progdigy.com/

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值