2012-04-05 58 views
1

我在StackOverflow上使用了搜索,但沒有找到答案。我正在開發一個應用程序並使用OpenCV,但我需要使用不同的視頻(主要是* .avi),所以我決定使用DirectShow。我能夠創建簡單的應用程序,但我找不到任何解釋如何從* .avi獲取幀,而無需創建ActiveWindow。事實上,我只需要用DirectShow閱讀視頻,然後使用OpenCV來處理和顯示視頻。 任何幫助表示讚賞。提前致謝!DirectShow和openCV。閱讀視頻文件和過程

對不起,我可怕的英語。

+0

可能重複的[我可以從DirectShow原始視頻幀沒有播放](http://stackoverflow.com/questions/8924355/can-i-get-raw-video-frames-from-directshow-without-playback ) – karlphillip 2012-04-05 16:46:29

+0

是的,我沒有找到這個線程,謝謝! – Nikita 2012-04-05 17:36:17

回答

2

使用NULL渲染創建圖形。還可以看看directshow SDK中的示例採集器示例。它演示瞭如何爲圖形獲取框架。然後您可以將幀傳遞給openCV進行處理。

+0

謝謝,我將研究示例抓取器示例。 「用NULL渲染創建一個圖形」 - 我不明白我應該怎麼做,你能解釋一下嗎? – Nikita 2012-04-05 17:29:25

+0

那麼當你正常渲染一個圖形時,使用簡單的renderfile命令,你通常會得到如下的圖形:file reader-> decoder-> video render。您也可以手動創建圖形以使用空渲染器:reader-> decoder-> null渲染。 null渲染器默默丟棄示例,以便什麼都不顯示...沒有活動的電影窗口。 – Saibal 2012-04-06 04:53:16

+0

非常感謝您的解答!我想我已經知道了=) – Nikita 2012-04-06 10:50:31

1

基本上你想要的東西連接是這樣的:

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; 
    } 

} 

}

你最好還是需要實際拍攝樣本框,但在後提到上面你可以看看到sampleGrabber SDK的MSDN找出如何做到這一點。