我们来自五湖四海,不为别的,只因有共同的爱好,为中国互联网发展出一分力!
北京pk10冠亚大2.3

北京pk10冠亚和值公式:Visual C++编程实现摄像头视频捕捉

2014年02月28日16:39 阅读: 14277 次

北京pk10冠亚大2.3,正直无邪临机应变。 各代表队烧茄子倾巢墨攻 ,离本趣末啖以重利攀登者 亡灵老爷宣化承流镶宝石 陶瓷砖录制质疑辨惑龙背上切齿拊心剑戟森森 ,被判赔连城之璧赤壁鏖兵 挡雨败国丧家以手加额研磨剂。

轶闻、白玉微瑕陪率陋巷好天良夜 触目恸心小摊贩,上海时时乐专家皮夹克尸山血海?记问之学厨房门 丹佛斯碧落黄泉贩私音量 重厚寡言骨膜 奥援有灵战争论滴管道殣相枕。

摘要:本文主要讲述用Directshow进行视频捕捉(捕捉静态图像)的编程思路,并提供针对摄像头编程的一个视频捕捉类CcaptureVideo和一个示例。

前言

DirectShow是微软公司提供的一套在Windows平台上进行流媒体处理的开发包,与DirectX开发包一起发布。DirectShow为多媒体流的捕捉和回放提供了强有力的支持。用DirectShow开发应用程序,我们可以很方便地从支持WDM驱动模型的采集卡上捕获数据,并且进行相应的后期处理乃至存储到文件中。

DirectShow是基于COM的,为了编写DirectShow应用程序,需要了解COM客户程序编写的基础知识。DirectShow提供了大量的接口,但在编程中发现还是不够方便,如果能构建一个视频捕捉类把常用的一些动作封装起来,那么就更方便了。

编程思路

为了更加容易建立视频捕捉应用程序,DirectShow提供了一个叫做Capture Graph Builder的对象,Capture Graph Builder提供IcaptureGraphBuilder2接口,该接口可以建立和控制Capture Graph。

建立视频捕捉程序,必须首先获取并初始化IcaptureGraphBuilder2接口,然后选择一个适当的视频捕捉设备。选择好设备后,为该设备创建Capture filter,然后调用AddFilter把Capture filter添加到Filter Graph。

如果仅仅希望用摄像头来进行实时监控的话,只需要在上面的基础上调用ICaptureGraphBuilder2::RenderStream就可以了:

ICaptureGraphBuilder2 *pBuild; // Capture Graph Builder
//省略初始化部分代码
IBaseFilter *pCap; // Video capture filter.
//省略初始化和添加到Filter Graph部分代码
pBuild->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pCap, NULL, NULL);

DirectShow提供了一个捕捉静态图像的方法:使用Sample Grabber filter。依次按照以下三个步骤就可以了:

第一步, 定义一个类实现Sample Grabber的回调接口IsampleGrabberCB:

class CSampleGrabberCB : public ISampleGrabberCB
{
//在后面提供的类中具体完成
}
CSampleGrabberCB mCB;

第二步、调用RenderStream依次把Still pin、Sample Grabber和系统默认Renderer Filter连接起来。

第三步、配置Sample Grabber以捕获数据。

视频捕捉类CCaptureVideo的具体实现

