DirectShow和openCV。阅读视频文件和流程

时间:2012-04-05 16:11:47

标签: c++ opencv directshow

我在StackOverflow上使用了搜索,但我找不到答案。我正在开发一个应用程序并使用OpenCV,但我需要使用不同的视频(大多数是* .avi),所以我决定使用DirectShow。我能够创建简单的应用程序,但我找不到任何解释如何从* .avi获取帧,而不创建ActiveWindow。事实上,我只需要使用DirectShow阅读视频,然后我将使用OpenCV来处理和显示视频。 任何帮助赞赏。提前致谢!

对不起我糟糕的英语。

2 个答案:

答案 0 :(得分:2)

使用NULL渲染创建图形。另请参阅directshow SDK中的示例抓取器示例。它显示了如何抓取图形的框架。然后,您可以将框架传递给openCV进行处理。

答案 1 :(得分:1)

基本上你想连接这样的东西:

Source -> Sample Grabber -> Null renderer

下载graphEdit或GraphEdit +,您可以直观地表示这些过滤器。作为一个例子,我继续从我的本地网络摄像头到连接到空渲染器的样本抓取器构建了一个图形。 GraphEdit +生成的C#代码是:

//Don't forget to add reference to DirectShowLib in your project.
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices.ComTypes;
using System.Runtime.InteropServices;
using DirectShowLib;

namespace graphcode
{
class Program
{
    static void checkHR(int hr, string msg)
    {
        if (hr < 0)
        {
            Console.WriteLine(msg);
            DsError.ThrowExceptionForHR(hr);
        }
    }

    static void BuildGraph(IGraphBuilder pGraph)
    {
        int hr = 0;

        //graph builder
        ICaptureGraphBuilder2 pBuilder = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
        hr = pBuilder.SetFiltergraph(pGraph);
        checkHR(hr, "Can't SetFiltergraph");

        Guid CLSID_SampleGrabber = new Guid("{C1F400A0-3F08-11D3-9F0B-006008039E37}"); //qedit.dll
        Guid CLSID_NullRenderer = new Guid("{C1F400A4-3F08-11D3-9F0B-006008039E37}"); //qedit.dll

        //add Integrated Camera
        IBaseFilter pIntegratedCamera = CreateFilter(@"@device:pnp:\\?\usb#vid_04f2&pid_b221&mi_00#7&34997cec&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global");
        hr = pGraph.AddFilter(pIntegratedCamera, "Integrated Camera");
        checkHR(hr, "Can't add Integrated Camera to graph");

        //add SampleGrabber
        IBaseFilter pSampleGrabber = (IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_SampleGrabber));
        hr = pGraph.AddFilter(pSampleGrabber, "SampleGrabber");
        checkHR(hr, "Can't add SampleGrabber to graph");

        //add Null Renderer
        IBaseFilter pNullRenderer = (IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_NullRenderer));
        hr = pGraph.AddFilter(pNullRenderer, "Null Renderer");
        checkHR(hr, "Can't add Null Renderer to graph");

        //connect Integrated Camera and SampleGrabber
        hr = pGraph.ConnectDirect(GetPin(pIntegratedCamera, "Capture"), GetPin(pSampleGrabber, "Input"), null);
        checkHR(hr, "Can't connect Integrated Camera and SampleGrabber");

        //connect SampleGrabber and Null Renderer
        hr = pGraph.ConnectDirect(GetPin(pSampleGrabber, "Output"), GetPin(pNullRenderer, "In"), null);
        checkHR(hr, "Can't connect SampleGrabber and Null Renderer");

    }

    static void Main(string[] args)
    {
        try
        {
            IGraphBuilder graph = (IGraphBuilder)new FilterGraph();
            Console.WriteLine("Building graph...");
            BuildGraph(graph);
            Console.WriteLine("Running...");
            IMediaControl mediaControl = (IMediaControl)graph;
            IMediaEvent mediaEvent = (IMediaEvent)graph;
            int hr = mediaControl.Run();
            checkHR(hr, "Can't run the graph");
            bool stop = false;
            int n = 0;
            while (!stop)
            {
                System.Threading.Thread.Sleep(500);
                Console.Write(".");
                EventCode ev;
                IntPtr p1, p2;
                if (mediaEvent.GetEvent(out ev, out p1, out p2, 0) == 0)
                {
                    if (ev == EventCode.Complete || ev == EventCode.UserAbort)
                    {
                        Console.WriteLine("Done!");
                        stop = true;
                    }
                    else
                    if (ev == EventCode.ErrorAbort)
                    {
                        Console.WriteLine("An error occured: HRESULT={0:X}", p1);
                        mediaControl.Stop();
                        stop = true;
                    }
                    mediaEvent.FreeEventParams(ev, p1, p2);
                }
                // stop after 10 seconds
                n++;
                if (n > 20)
                {
                    Console.WriteLine("stopping..");
                    mediaControl.Stop();
                    stop = true;
                }
            }
        }
        catch (COMException ex)
        {
            Console.WriteLine("COM error: " + ex.ToString());
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error: " + ex.ToString());
        }
    }

    public static IBaseFilter CreateFilter(string displayName)
    {
        int hr = 0;
        IBaseFilter filter = null;
        IBindCtx bindCtx = null;
        IMoniker moniker = null;

        try
        {
            hr = CreateBindCtx(0, out bindCtx);
            Marshal.ThrowExceptionForHR(hr);

            int eaten;
            hr = MkParseDisplayName(bindCtx, displayName, out eaten, out moniker);
            Marshal.ThrowExceptionForHR(hr);

            Guid guid = typeof(IBaseFilter).GUID;
            object obj;
            moniker.BindToObject(bindCtx, null, ref guid, out obj);
            filter = (IBaseFilter)obj;
        }
        finally
        {
            if (bindCtx != null) Marshal.ReleaseComObject(bindCtx);
            if (moniker != null) Marshal.ReleaseComObject(moniker);
        }

        return filter;
    }

    [DllImport("ole32.dll")]
    public static extern int CreateBindCtx(int reserved, out IBindCtx ppbc);

    [DllImport("ole32.dll")]
    public static extern int MkParseDisplayName(IBindCtx pcb, [MarshalAs(UnmanagedType.LPWStr)] string szUserName, out int pchEaten, out IMoniker ppmk);

    static IPin GetPin(IBaseFilter filter, string pinname)
    {
        IEnumPins epins;
        int hr = filter.EnumPins(out epins);
        checkHR(hr, "Can't enumerate pins");
        IntPtr fetched = Marshal.AllocCoTaskMem(4);
        IPin[] pins = new IPin[1];
        while (epins.Next(1, pins, fetched) == 0)
        {
            PinInfo pinfo;
            pins[0].QueryPinInfo(out pinfo);
            bool found = (pinfo.name == pinname);
            DsUtils.FreePinInfo(pinfo);
            if (found)
                return pins[0];
        }
        checkHR(-1, "Pin not found");
        return null;
    }

}

}

您仍然需要实际捕获示例帧,但正如上面的帖子中所提到的,您可以查看MSDN上的sampleGrabber SDK以了解如何执行此操作。