如何用Directshow采集摄像头图像

      很多人接触Directshow都是从采集摄像头开始的,因为用Directshow做采集是Windows平台上最通用、最成熟的做法。 现在市场上大多数的摄像头和采集卡在Windows系统上的驱动基于WDM架构,微软定义了采集卡设备与上层程序间的通信驱动接口,这已经成为一种标准,因此,控制摄像头和采集图像基本都通过Directshow框架来实现。VLC,FFmpeg等软件支持采集摄像头图像其实也是通过DShow,只是做了一层封装。

     如果我们要做一个采集摄像头应用,要实现采集图像数据(即获得图像的YUV或RGB数据)的功能,应该如何开发呢?很多初学者会想到参考Directshow SDK sample里面的例子----AMCap,因为这个例子也是支持采集摄像头图像的。不过,它不支持直接获得原始图像数据。AMCap支持三种工作模式:预览模式,采集模式,预览+采集。预览模式就是把采集到的图像显示到窗口中;而采集模式是把采集到的视频录制成一个AVI文件。

    在预览模式,AMCap创建的Directshow链路图如下:


   在预览+采集模式下,AMCap创建的Directshow链路图如下:


      在预览模式,AMCap只是把(USB Camera)Capture Filter采集到的图像传给视频渲染器Video Renderer,Video Renderer负责把图像显示到Renderer捆绑的窗口上。

     而预览+采集模式下,从Capture Filter的输出Pin输出两条链路,一条是预览:Smart Tee 0001->LAVVideo Decoder -> Video Renderer,另外一条是保存文件:Smart Tee ->AVI Mux -> File Writer,其中File Write把收到的图像写到一个AVI文件中(123.avi)。但是无论工作在预览模式还是采集模式,AMCap都没有接口获得原始图像数据。

     虽然通过这个例子不能实现我们需要的功能,但是这个例子对如何使用Capture Filter做预览和录制还是很有参考价值的。

    有些读者可能会想:如果我们实现一个自定义Filter,把它连到Capture Filter后面,并且实现了一个回调,当收到Capture Filter来的Sample数据的时候就把它传给应用层,不是可以做到获得图像的数据了吗?

     没错,思路的确是对的。我们可以实现一个自定义Filter,但是自己开发Filter比较麻烦,建议用更简单的方式,事实上微软已经为我们提供了一个Sample Grabber的Filter,这个Filter有抓取数据和设置回调函数的功能。Sample Grabber一般已经安装到系统中,如果没有安装,大家可以去到Directshow SDK目录找到这个Sample工程(路径是:\SDK (C++)\Samples\C++\DirectShow\Filters\Grabber),然后编译,注册。

  关于Sample Grabber的用法,DirectX SDK的官方文档已经描述得很清楚,我这里摘录一下:

Using the Sample Grabber

The Sample Grabber filter is a transform filter that can be used to grab media samples from a stream as they pass through the filter graph.

If you simply want to grab a bitmap from a video file, it is easier to use the Media Detector (MediaDet) object. See Grabbing a Poster Frame for details. The Sample Grabber is more flexible, however, because it works with nearly any media type (see ISampleGrabber::SetMediaType for the few exceptions), and offers more control to the application.

Add the Sample Grabber to the Filter Graph

Start by creating an instance of the Sample Grabber filter and adding it to the filter graph:

// Create the Sample Grabber.
IBaseFilter *pGrabberF = NULL;
hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
    IID_IBaseFilter, (void**)&pGrabberF);
if (FAILED(hr))
{
    // Return an error.
}
hr = pGraph->AddFilter(pGrabberF, L"Sample Grabber");
if (FAILED(hr)
{
    // Return an error.
}

Query the Sample Grabber for the ISampleGrabber interface.

ISampleGrabber *pGrabber;
pGrabberF->QueryInterface(IID_ISampleGrabber, (void**)&pGrabber);

Set the Media Type

When you first create the Sample Grabber, it has no preferred media type. This means you can connect to almost any filter in the graph, but you would have no control over the type of data that it received. Before building the rest of the graph, therefore, you must set a media type for the Sample Grabber, by calling the ISampleGrabber::SetMediaType method.

When the Sample Grabber connects, it will compare this media type against the media type offered by the other filter. The only fields that it checks are the major type, subtype, and format type. For any of these, the value GUID_NULL means "accept any value." Most of the time, you will want to set the major type and subtype. For example, the following code specifies uncompressed 24-bit RGB video:

AM_M
  • 3
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值