Direct Show采集图像实例

// CaptureVideo.h: interface for the CCaptureVideo class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_CAPTUREVIDEO_H__973C8C7A_47A3_45B6_9B28_0A4A08003540__INCLUDED_)
#define AFX_CAPTUREVIDEO_H__973C8C7A_47A3_45B6_9B28_0A4A08003540__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include 
<atlbase.h>
#include 
<windows.h>
#include 
<dshow.h>
#ifndef SAFE_RELEASE
#define SAFE_RELEASE( x ) \
if ( NULL != x ) \
{ \
    x
->Release( ); \
    x 
= NULL; \
}

#endif
class CSampleGrabberCB;

class CCaptureVideo  : public CWnd
{
    friend 
class CSampleGrabberCB;
public:
    
void GrabOneFrame(BOOL bGrab);
    
void ImageProcess(BOOL bImage);
    HRESULT Init(
int iDeviceID,HWND hWnd);
    CCaptureVideo();
    
virtual ~CCaptureVideo();

    BOOL bIsVideoOpen;
    
void SwitchImageProcess(BOOL bprocess);
       
void ImageProcessing(unsigned char*m_pDibBits,int m_height, int m_width);

private:
    HWND m_hWnd;
    IGraphBuilder 
*m_pGB;
    ICaptureGraphBuilder2
* m_pCapture;
    IBaseFilter
* m_pBF;
    IMediaControl
* m_pMC;
    IVideoWindow
* m_pVW;
    CComPtr 
<ISampleGrabber> m_pGrabber;

protected:
    
void FreeMediaType(AM_MEDIA_TYPE& mt);
    
bool BindFilter(int deviceId, IBaseFilter **pFilter);
    HRESULT InitCaptureGraphBuilder();
}
;

#endif // !defined(AFX_CAPTUREVIDEO_H__973C8C7A_47A3_45B6_9B28_0A4A08003540__INCLUDED_)

// CaptureVideo.cpp: implementation of the CCaptureVideo class.
//
//////////////////////////////////////////////////////////////////////

#include 
"stdafx.h"
#include 
"CaptureVideo.h"
#include 
"ImageProcess.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
/////////////////////////声明全局变量//////////////////////////////////////
BOOL bIsSavePic = FALSE;
BOOL bIsImageProcess 
= FALSE;
//////////////////////////////////////////////////////////////////////
class CSampleGrabberCB:public ISampleGrabberCB 
{
public:
    
long lWidth;
    
long lHeight;
    CCaptureVideo dlg;

    STDMETHODIMP_(ULONG) AddRef() 
return 2; }
    STDMETHODIMP_(ULONG) Release() 
return 1; }
    STDMETHODIMP QueryInterface(REFIID riid, 
void ** ppv)
    
{
        
if( riid == IID_ISampleGrabberCB || riid == IID_IUnknown )
        

            
*ppv = (void *) static_cast<ISampleGrabberCB*> ( this );
            
return NOERROR;
        }
 
        
        
return E_NOINTERFACE;
    }

    
    STDMETHODIMP SampleCB( 
double SampleTime, IMediaSample * pSample )
    
{
        
return 0;
    }

//回调函数
    STDMETHODIMP BufferCB( double dblSampleTime, unsigned char* pBuffer, long lBufferSize )
    
{
        
if (!pBuffer)     return E_POINTER;
        
        
if (bIsImageProcess) 
        
{//如果条件为真则进行数字图像处理
            dlg.ImageProcessing(pBuffer, lHeight, lWidth);
        }

        
        
return 0;
    }

}
;
CSampleGrabberCB mCB;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCaptureVideo::CCaptureVideo() 
{
    
//COM Library Intialization
    if(FAILED(CoInitialize(NULL))) 
    
{
        AfxMessageBox(
"CoInitialize Failed!\r\n"); 
        
return;
    }

    m_hWnd 
= NULL;
    m_pVW 
= NULL;
    m_pMC 
= NULL;
    m_pGB 
= NULL;
    m_pCapture 
= NULL; 
    bIsVideoOpen 
= FALSE;
}


