VC捕捉摄像头图像入门源码要点_第1页
VC捕捉摄像头图像入门源码要点_第2页
VC捕捉摄像头图像入门源码要点_第3页
VC捕捉摄像头图像入门源码要点_第4页
VC捕捉摄像头图像入门源码要点_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、【转】VC捕捉摄像头图像入门源码VC捕捉摄像头图像入门源码(非常适合新手)(转)默认分类2009-11-02 17:46:56 阅读39评论0字号:大中 小此源码是我更改过的基于 VFW(Video for Windows)的源码,使用了定时器能 实时的显示图像,从网上可搜到原版源码,但是原版的功能是保存为一个文件, 且不能实时显示,此版本虽然能显示,但感觉反应速度不是很快,没有基于 DirectShow的程序更新速度快,不过在 WM_PAINT息处理里加while(1)capGrabFrame(ghWndCap);刷新速度就快很多了,但是这样程序就进 入死循环不能再处理其他消息,至于怎样改进

2、,就靠读者你了。/源码的任何部分都可以在 MSDN!查至IJ,请参考 MSDN#include <windows.h>#include <stdio.h>#include <vfw.h>#pragma comment(lib,"vfw32.lib")HWND ghWndCap ; /f甫获窗的句柄CAPSTATUS gCapStatus ; / 捕获窗的状态CAPDRIVERCAPS gCapDriverCaps ; 视频驱动的能力 char gachBuffer20;/char szCaptureFile口 = "CamCap

3、ture.AVI"/ / StatusCallbackProc: 册这个回调函数。/ hWnd:/ nID:/ lpStatusText:状态回调函数,使用capSetCallbackOnStatus 宏来注捕获窗体句柄当前状态的状态码 当前状态的文本字符/LRESULT CALLBACK StatusCallbackProc(HWND hWnd,int nID,LPSTR lpStatusText)if(!ghWndCap)return FALSE;/获得捕获窗的状态capGetStatus(ghWndCap,&gCapStatus,sizeof(CAPSTATUS);/

4、更新捕获窗的大小 , 得到消息 WM_CAP_GET_STATUSSetWindowPos(ghWndCap,NULL,0,0,gCapStatus.uiImageWidth,gCapStatus.uiI mageHeight,SWP_NOZORDER|SWP_NOMOVE);if(nID=0)/ 清除旧的状态信息SetWindowText(ghWndCap,(LPSTR)"hello");return (LRESULT)TRUE;/ 显示状态 ID 和状态文本wsprintf(gachBuffer,"Status# %d: %s",nID,lpStat

5、usText);SetWindowText(ghWndCap,(LPSTR)gachBuffer);return (LRESULT)TRUE;/ ErrorCallbackProc:错误回调函数, 过 capSetCallbackOnError 宏来 注册回调捕获窗口句柄错误代码关于错误的文本信息/ hWnd:/ nErrID: / lpErrorText: /LRESULT CALLBACK ErrorCallbackProc(HWND hWnd,int nErrID,LPSTR lpErrorText)if(!ghWndCap)return FALSE;if(nErrID=0)return

6、 TRUE;/ 清除旧的错误wsprintf(gachBuffer,"Error# %d",nErrID);/ 显示错误标识和文本MessageBox(hWnd, lpErrorText, gachBuffer,MB_OK | MB_ICONEXCLAMATION); return (LRESULT) TRUE;/ FrameCallbackProc: 帧回调函数, 通过 capSetCallbackFrame 宏来注册捕获窗体句柄指向一个包含帧信息的数据结构体回调函数/ hWnd:/ lpVHdr: / /LRESULT CALLBACK FrameCallbackPro

7、c(HWND hWnd,LPVIDEOHDR lpVHdr) FILE *fp;fp=fopen("caram.dat","w");if(!ghWndCap)return FALSE;/ 假设 fp 为一打开的 .dat 文件指针fwrite(lpVHdr->lpData,1,lpVHdr->dwBufferLength,fp); return (LRESULT)TRUE;/ /TimerProc 函数处理定时器,在这里抓取并显示图像/VOID CALLBACK TimerProc(HWND hwnd,/ handle to windowUI

8、NT uMsg,/ WM_TIMER messageUINT_PTR idEvent, / timer identifierDWORD dwTime/ current system time)capGrabFrame(ghWndCap);/ 主回调函数/LRESULT CALLBACK WindowProc(HWND hwnd,/ handle to windowUINT uMsg,/ message identifierWPARAM wParam, / first message parameter LPARAM lParam / second message parameter )/ HD

9、C hdc;/ PAINTSTRUCT ps;/ RECT rect;switch(uMsg)case WM_CREATE:ghWndCap=capCreateCaptureWindow(LPSTR)"Capture Window",WS_CHILD|WS_VISIBLE,0,0,320,240,(HWND)hwnd,(int)0);capSetCallbackOnError(ghWndCap,(FARPROC)ErrorCallbackProc);capSetCallbackOnStatus(ghWndCap,(FARPROC)StatusCallbackProc); c

