// 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(0, 0, 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 < 0) return 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(0, 0, 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(0, 0, 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);}