gpt4 book ai didi

visual-c++ - 从 directshow 获取 iplImage 或 Mat 到 opencv

转载 作者:太空宇宙 更新时间:2023-11-03 21:19:51 24 4
gpt4 key购买 nike

由于在使用 c++ 和 opencv 时难以更改相机的分辨率,我不得不将我的眼动追踪软件更改为 directshow。

Directshow 对我来说是新手,很难理解所有内容。但我发现这个很好的例子非常适合捕捉和查看网络摄像头。

http://www.codeproject.com/Articles/12869/Real-time-video-image-processing-frame-grabber-usi

我使用的是不需要 directShow SDK 的版本。 (不过例子中用的还是directshow对吧??)

#include <windows.h>
#include <dshow.h>

#pragma comment(lib,"Strmiids.lib")

#define DsHook(a,b,c) if (!c##_) { INT_PTR* p=b+*(INT_PTR**)a; VirtualProtect(&c##_,4,PAGE_EXECUTE_READWRITE,&no);\
*(INT_PTR*)&c##_=*p; VirtualProtect(p, 4,PAGE_EXECUTE_READWRITE,&no); *p=(INT_PTR)c; }


// Here you get image video data in buf / len. Process it before calling Receive_ because renderer dealocates it.
HRESULT ( __stdcall * Receive_ ) ( void* inst, IMediaSample *smp ) ;
HRESULT __stdcall Receive ( void* inst, IMediaSample *smp ) {
BYTE* buf; smp->GetPointer(&buf); DWORD len = smp->GetActualDataLength();
HRESULT ret = Receive_ ( inst, smp );
return ret;
}

int WINAPI WinMain(HINSTANCE inst,HINSTANCE prev,LPSTR cmd,int show){
HRESULT hr = CoInitialize(0); MSG msg={0}; DWORD no;

IGraphBuilder* graph= 0; hr = CoCreateInstance( CLSID_FilterGraph, 0, CLSCTX_INPROC,IID_IGraphBuilder, (void **)&graph );
IMediaControl* ctrl = 0; hr = graph->QueryInterface( IID_IMediaControl, (void **)&ctrl );

ICreateDevEnum* devs = 0; hr = CoCreateInstance (CLSID_SystemDeviceEnum, 0, CLSCTX_INPROC, IID_ICreateDevEnum, (void **) &devs);
IEnumMoniker* cams = 0; hr = devs?devs->CreateClassEnumerator (CLSID_VideoInputDeviceCategory, &cams, 0):0;
IMoniker* mon = 0; hr = cams->Next (1,&mon,0); // get first found capture device (webcam?)
IBaseFilter* cam = 0; hr = mon->BindToObject(0,0,IID_IBaseFilter, (void**)&cam);
hr = graph->AddFilter(cam, L"Capture Source"); // add web cam to graph as source
IEnumPins* pins = 0; hr = cam?cam->EnumPins(&pins):0; // we need output pin to autogenerate rest of the graph
IPin* pin = 0; hr = pins?pins->Next(1,&pin, 0):0; // via graph->Render
hr = graph->Render(pin); // graph builder now builds whole filter chain including MJPG decompression on some webcams
IEnumFilters* fil = 0; hr = graph->EnumFilters(&fil); // from all newly added filters
IBaseFilter* rnd = 0; hr = fil->Next(1,&rnd,0); // we find last one (renderer)
hr = rnd->EnumPins(&pins); // because data we are intersted in are pumped to renderers input pin
hr = pins->Next(1,&pin, 0); // via Receive member of IMemInputPin interface
IMemInputPin* mem = 0; hr = pin->QueryInterface(IID_IMemInputPin,(void**)&mem);

DsHook(mem,6,Receive); // so we redirect it to our own proc to grab image data

hr = ctrl->Run();

while ( GetMessage( &msg, 0, 0, 0 ) ) {
TranslateMessage( &msg );
DispatchMessage( &msg );
}
};

为来自凸轮的每个新帧调用 HRESULT Receive 方法。评论说 buf 包含数据。但是我有 3 个问题。

  1. 我无法包含 opencv 库。我在 visual studio 中创建了一个新项目,并添加了我一直包含的相同属性表。与早期项目的唯一区别是我现在创建了一个完全空的项目,之前我创建了一个 win32 应用程序。如何将opencv添加到directshow工程中?

  2. 上面的例子。来自缓冲区。这是一个指向数据的指针。我如何将其放入 iplImage/Mat 以用于 opencv calc?

  3. 有没有办法不显示来自网络摄像头的图像(我只需要对帧执行一些算法,我想删除包含结果的窗口可能会给我更多分析算法的能力?!)

谢谢!

最佳答案

使用 DirectShow,您通常会创建一个管道,即一个图形,然后向其中添加过滤器,如下所示:

Camera -> [可能是一些额外的东西] -> Sample Grabber -> Null Renderer

相机,Sample Grabber , Null Renderer都是干净的 Windows 附带的所有标准组件。 Sample Grabber 可以设置为通过 ISampleGrabberCB::SampleCB 给您回电并为您提供捕获的每个视频帧的数据。 Null Renderer 是管道的终止而不在监视器上显示视频(只是视频捕获)。

SampleCB 关键字为您带来您需要的示例代码。通过此调用收到数据后,您可以按照@praks411 的建议将其转换/包装到 IPL/OpenCV 类中。

如此简单地完成它,您就不需要 DirectShow BaseClasses,并且代码将仅仅是常规的 ATL/MFC 代码和项目。确保使用 CComPtr 包装器类来处理 COM 接口(interface),以免丢失引用和泄漏对象。最新的 Windows SDK 中可能缺少某些声明,因此您需要使用 Windows SDK 6.x 或只从那里复制缺少的部分。

另见:

关于visual-c++ - 从 directshow 获取 iplImage 或 Mat 到 opencv,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16477314/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com