简体   繁体   English

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

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

I used search on StackOverflow, but I didn't find the answer.我使用了 StackOverflow 上的搜索,但没有找到答案。 I'm developing an application and use OpenCV, but I need to work with different videos (mostly *.avi), so I decided to use DirectShow.我正在开发一个应用程序并使用 OpenCV,但我需要处理不同的视频(主要是 *.avi),所以我决定使用 DirectShow。 I was able to create simple application, but I can't find any explanation how to get frames from *.avi, without creation of ActiveWindow.我能够创建简单的应用程序,但我找不到任何解释如何在不创建 ActiveWindow 的情况下从 *.avi 获取帧。 In fact, I need only to read video with DirectShow and then I'll use OpenCV to process and show video.事实上,我只需要用DirectShow读取视频,然后我会使用OpenCV来处理和显示视频。 Any help appreciated.任何帮助表示赞赏。 Thanks in advance!提前致谢!

Excuse me for my awful English.请原谅我糟糕的英语。

Create a graph with a NULL render.使用 NULL 渲染创建一个图形。 Also look at sample grabber example in directshow SDK. It shows how to grab a frame for a graph.另请参阅 directshow SDK 中的示例抓取器示例。它显示了如何抓取图形的帧。 You can then pass on the frame to openCV for processing.然后您可以将帧传递给 openCV 进行处理。

Basically you want to connect something like this:基本上你想连接这样的东西:

Source -> Sample Grabber -> Null renderer

Download graphEdit or GraphEdit+ and you can visually represent these filters.下载 graphEdit 或 GraphEdit+,您可以直观地表示这些过滤器。 As an example I went ahead and built a graph from my local webcam to a sample grabber connectted to a null renderer.作为示例,我继续构建了一个从本地网络摄像头到连接到 null 渲染器的样本采集器的图形。 The C# code generated by GraphEdit+ is this: 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;
    }

}

} }

You'd still need to actually capture the sample frame, but as was mentioned in the post above you can look into the sampleGrabber SDK on MSDN to find out how to do that.您仍然需要实际捕获示例帧,但如上文所述,您可以查看 MSDN 上的 sampleGrabber SDK 以了解如何执行此操作。

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

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