繁体   English   中英

DirectShow和openCV。读取视频文件并处理

[英]DirectShow and openCV. Read video file and process

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

请原谅我糟糕的英语。

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

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

Source -> Sample Grabber -> Null renderer

下载 graphEdit 或 GraphEdit+,您可以直观地表示这些过滤器。 作为示例,我继续构建了一个从本地网络摄像头到连接到 null 渲染器的样本采集器的图形。 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 以了解如何执行此操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM