2

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 lib を含めることはできません。Visual Studio で新しいプロジェクトを作成し、いつもと同じプロパティ シートを追加します。以前のプロジェクトとの唯一の違いは、完全に空のプロジェクトを作成し、以前は win32 アプリケーションを作成したことです。directshow プロジェクトに opencv を追加するには?

  2. 上記の例。バフから。これはデータへのポインタです。それをopencv calcのiplImage/Matに入れるにはどうすればよいですか?

  3. ウェブカメラからの画像を表示しない方法はありますか (フレームに対していくつかのアルゴリズムを実行するだけで済みます。結果が表示されたウィンドウを削除すると、分析アルゴリズムの能力が向上するのではないでしょうか?!)

ありがとう!

4

2 に答える 2