获取iplImage或Mat从directshow到opencv [英] Get iplImage or Mat from directshow to opencv

查看:782
本文介绍了获取iplImage或Mat从directshow到opencv的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I had to change to directshow for my eyetracking software due to the difficulties to change resolution of the camera when using c++ and opencv.

Directshow对我来说是新的,它很难理解一切。但我发现这个很好的例子,完美的捕捉&查看网络摄像头。

Directshow is new to me and it is kind of hard to understand everything. But I found this nice example that works perfectly for capturing & viewing the web cam.

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

我使用的版本不需要directShow SDK。 (但它仍然是directshow在示例中使用,右?)

I am using the version that not requires directShow SDK. (But it is still directshow that is used in the example, right??)

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

从cam中为每个新帧调用HRESULT Receive方法。评论说buf包含数据。但我有3个问题/问题。

The method HRESULT Receive is called for every new frame from the cam. the the comments says that buf contains the data. But I have 3 problems/questions.


  1. 我不能包括opencv lib。我在visual studio中创建一个新项目,并添加相同的属性表,我总是包括。与早期项目的唯一区别是,我现在创建一个totaly空项目,早些时候我创建了一个win32应用程序。
    如何将opencv添加到directshow项目中?

  1. I cant include the opencv lib. I create a new project in visual studio, and add the same property sheets as I always include. the only difference from earlier projects is that I Now create a totaly empty project, earlier I created a win32 application. How to add opencv into the directshow project?

上面的例子。从buf。这是一个指向数据的指针。如何获得进入iplImage / mat的opencv calc?

The example above. from buf. which is a pointer to the data. How do I get that into iplImage/Mat for the opencv calc?

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

Is there a way to not show the images from the webcam (I only need to perform some algorithms on the frames, I guess removing the window with the results might give me more power for the analyse algorithms?!)

感谢!

推荐答案

使用DirectShow,你通常创建一个管道,即一个图形,这:

With DirectShow you typically create a pipeline, that is a graph and you add filters to it, like this:

相机 - > [可能还有一些额外的东西] - > Sample Grabber - > Null Renderer

Camera -> [possibly some extra stuff] -> Sample Grabber -> Null Renderer

示例抓取器 Null呈现器都是与干净的Windows一起运送的标准组件。您可以通过 ISampleGrabberCB :: SampleCB ,并为您捕获的每个视频帧提供数据。 Null Renderer是管道的终止,而不在监视器上显示视频(只是视频捕获)。

Camera, Sample Grabber, Null Renderer are all standard components shipped with clean Windows. Sample Grabber can be set to call you back via ISampleGrabberCB::SampleCB and give you data for every video frame captured. Null Renderer is the termination of pipeline without displaying video on monitor (just video capture).

SampleCB 给你需要的示例代码。通过此调用接收到数据,您可以根据@ praks411建议将其转换/包装为IPL / OpenCV类。

SampleCB is the keyword to bring you sample code you need. Having data received with this call, you can convert/wrap it into IPL/OpenCV class as suggested by @praks411.

完成这么简单, t需要DirectShow BaseClasses,并且代码将只是常规的ATL / MFC代码和项目。确保使用 CComPtr wrapper类来处理COM接口,以不丢失引用和泄漏对象。

Having it done as simple as this, you don't need DirectShow BaseClasses, and the code will be merely regular ATL/MFC code and project. Make sure to use CComPtr wrapper class to deal with COM interfaces to not lose references and leak objects. Some declarations might be missing in very latest Windows SDK, so you need to either use Windows SDK 6.x or just copy missing parts from there.

另请参阅:

  • How to capture frames using Delphi/DSPack without displaying it on TVideoWindow? (Delphi code, but good description and figures)
  • DirectShow: Examples for Using SampleGrabber for Grabbing a Frame and Building a VU Meter
  • SetLifeCamStudioResolutionSample - A small DirectShow project showing how to set capture up, including resolution on camera, and Sample Grabber, and also missing SDK declarations; related Q is Can't make IAMStreamConfig.SetFormat() to work with LifeCam Studio
  • Building the Filter Graph on Sample Grabber and Null Renderer

这篇关于获取iplImage或Mat从directshow到opencv的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