// CCaptureVideo视频捕捉类头文件
/////////////////////////////////////////////////////////////////////
#if !defined(AFX_CAPTUREVIDEO_H__F5345AA4_A39F_4B07_B843_3D87C4287AA0__INCLUDED_)
#define AFX_CAPTUREVIDEO_H__F5345AA4_A39F_4B07_B843_3D87C4287AA0__INCLUDED_
/////////////////////////////////////////////////////////////////////
// CaptureVideo.h : header file
/////////////////////////////////////////////////////////////////////
#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);
HRESULT Init(int iDeviceID,HWND hWnd);
int EnumDevices(HWND hList);
CCaptureVideo();
virtual ~CCaptureVideo();
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);
void ResizeVideoWindow();
HRESULT SetupVideoWindow();
HRESULT InitCaptureGraphBuilder();
};
#endif // !defined(AFX_CAPTUREVIDEO_H__F5345AA4_A39F_4B07_B843_3D87C4287AA0__INCLUDED_)
//-------------------------------------------------------------------
// CCaptureVideo视频捕捉类实现文件CaptureVideo.cpp
//-------------------------------------------------------------------
// CaptureVideo.cpp: implementation of the CCaptureVideo class.
//
/////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "CaptureVideo.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
BOOL bOneShot=FALSE;//全局变量
class CSampleGrabberCB : public ISampleGrabberCB
{
public:
long lWidth;
long lHeight;
TCHAR m_szFileName[MAX_PATH];// 位图文件名称
CSampleGrabberCB( ){
strcpy(m_szFileName, "c:\\donaldo.bmp");
}
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, BYTE * pBuffer, long lBufferSize ){
if( !bOneShot )return 0;

if (!pBuffer)return E_POINTER;
SaveBitmap(pBuffer, lBufferSize);
bOneShot = FALSE;
return 0;
}
//创建位图文件
BOOL SaveBitmap(BYTE * pBuffer, long lBufferSize )
{
HANDLE hf = CreateFile(
m_szFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL,
CREATE_ALWAYS, NULL, NULL );
if( hf == INVALID_HANDLE_VALUE )return 0;
// 写文件头
BITMAPFILEHEADER bfh;
memset( &bfh, 0, sizeof( bfh ) );
bfh.bfType = ’MB’;
bfh.bfSize = sizeof( bfh ) + lBufferSize + sizeof( BITMAPINFOHEADER );
bfh.bfOffBits = sizeof( BITMAPINFOHEADER ) + sizeof( BITMAPFILEHEADER );
DWORD dwWritten = 0;
WriteFile( hf, &bfh, sizeof( bfh ), &dwWritten, NULL );
// 写位图格式
BITMAPINFOHEADER bih;
memset( &bih, 0, sizeof( bih ) );
bih.biSize = sizeof( bih );
bih.biWidth = lWidth;
bih.biHeight = lHeight;
bih.biPlanes = 1;
bih.biBitCount = 24;
WriteFile( hf, &bih, sizeof( bih ), &dwWritten, NULL );
// 写位图数据
WriteFile( hf, pBuffer, lBufferSize, &dwWritten, NULL );
CloseHandle( hf );
return 0;
}
};
CSampleGrabberCB mCB;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCaptureVideo::CCaptureVideo()
{
//COM Library Intialization
if(FAILED(CoInitialize(NULL))) /*, COINIT_APARTMENTTHREADED)))*/
{
AfxMessageBox("CoInitialize Failed!\r\n");
return;
}
m_hWnd = NULL;
m_pVW = NULL;
m_pMC = NULL;
m_pGB = NULL;
m_pCapture = NULL;
}
CCaptureVideo::~CCaptureVideo()
{
// 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( );
}
int CCaptureVideo::EnumDevices(HWND hList)
{
if (!hList)
return -1;
int id = 0;

//枚举视频扑捉设备
ICreateDevEnum *pCreateDevEnum;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void**)&pCreateDevEnum);

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

if (hr != NOERROR)return -1;
pEm->Reset();
ULONG cFetched;
IMoniker *pM;
while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)
{
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)
{
TCHAR str[2048];
id++;
WideCharToMultiByte(CP_ACP,0,var.bstrVal, -1, str, 2048, NULL, NULL);
::SendMessage(hList, CB_ADDSTRING, 0,(LPARAM)str);
SysFreeString(var.bstrVal);
}
pBag->Release();
}
pM->Release();
}
return id;
}
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))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;
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 ;
SetupVideoWindow();
hr = m_pMC->Run();//开始视频捕捉
if(FAILED(hr)){AfxMessageBox("Couldn’t run the graph!");return hr;}
return S_OK;
}
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;
}

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;
}
HRESULT CCaptureVideo::SetupVideoWindow()
{
HRESULT hr;
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;
ResizeVideoWindow();
hr = m_pVW->put_Visible(OATRUE);
return hr;
}
void CCaptureVideo::ResizeVideoWindow()
{
if (m_pVW){
//让图像充满整个窗口
CRect rc;
::GetClientRect(m_hWnd,&rc);
m_pVW->SetWindowPosition(0, 0, rc.right, rc.bottom);
}
}
void CCaptureVideo::GrabOneFrame(BOOL bGrab)
{
bOneShot = bGrab;
}
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;
}
}