10、apSetCallbackOnFrame(ghWndCap,(FARPROC)FrameCallbackProc);capDriverConnect(ghWndCap,0); / 将捕获窗同驱动连接capDriverGetCaps(ghWndCap,&gCapDriverCaps,sizeof(CAPDRIVERCAPS);/ 获得驱动的能力 , 相关的信息放在结构变量gCapDriverCaps 中capPreviewRate(ghWndCap, 66); /uses this macro to set the framedisplay rate for preview mode t

11、o 66 milliseconds per framecapPreview(ghWndCap, TRUE); /and then uses the capPreview macro to place the capture window in preview mode.if(gCapDriverCaps.fHasOverlay) / 检查驱动器是否有叠加能力capOverlay(ghWndCap,TRUE); / 启动 Overlay 模式if(gCapDriverCaps.fHasDlgVideoSource)capDlgVideoSource(ghWndCap);/Video source

12、 对话框if(gCapDriverCaps.fHasDlgVideoFormat)capDlgVideoFormat(ghWndCap);/ Video format 对话框if(gCapDriverCaps.fHasDlgVideoDisplay)capDlgVideoDisplay(ghWndCap); / Video display 对话框/ capFileSetCaptureFile( ghWndCap,szCaptureFile); / 将要保存的文件名设为本源文件开头处的全局字符串常量/ capFileAlloc(ghWndCap, (1024L * 1024L * 5); / 为

13、捕获文件分配存储空间capCaptureSequence(ghWndCap); / 开始捕获视频序列/ capGrabFrame(ghWndCap); / 捕获单帧图像SetTimer(hwnd,1,10,TimerProc);break;case WM_PAINT:capGrabFrame(ghWndCap);/* hdc=BeginPaint(hwnd,&ps);GetClientRect(hwnd,&rect);DrawText(hdc,TEXT("Hello,WindowsXP!"),-1,&rect,DT_SINGLELINE|DT_CEN

14、TER|DT_VCENTER);EndPaint(hwnd,&ps);*/break;case WM_CLOSE: if(IDYES=MessageBox(hwnd,"Sure exit ?","CamCapture",MB_YESNO) DestroyWindow(hwnd); break;case WM_DESTROY:KillTimer(hwnd,1);capSetCallbackOnStatus(ghWndCap,NULL); capSetCallbackOnError(ghWndCap,NULL); capSetCallbackOnFr

15、ame(ghWndCap,NULL); capCaptureAbort(ghWndCap);/ 停止捕获 capDriverDisconnect(ghWndCap); / 将捕获窗同驱动断开 PostQuitMessage(0); break;default:return DefWindowProc(hwnd,uMsg,wParam,lParam); return 0;/ 主函数int WINAPI WinMain(HINSTANCE hInstance,/ handle to currentinstanceHINSTANCE hPrevInstance, / handle to previo

16、us instanceLPSTR lpCmdLine,/ command lineint nCmdShow/ show state) static TCHAR szAppName=TEXT("CamCapture"); WNDCLASS wndcls; HWND hwnd; MSG msg;wndcls.cbClsExtra=0;wndcls.cbWndExtra=0;wndcls.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH); wndcls.hCursor=LoadCursor(NULL,IDC_CROSS); wnd

17、cls.hIcon=LoadIcon(NULL,IDI_QUESTION); wndcls.hInstance=hInstance;wndcls.lpfnWndProc=WindowProc;wndcls.lpszClassName="CamCapture"wndcls.lpszMenuName=NULL;wndcls.style=CS_HREDRAW | CS_VREDRAW;if(!RegisterClass(&wndcls)MessageBox(NULL,TEXT("This program requires Windows NT!"),s

18、zAppName,MB_ICONERROR);return 0;hwnd=CreateWindow("CamCapture","CamCapture",WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,CW_USEDEFAULT,320,240,NULL,NULL,hInstance,NULL);ShowWindow(hwnd,nCmdShow);UpdateWindow(hwnd);while(GetMessage(&msg,NULL,0,0)TranslateMessage(&msg);DispatchMessag

19、e(&msg);return 0;摘要: 本文主要讲述用 Directshow 进行视频捕捉 (捕捉静态图像) 的编程思路,并提供针对摄像头编程的一个视频捕捉类CcaptureVideo 和一个示例。、户 、.前言DirectShow是微软公司提供的一套在 Windows平台上进行流媒体处理的开发包,与 DirectX 开发包一起发布。 DirectShow 为多媒体流的捕捉和回放提供了强有力的支持。用 DirectShow 开发应用程序,我们可以很方便地从支持WDM驱动模型的采集卡上捕获数据,并且进行相应的后期处理乃至存储到文件中。DirectShow是基于COM勺,为了编写 Dir

20、ectShow应用程序,需要了解 COM客户程序编写的基础知识。 DirectShow 提供了大量的接口,但在编程中发现还是不够方便, 如果能构建一个视频捕捉类把常用的一些动作封装起来, 那么就更方便了。编程思路为了更加容易建立视频捕捉应用程序, DirectShow 提供了一个叫做CaptureGraph Builder 的对象, Capture Graph Builder 提供 IcaptureGraphBuilder2 接口,该接口可以建立和控制 Capture Graph 。建立视频捕捉程序,必须首先获取并初始化 IcaptureGraphBuilder2 接口,然后选择一个适当的视频

21、捕捉设备。选择好设备后,为该设备创建Capturefilter ,然后调用 AddFilter 把 Capture filter 添加到 Filter Graph 。如果仅仅希望用摄像头来进行实时监控的话,只需要在上面的基础上调用ICaptureGraphBuilder2:RenderStream 就可以了:ICaptureGraphBuilder2 *pBuild; / Capture Graph Builder/ 省略初始化部分代码IBaseFilter *pCap; / Video capture filter./ 省略初始化和添加到 Filter Graph 部分代码pBuild-&g

22、t;RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pCap, NULL, NULL);DirectShow 提供了一个捕捉静态图像的方法: 使用 SampleGrabber filter 。依次按照以下三个步骤就可以了:第一步 , 定义一个类实现Sample Grabber 的回调接口 IsampleGrabberCB :class CSampleGrabberCB : public ISampleGrabberCB / 在后面提供的类中具体完成CSampleGrabberCB mCB;第二步、调用 RenderSt

23、ream 依次把 Still pin 、 Sample Grabber 和系统默 认 Renderer Filter 连接起来。第三步、配置Sample Grabber 以捕获数据。视频捕捉类CCaptureVideo 的具体实现/ CCaptureVideo 视频捕捉类头文件/#if !defined(AFX_CAPTUREVIDEO_H_F5345AA4_A39F_4B07_B843_3D87C4287AA0 _INCLUDED_)#defineAFX_CAPTUREVIDEO_H_F5345AA4_A39F_4B07_B843_3D87C4287AA0_INCLUDED_ / Captu

24、reVideo.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; #endifclass CSampleGrabberCB;class CCaptureVideo

25、 : public CWndfriend 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_pM

26、C;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_A3

27、9F_4B07_B843_3D87C4287AA0_INCLUDED_)/ CCaptureVideo 视频捕捉类实现文件 CaptureVideo.cpp/ CaptureVideo.cpp: implementation of the CCaptureVideo class./#include "stdafx.h"#include "CaptureVideo.h"#ifdef _DEBUG#undef THIS_FILEstatic char THIS_FILE=_FILE_;#define new DEBUG_NEW#endifBOOL bOneS

28、hot=FALSE;/全局变量class CSampleGrabberCB : public ISampleGrabberCBpublic:long lWidth;long lHeight;TCHAR m_szFileNameMAX_PATH;位图文件名称CSampleGrabberCB( )strcpy(m_szFileName, "c:donaldo.bmp");STDMETHODIMP_(ULONG) AddRef() return 2; STDMETHODIMP_(ULONG) Release() return 1; STDMETHODIMP QueryInterf

29、ace(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

30、, 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

31、, NULL );if( hf = INVALID_HANDLE_VALUE )return 0;/ 写文件头BITMAPFILEHEADER bfh;memset( &bfh, 0, sizeof( bfh ) );bfh.bfType = MB;bfh.bfSize = sizeof( bfh ) + lBufferSize + sizeof( BITMAPINFOHEAD)E; Rbfh.bfOffBits = sizeof( BITMAPINFOHEADER ) +sizeof( BITMAPFILEHEADER );DWORD dwWritten = 0;WriteFile(

32、 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 );/ 写位图数据Writ

33、eFile( hf, pBuffer, lBufferSize, &dwWritten, NULL );CloseHandle( hf );return 0;CSampleGrabberCB mCB;/ Construction/Destruction/CCaptureVideo:CCaptureVideo()/COM Library Intializationif(FAILED(CoInitialize(NULL) /*, COINIT_APARTMENTTHREADED)*/AfxMessageBox("CoInitialize Failed!rn");retu

34、rn;m_hWnd = NULL;m_pVW = NULL;m_pMC = NULL;m_pGB = NULL;m_pCapture = NULL;CCaptureVideo:CCaptureVideo()/ Stop media playbackif(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)

35、;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<

36、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_IP

37、ropertyBag, (void *)&pBag); if(SUCCEEDED(hr)VARIANT var;var.vt = VT_BSTR;hr = pBag->Read(L"FriendlyName", &var, NULL);if (hr = NOERROR)TCHAR str2048;id+;WideCharToMultiByte(CP_ACP,0,var.bstrVal, -1, str, 2048, NULL, NULL);:SendMessage(hList, CB_ADDSTRING, 0,(LPARAM)str);SysFreeS

38、tring(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 w

39、as 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 grabberhr = m_pGrabber.CoCreateInstance( CLSID_Sampl

40、eGrabber );if( !m_pGrabber )AfxMessageBox("Fail to create SampleGrabber, maybeqedit.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_Vi

41、deo;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");re

42、turn hr;/ try to render preview/capture pinhr = 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(&

43、quot;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 = v

44、ih->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

45、graph!");return hr; return S_OK;bool CCaptureVideo:BindFilter(int deviceId, IBaseFilter *pFilter)if (deviceId < 0) return false;/ enumerate all video capture devicesCComPtr<ICreateDevEnum> pCreateDevEnum;HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,CLSCTX_INPROC_SERVER,II

46、D_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 = p

47、Em->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 = devic

48、eId)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_IGrap

49、hBuilder, (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()HR

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论