CCaptureVideo::
~CCaptureVideo()
{
    
if (bIsVideoOpen) 
    
{    
        
// Stop media playback
        if(m_pMC)
        
{
            m_pMC
->Stop();
        }

        
        
if(m_pVW)
        
{
            m_pVW
->put_Visible(OAFALSE);
            m_pVW
->put_Owner(NULL);
        }

        
        SAFE_RELEASE(m_pCapture);
        SAFE_RELEASE(m_pMC);
        SAFE_RELEASE(m_pGB);
        SAFE_RELEASE(m_pBF);
        CoUninitialize( );
    }

}


///////////////////////////////////////////////////////////////////////////
////
////                        DirectShow核心代码
////
///////////////////////////////////////////////////////////////////////////

HRESULT CCaptureVideo::Init(int iDeviceID, HWND hWnd)
{
    HRESULT hr;
    hr 
= InitCaptureGraphBuilder();
    
if (FAILED(hr))
    
{
        AfxMessageBox(
"Failed to get video interfaces!");
        
return hr;
    }


    
// Bind Device Filter. We know the device because the id was passed in
    if(!BindFilter(iDeviceID, &m_pBF))
    
{
        AfxMessageBox(
"未找到USB摄像头!\n请检查设备后重试!");
        PostQuitMessage(
0);
        
return S_FALSE;
    }

    
    hr 
= m_pGB->AddFilter(m_pBF, L"Capture Filter");
    
// hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, // m_pBF, NULL, NULL);
    
// create a sample grabber
    hr = m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );
    
if!m_pGrabber )
    
{
        AfxMessageBox(
"Fail to create SampleGrabber, maybe qedit.dll is not registered?");
        
return hr;
    }


    CComQIPtr
< IBaseFilter, &IID_IBaseFilter > pGrabBase(m_pGrabber);
    
    
//**********设置视频格式**********//
    AM_MEDIA_TYPE mt; 
    ZeroMemory(
&mt, sizeof(AM_MEDIA_TYPE));
    mt.majortype 
= MEDIATYPE_Video;
    mt.subtype 
= MEDIASUBTYPE_RGB24;  //抓取24位位图
    hr = m_pGrabber->SetMediaType(&mt);

    
if( FAILED( hr ) )
    
{
        AfxMessageBox(
"Fail to set media type!");
        
return hr;
    }

    
    hr 
= m_pGB->AddFilter( pGrabBase, L"Grabber" );
    
if( FAILED( hr ) )
    
{
        AfxMessageBox(
"Fail to put sample grabber in graph");
        
return hr;
    }


    
// try to render preview/capture pin
    hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,m_pBF,pGrabBase,NULL);
    
if( FAILED( hr ) )
        hr 
= m_pCapture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,m_pBF,pGrabBase,NULL);

    
if( FAILED( hr ) )
    
{
        AfxMessageBox(
"Can't build the graph");
        
return hr;
    }

    
    hr 
= m_pGrabber->GetConnectedMediaType( &mt );
    
    
if ( FAILED( hr) )
    
{
        AfxMessageBox(
"Failt to read the connected media type");
        
return hr;
    }


    VIDEOINFOHEADER 
* vih = (VIDEOINFOHEADER*) mt.pbFormat;
    mCB.lWidth 
= vih->bmiHeader.biWidth;
    mCB.lHeight 
= vih->bmiHeader.biHeight;
    FreeMediaType(mt);
    hr 
= m_pGrabber->SetBufferSamples( FALSE );
    hr 
= m_pGrabber->SetOneShot( FALSE );
    hr 
= m_pGrabber->SetCallback( &mCB, 1 );
    
    
//*********设置视频捕捉窗口********//
    m_hWnd = hWnd ; //picture控件的句柄
    hr = m_pVW->put_Owner((OAHWND)m_hWnd);
    
if (FAILED(hr)) return hr;
    hr 
= m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN);
    
if (FAILED(hr)) return hr;

    
if (m_pVW)
    
{    
        CRect rc;
        ::GetClientRect(m_hWnd,
&rc);
        m_pVW
->SetWindowPosition(00, rc.right, rc.bottom);//让图像充满整个窗口
    }
 

    hr 
= m_pVW->put_Visible(OATRUE);

    
//*********开始视频捕捉********//
    hr = m_pMC->Run();
    
if(FAILED(hr))
    