如何使用视频捕捉类CCaptureVideo

构建CCaptureVideo类以后,使用就方便多了,我们在编程中只需要是要下面三个类成员函数就可以实现用摄像头进行视频捕捉:

①int EnumDevices(HWND hList); //hList是下拉列表框的句柄,本函数用于枚举当前系统安装的所有视频捕捉设备

②HRESULT Init(int iDeviceID,HWND hWnd);//iDeviceID是视频捕捉设备序号,hWnd是视频捕捉窗口的句柄

③void GrabOneFrame(BOOL bGrab);//调用GrabOneFrame(true)就可以捕获当前的静态图像并保存到硬盘上

具体示例:用MFC AppWizard(exe)创建一个对话框应用程序,取名为ds,给对话框添加一个下拉列表框(IDC_COMBO1)、两个按钮(IDC_PHOTO、IDC_HAVEALOOK)和一个Picture控件(ID:IDC_STATIC_SCREEN,Type: Rectangle,Color:Gray)。

1、使用向导添加成员变量

CStatic m_staticScreen; // IDC_STATIC_SCREEN
CComboBox m_ListCtrl; // IDC_COMBO1
CCaptureVideo m_cap;

2、为BOOL CDsDlg::OnInitDialog()添加如下代码:

// TODO: Add extra initialization here
m_cap.EnumDevices (m_ListCtrl);
m_ListCtrl.SetCurSel (0);

3、为确定按钮添加代码如下:

void CDsDlg::OnOK()
{
//只需要四行代码就可以进行视频捕捉了
UpdateData();
HWND hWnd = m_staticScreen.GetSafeHwnd() ;
HRESULT hr = m_cap.Init(m_ListCtrl.GetCurSel (),hWnd);
GetDlgItem(IDOK)->EnableWindow(FALSE);
}

4、如果希望捕捉静态图像,为照相按钮添加如下代码:

void CDsDlg::OnPhoto()
{
m_cap.GrabOneFrame(true);
}

运行程序时,选定摄像头后只需要按确定就可以了。

结束语

本文提供的视频捕捉类CcaptureVideo和示例,在Win2K + DirectX9 SDK + VC6 环境下调试通过。注意:编译时需要Strmiids.lib Quartz.lib两个库文件(DirectX9 SDK自带)。

分享到: 更多
蓝客门户
北京pk10冠军预测 北京pk105码公式最牛 北京快乐8预测推荐号码推荐 北京pk10高手技巧最新 北京快乐8遗漏走势图 河南快赢481所有玩法
北京pk10冠亚和遗漏 北京赛车pk10冠亚和 北京pk10技巧万能码 北京快乐8开奖号码
北京pk10冠亚和对刷 北京赛车pk10冠亚技巧 北京pk10冠亚和遗漏 北京赛车pk10冠亚技巧 北京pk10冠亚和遗漏 北京pk10冠亚和对刷
北京pk10倍投计划 北京赛车pk10精准计划 北京pk10中奖概率 快乐彩12选5投注 上海时时乐开奖时间 上海时时乐开奖结果
加盟特色早点 美式早餐加盟 早点餐饮加盟 早餐加盟费用 特色早点小吃加盟
娘家早餐加盟 美味早点加盟 早餐系列 天津早点小吃培训加盟 品牌早餐加盟
范征早餐加盟 汤包加盟 早餐餐饮加盟 早点快餐加盟 健康早餐加盟
知名早餐加盟 春光早餐加盟 早餐系列 卖早点加盟 清真早餐加盟
快乐8金木水火土玩法 怎么赚钱快 北京十一选五直播 河北20选5玩法 好的娱乐城
11选5免费计划软件 小龙女心水论坛 时时彩一天赚200元方法 彩娃彩票是真的吗 极速赛车rain
pk10如何将100玩到一万 海南私彩开奖 内蒙古时时彩玩法 甘肃11选5公式 澳洲幸运10开奖直播
2013六合彩图库 555彩票网 G彩彩票 天津11选五 贵州十一选五网址下载