2012-04-05 6 views
1

Ich habe die Suche auf StackOverflow, aber ich habe die Antwort nicht gefunden. Ich entwickle eine Anwendung und benutze OpenCV, aber ich muss mit verschiedenen Videos arbeiten (meistens * .avi), also habe ich mich für DirectShow entschieden. Ich war in der Lage, einfache Anwendungen zu erstellen, aber ich kann keine Erklärung dafür finden, wie man Frames von * .avi erhält, ohne ActiveWindow zu erstellen. In der Tat, ich brauche nur Video mit DirectShow zu lesen und dann verwende ich OpenCV, um Video zu verarbeiten und zu zeigen. Jede Hilfe wird geschätzt. Danke im Voraus!DirectShow und openCV. Video-Datei lesen und verarbeiten

Entschuldigung für mein schreckliches Englisch.

+0

möglich Duplikat von [Kann ich rohe Videorahmen von DirectShow ohne Wiedergabe erhalten] (http://stackoverflow.com/questions/8924355/can-i-get-raw-video-frames-from-directshow-witound-playback) – karlphillip

+0

Ja, ich habe diesen Thread nicht gefunden, danke! – Nikita

Antwort

2

Erstellen Sie ein Diagramm mit einem NULL-Render. Sehen Sie sich auch das Sample Grabber-Beispiel im directshow SDK an. Es zeigt, wie man einen Rahmen für ein Diagramm erhält. Sie können dann den Rahmen an openCV zur Verarbeitung weitergeben.

+0

Vielen Dank, ich werde Beispiel Grabber Beispiel untersuchen. "Erstellen Sie ein Diagramm mit einem NULL-Render" - Ich verstehe nicht, wie ich das machen soll, können Sie das bitte erklären? – Nikita

+0

Nun, wenn Sie normalerweise ein Diagramm rendern, indem Sie einen einfachen Befehl renderfile verwenden, haben Sie normalerweise die folgende Grafik: Dateireader-> Decoder-> Videowiedergabe. Sie können alternativ ein Diagramm manuell erstellen, um einen Null-Renderer zu verwenden: reader-> decoder-> null render. Ein Null-Renderer verwirft unbeaufsichtigt Samples, so dass nichts angezeigt wird ... kein aktives Filmfenster. – Saibal

+0

Vielen Dank für die Erklärung! Ich denke, ich habe es =) – Nikita

1

Im Grunde wollen Sie so etwas verbinden:

Source -> Sample Grabber -> Null renderer 

Herunterladen GraphEdit oder GraphEdit + und Sie können visuell darstellen diese Filter. Als Beispiel habe ich ein Diagramm von meiner lokalen Webcam zu einem Sample-Grabber erstellt, der mit einem Null-Renderer verbunden ist. Das C# -Code erzeugt durch GraphEdit + ist dies:

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

} 

}

Sie würden immer noch brauchen, um das Sample Rahmen zu erfassen, sondern wie im Beitrag erwähnt wurde über Sie das sampleGrabber SDK auf MSDN aussehen in können um herauszufinden, wie man das macht.

Verwandte Themen