我在StackOverflow上使用了搜索,但沒有找到答案。我正在開發一個應用程序並使用OpenCV,但我需要使用不同的視頻(主要是* .avi),所以我決定使用DirectShow。我能夠創建簡單的應用程序,但我找不到任何解釋如何從* .avi獲取幀,而無需創建ActiveWindow。事實上,我只需要用DirectShow閱讀視頻,然後使用OpenCV來處理和顯示視頻。 任何幫助表示讚賞。提前致謝!DirectShow和openCV。閱讀視頻文件和過程
對不起,我可怕的英語。
我在StackOverflow上使用了搜索,但沒有找到答案。我正在開發一個應用程序並使用OpenCV,但我需要使用不同的視頻(主要是* .avi),所以我決定使用DirectShow。我能夠創建簡單的應用程序,但我找不到任何解釋如何從* .avi獲取幀,而無需創建ActiveWindow。事實上,我只需要用DirectShow閱讀視頻,然後使用OpenCV來處理和顯示視頻。 任何幫助表示讚賞。提前致謝!DirectShow和openCV。閱讀視頻文件和過程
對不起,我可怕的英語。
使用NULL渲染創建圖形。還可以看看directshow SDK中的示例採集器示例。它演示瞭如何爲圖形獲取框架。然後您可以將幀傳遞給openCV進行處理。
謝謝,我將研究示例抓取器示例。 「用NULL渲染創建一個圖形」 - 我不明白我應該怎麼做,你能解釋一下嗎? – Nikita 2012-04-05 17:29:25
那麼當你正常渲染一個圖形時,使用簡單的renderfile命令,你通常會得到如下的圖形:file reader-> decoder-> video render。您也可以手動創建圖形以使用空渲染器:reader-> decoder-> null渲染。 null渲染器默默丟棄示例,以便什麼都不顯示...沒有活動的電影窗口。 – Saibal 2012-04-06 04:53:16
非常感謝您的解答!我想我已經知道了=) – Nikita 2012-04-06 10:50:31
基本上你想要的東西連接是這樣的:
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找出如何做到這一點。
可能重複的[我可以從DirectShow原始視頻幀沒有播放](http://stackoverflow.com/questions/8924355/can-i-get-raw-video-frames-from-directshow-without-playback ) – karlphillip 2012-04-05 16:46:29
是的,我沒有找到這個線程,謝謝! – Nikita 2012-04-05 17:36:17