{
        AfxMessageBox(
"Couldn't run the graph!");
        
return hr;
    }


    bIsVideoOpen 
= TRUE;
    
return S_OK;
}


HRESULT CCaptureVideo::InitCaptureGraphBuilder()
{
    HRESULT hr;
    
// 创建IGraphBuilder接口
    hr=CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&m_pGB);
    
// 创建ICaptureGraphBuilder2接口
    hr = CoCreateInstance (CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC,IID_ICaptureGraphBuilder2, (void **&m_pCapture);
    
if (FAILED(hr)) return hr;
    m_pCapture
->SetFiltergraph(m_pGB);
    hr 
= m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
    
if (FAILED(hr)) return hr;
    hr 
= m_pGB->QueryInterface(IID_IVideoWindow, (LPVOID *)&m_pVW);
    
if (FAILED(hr)) return hr;
    
return hr;
}


bool CCaptureVideo::BindFilter(int deviceId, IBaseFilter **pFilter)
{
    
if (deviceId < 0return false;

    
// enumerate all video capture devices
    CComPtr<ICreateDevEnum> pCreateDevEnum;
    HRESULT hr 
= CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void**)&pCreateDevEnum);
    
if (hr != NOERROR)
    
{
        
return false;
    }


    CComPtr
<IEnumMoniker> pEm;
    hr 
= pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEm, 0);
    
if (hr != NOERROR) 
    
{
        
return false;
    }


    pEm
->Reset();
    ULONG cFetched;
    IMoniker 
*pM;
    
int index = 0;
    
while(hr = pEm->Next(1&pM, &cFetched), hr==S_OK, index <= deviceId)
    
{
        IPropertyBag 
*pBag;
        hr 
= pM->BindToStorage(00, IID_IPropertyBag, (void **)&pBag);
        
if(SUCCEEDED(hr)) 
        
{
            VARIANT var;
            var.vt 
= VT_BSTR;
            hr 
= pBag->Read(L"FriendlyName"&var, NULL);
            
if (hr == NOERROR) 
            
{
                
if (index == deviceId)
                
{
                    pM
->BindToObject(00, IID_IBaseFilter, (void**)pFilter);
                }


                SysFreeString(var.bstrVal);
            }

            
            pBag
->Release();
        }

        
        pM
->Release();
        index
++;
    }

    
    
return true;
}


void CCaptureVideo::FreeMediaType(AM_MEDIA_TYPE& mt)
{
    
if (mt.cbFormat != 0
    
{
        CoTaskMemFree((PVOID)mt.pbFormat);
        
// Strictly unnecessary but tidier
        mt.cbFormat = 0;
        mt.pbFormat 
= NULL;
    }

    
    
if (mt.pUnk != NULL) 
    
{
        mt.pUnk
->Release();
        mt.pUnk 
= NULL;
    }

}
 

//////////////////////////////////////////////////////////////////////////////////////////

void CCaptureVideo::SwitchImageProcess(BOOL bprocess)
{
    bIsImageProcess 
= bprocess;
}


//////////////////////////////////////////////////////////////////////////////
/////////
/////////                         数字图像处理       
////////
///////////////////////////////////////////////////////////////////////////////

void CCaptureVideo::ImageProcessing(unsigned char*m_pDibBits, int m_height, int m_width)
{    
    CImageProcess::ColorToGray(m_pDibBits,m_height, m_width); 
//彩色转灰度
    CImageProcess::ConvertGrayToWhiteBlack(m_pDibBits, m_height, m_width, 120); //二值化
}



主程序


#ifdef _DEBUG
#pragma comment(lib,"strmbasd.lib")
#else
#pragma comment(lib,"STRMBASE.lib")
#endif
#pragma comment(lib,"strmiids.lib")
#pragma comment(lib,"quartz.lib")

void CUSBShowDlg::OnBUTTONOpenVideo() //打开摄像头
{
    HWND hWnd 
= m_StaticShow.GetSafeHwnd(); 
    HRESULT hr 
= m_cap.Init(0,hWnd); //DirectShow初始化
}


void CUSBShowDlg::OnBUTTONImageProcess() //启动数字图像处理开关
{
    m_cap.SwitchImageProcess(TRUE);
}

原文地址:https://www.cnblogs.com/wqj1212/p/1133116.html