C ++ - DirectShow - 网络摄像头捕获的两个图像之间的比较

时间:2014-11-03 19:04:32

标签: image comparison webcam directshow pixels

我是DirectShow世界的新手,我刚学习了Microsoft SDK Samples提供的简单“playcap”示例。通过这个小程序,我已经能够拥有一个带有我的网络摄像头流的窗口。 如何从网络摄像头拍摄两张照片并进行比较(即使不将它们保存在硬盘上)以找出哪些像素不同? 我很容易使用Win32API捕获窗口完成这项工作,但它非常慢,我需要快速。 提前谢谢,这对我的项目非常重要。

1 个答案:

答案 0 :(得分:-1)

您最好搜索here以获取答案,或查看Sample Grabber Filter的示例。 有关详细信息,请直接写信给我here

将Sample Grabber过滤器添加到图表中。

IBaseFilter *pSG_Filter;
    hr = CoCreateInstance(
    CLSID_SampleGrabber, 
    NULL, 
    CLSCTX_INPROC_SERVER,
    IID_IBaseFilter, 
    (void**)&pSG_Filter
);

hr = pGraph->AddFilter(pSG_Filter, L"SampleGrab");

将Null Renderer过滤器添加到图表中。

IBaseFilter *pNull;

hr = CoCreateInstance(
    CLSID_NullRenderer, 
    NULL, 
    CLSCTX_INPROC_SERVER,
    IID_IBaseFilter, 
    (void**)&pNull
    );

hr = pGraph->AddFilter(pNull, L"NullRender");

现在你可以使用ICaptureGraphBuilder2 :: RenderStream方法在一个方法调用中连接所有三个过滤器,从静止引脚到Sample Grabber,从Sample Grabber到Null Renderer:

hr = pBuild->RenderStream(
    &PIN_CATEGORY_STILL, // Connect this pin ...
    &MEDIATYPE_Video,    // with this media type ...
    pCap,                // on this filter ...
    pSG_Filter,          // to the Sample Grabber ...
    pNull);              // ... and finally to the Null Renderer.

现在使用ISampleGrabber接口配置Sample Grabber,以便缓冲样本:

ISampleGrabber *pSG = NULL;

hr = pSG_Filter->QueryInterface(IID_ISampleGrabber, (void**)&pSG);
if (SUCCEEDED(hr))
{
    hr = pSG->SetOneShot(FALSE);
    hr = pSG->SetBufferSamples(TRUE);

    ...

现在,您应该查看方法ISampleGrabber :: SetOneShot,并在那里设置为TRUE。

使用指向回调对象的指针设置回调接口:

hr = pSG->SetCallback(&g_StillCapCB, 0); // 0 = Use the SampleCB callback method.

获取静止引脚用于连接Sample Grabber的媒体类型:

// Store the media type for later use.
AM_MEDIA_TYPE g_StillMediaType;

hr = pSG->GetConnectedMediaType(&g_StillMediaType);
pSG->Release();

此媒体类型将包含定义静止图像格式的BITMAPINFOHEADER结构。

以下是回调类的示例。请注意,该类实现了IUnknown,它通过ISampleGrabber接口继承,但它不保留引用计数。这是安全的,因为应用程序在堆栈上创建对象,并且对象在整个过滤器图形的生命周期内保持在范围内。

所有工作都在BufferCB方法中进行,每当获取新样本时,Sample Grabber都会调用该方法。在以下示例中,该方法将位图写入文件:

class SampleGrabberCallback : public ISampleGrabberCB
{
    public:
    // Fake referance counting.
    STDMETHODIMP_(ULONG) AddRef() { return 1; }
    STDMETHODIMP_(ULONG) Release() { return 2; }

    STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject)
    {
        if (NULL == ppvObject) return E_POINTER;
        if (riid == __uuidof(IUnknown))
        {
            *ppvObject = static_cast<IUnknown*>(this);
             return S_OK;
        }
        if (riid == __uuidof(ISampleGrabberCB))
        {
            *ppvObject = static_cast<ISampleGrabberCB*>(this);
             return S_OK;
        }
        return E_NOTIMPL;
    }

    STDMETHODIMP SampleCB(double Time, IMediaSample *pSample)
    {
        return E_NOTIMPL;
    }

    STDMETHODIMP BufferCB(double Time, BYTE *pBuffer, long BufferLen)
    {
        if ((g_StillMediaType.majortype != MEDIATYPE_Video) ||
            (g_StillMediaType.formattype != FORMAT_VideoInfo) ||
            (g_StillMediaType.cbFormat < sizeof(VIDEOINFOHEADER)) ||
            (g_StillMediaType.pbFormat == NULL))
        {
            return VFW_E_INVALIDMEDIATYPE;
        }
        HANDLE hf = CreateFile("C:\\Example.bmp", GENERIC_WRITE, 
        FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);
        if (hf == INVALID_HANDLE_VALUE)
        {
            return E_FAIL;
        }
        long cbBitmapInfoSize = g_StillMediaType.cbFormat - SIZE_PREHEADER;
        VIDEOINFOHEADER *pVideoHeader =
           (VIDEOINFOHEADER*)g_StillMediaType.pbFormat;

        BITMAPFILEHEADER bfh;
        ZeroMemory(&bfh, sizeof(bfh));
        bfh.bfType = 'MB';  // Little-endian for "BM".
        bfh.bfSize = sizeof( bfh ) + BufferLen + cbBitmapInfoSize;
        bfh.bfOffBits = sizeof( BITMAPFILEHEADER ) + cbBitmapInfoSize;

        // Write the file header.
        DWORD dwWritten = 0;
        WriteFile( hf, &bfh, sizeof( bfh ), &dwWritten, NULL );
        WriteFile(hf, HEADER(pVideoHeader), cbBitmapInfoSize, &dwWritten, NULL);        
        WriteFile( hf, pBuffer, BufferLen, &dwWritten, NULL );
        CloseHandle( hf );
        return S_OK;

    }
};

在应用程序退出之前释放媒体类型:

// On exit, remember to release the media type.
FreeMediaType(g_StillMediaType);