从DirectShow中获取的IplImage或垫的OpenCV(Get iplImage or M

2019-09-02 11:20发布

我不得不改变到DirectShow对我的眼动追踪软件由于困难用c ++和OpenCV时改变相机的分辨率。

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接收的方法被称为从凸轮每一个新的框架。 该评论说,buf将包含的数据。 但是,我有3个问题/问题。

  1. 我不能包括OpenCV的库。 我Visual Studio创建一个新的项目,并添加相同的属性表,因为我总是有。 从早期的项目唯一的区别就是我现在创建一个完全以空项目,早前我创建了一个Win32应用程序。 如何添加OpenCV的到DirectShow的项目?

  2. 上面的例子。 来自BUF。 这是一个指向数据的指针。 我如何获取到的IplImage /垫子OpenCV的钙?

  3. 有没有办法不显示从摄像头图像(我只需要对帧进行一些算法,我想删除的结果窗口会给我更多的动力的分析算法?!)

谢谢!

Answer 1:

随着DirectShow中您通常会创建一个管道,这是一个图,您添加过滤器,就像这样:

摄像机 - > [可能还有一些额外的东西] - >样品采集卡 - > Null渲染

相机, 样品采集卡 , Null渲染附带干净的Windows所有标准组件。 样品采集卡可以设置给您回电话通过ISampleGrabberCB::SampleCB并给你拍摄的每个视频帧数据。 Null渲染管线是没有监视器上显示的视频终端(只是视频拍摄)。

SampleCB是带给你所需要的示例代码的关键字。 这个电话,你可以转换/它包装成IPL / OpenCV的类通过@ praks411的建议接收到具有数据。

它已经像这样简单的做,你不需要DirectShow的基类的,并且代码将仅仅是普通ATL / MFC代码和项目。 确保使用CComPtr包装类来处理COM接口不丢失引用和泄漏的对象。 有些声明可能会丢失在最新的Windows SDK,所以你需要或者使用Windows SDK 6.x或刚刚从那里复制缺少的部分。

也可以看看:

  • 如何用Delphi / DSPACK不会对TVideoWindow显示其拍摄帧? (Delphi代码,但良好的描述和附图)
  • DirectShow的:例如对于使用SampleGrabber为抓住一个框架,并建立一个VU表
  • SetLifeCamStudioResolutionSample -显示如何设置捕获了,包括摄像头的分辨率和样品采集卡,并且还缺少SDK声明一个小DirectShow的项目; 相关Q的不能让IAMStreamConfig.SetFormat()用的LifeCam Studio来工作
  • 构建过滤器图表上的样品采集卡和Null渲染


Answer 2:

我想,您可以在现有的OpenCV。 我已经做了的控制台应用程序。 您将需要包括路径OpenCV的财产页眉和路径OpenCV的LIB您当前的项目。

转到项目属性:1.To addheaders C / C ++ ----->附加包含目录--->这里添加的OpenCV包括目录(您可能要包括倍数目录)

  1. 要添加库链接----->附加库目录---->这里补充的OpenCV库。

若要从BUF创建的IplImage。 一旦你的高度和图像的宽度您可以使用下面。

IplImage *m_img_show;
CvSize cv_img_size = cvSize(m_mediaInfo.m_width, m_mediaInfo.m_height);
            m_img_show = cvCreateImageHeader(cv_img_size, IPL_DEPTH_8U,3);
            cvSetData(m_img_show, m_pBuffer, m_mediaInfo.m_width*3);

我认为图像的预览是非常有帮助的。 看来你的过滤器,从上面取渲染数据。 如果你想,你可能想改变你的渲染器,并在窗口模式下使用它。 其他选项可以使用样品采集过滤器。



文章来源: Get iplImage or Mat from directshow to opencv