已阅读5页,还剩12页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【转】VC捕捉摄像头图像入门源码VC捕捉摄像头图像入门源码(非常适合新手)(转) 默认分类 2009-11-02 17:46:56 阅读39 评论0 字号:大中小/此源码是我更改过的基于VFW(Video for Windows)的源码,使用了定时器能实时的显示图像,从网上可搜到原版源码,但是原版的功能是保存为一个文件,且不能实时显示,此版本虽然能显示,但感觉反应速度不是很快,没有基于DirectShow的程序更新速度快,不过在WM_PAINT消息处理里加while(1)capGrabFrame(ghWndCap);刷新速度就快很多了,但是这样程序就进入死循环不能再处理其他消息,至于怎样改进,就靠读者你了。/源码的任何部分都可以在MSDN里查到,请参考MSDN。#include #include #include #pragma comment(lib,vfw32.lib)HWND ghWndCap ; /捕获窗的句柄CAPSTATUS gCapStatus ; /捕获窗的状态CAPDRIVERCAPS gCapDriverCaps ; /视频驱动的能力 char gachBuffer20;/char szCaptureFile = CamCapture.AVI;/ StatusCallbackProc: 状态回调函数,使用capSetCallbackOnStatus宏来注册这个回调函数。/ hWnd: 捕获窗体句柄 / nID: 当前状态的状态码 / lpStatusText: 当前状态的文本字符 /LRESULT CALLBACK StatusCallbackProc(HWND hWnd,int nID,LPSTR lpStatusText)if(!ghWndCap) return FALSE;/获得捕获窗的状态capGetStatus(ghWndCap,&gCapStatus,sizeof(CAPSTATUS);/更新捕获窗的大小,得到消息WM_CAP_GET_STATUSSetWindowPos(ghWndCap,NULL,0,0,gCapStatus.uiImageWidth,gCapStatus.uiImageHeight,SWP_NOZORDER|SWP_NOMOVE);if(nID=0)/清除旧的状态信息 SetWindowText(ghWndCap,(LPSTR)hello); return (LRESULT)TRUE;/显示状态ID和状态文本wsprintf(gachBuffer,Status# %d: %s,nID,lpStatusText);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 TRUE;/清除旧的错误wsprintf(gachBuffer,Error# %d,nErrID);/显示错误标识和文本MessageBox(hWnd, lpErrorText, gachBuffer,MB_OK | MB_ICONEXCLAMATION); return (LRESULT) TRUE;/ / FrameCallbackProc: 帧回调函数,通过capSetCallbackFrame宏来注册回调函数 / hWnd: 捕获窗体句柄 / lpVHdr: 指向一个包含帧信息的数据结构体/ LRESULT CALLBACK FrameCallbackProc(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 window UINT uMsg, / WM_TIMER message UINT_PTR idEvent, / timer identifier DWORD dwTime / current system time )capGrabFrame(ghWndCap);/主回调函数/LRESULT CALLBACK WindowProc( HWND hwnd, / handle to window UINT uMsg, / message identifier WPARAM wParam, / first message parameter LPARAM lParam / second message parameter )/ HDC 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); capSetCallbackOnFrame(ghWndCap,(FARPROC)FrameCallbackProc); capDriverConnect(ghWndCap,0); / 将捕获窗同驱动连接 capDriverGetCaps(ghWndCap,&gCapDriverCaps,sizeof(CAPDRIVERCAPS);/获得驱动的能力,相关的信息放在结构变量gCapDriverCaps中 capPreviewRate(ghWndCap, 66); /uses this macro to set the frame display rate for preview mode to 66 milliseconds per frame capPreview(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 对话框 if(gCapDriverCaps.fHasDlgVideoFormat)capDlgVideoFormat(ghWndCap); / Video format 对话框 if(gCapDriverCaps.fHasDlgVideoDisplay)capDlgVideoDisplay(ghWndCap); / Video display 对话框/ capFileSetCaptureFile( ghWndCap, szCaptureFile); /将要保存的文件名设为本源文件开头处的全局字符串常量 / capFileAlloc(ghWndCap, (1024L * 1024L * 5); /为捕获文件分配存储空间 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,Windows XP!),-1,&rect,DT_SINGLELINE|DT_CENTER|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); capSetCallbackOnFrame(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 current instance HINSTANCE hPrevInstance, / handle to previous instance LPSTR lpCmdLine, / command line int 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);wndcls.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!),szAppName,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); DispatchMessage(&msg);return 0;摘要:本文主要讲述用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 #include #include #ifndef SAFE_RELEASE#define SAFE_RELEASE( x ) if ( NULL != x ) x-Release( ); x = NULL; #endifclass 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 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_FILEstatic char THIS_FILE=_FILE_;#define new DEBUG_NEW#endifBOOL bOneShot=FALSE;/全局变量class CSampleGrabberCB : public ISampleGrabberCB public: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 QueryInterface(REFIID riid, void * ppv)if( riid = IID_ISampleGrabberCB | riid = IID_IUnknown ) *ppv = (void *) static_cast ( 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 Intializationif(FAILED(CoInitialize(NULL) /*, COINIT_APARTMENTTHREADED)*/AfxMessageBox(CoInitialize Failed!rn); return;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);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 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(LFriendlyName, &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);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 inif(!BindFilter(iDeviceID, &m_pBF)return S_FALSE;hr = m_pGB-AddFilter(m_pBF, LCapture Filter);/ hr = m_pCapture-RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, / m_pBF, NULL, NULL);/ create a sample grabberhr = m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );if( !m_pGrabber )AfxMessageBox(Fail to create SampleGrabber, maybe qedit.dll is not registered?);return hr;CComQIPtr 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, LGrabber );if( FAILED( hr ) )AfxMessageBox(Fail to put sample grabber in graph);return 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(Cant 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(Couldnt run the graph!);return hr;return S_OK;bool CCaptureVideo:BindFilter(int deviceId, IBaseFilter *pFilter)if (deviceId 0)return false;/ enumerate all video capture devicesCComPtr pCreateDevEnum;HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void*)&pCreateDevEnum);if (hr != NOERROR)return false;CComPtr 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 BindToStorage(0, 0, IID_IPropertyBag, (void *)&pBag);if(SUCCEEDED(hr) VARIANT var;var.vt = VT_BSTR;hr = pBag-Read(LFriendlyName, &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)re
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 广发壹号停电通知书
- 广州高温停工令通知书
- 广西公务员进面试通知书
- 库尔勒抗疫解封通知书
- 康定中学开学通知书
- 延吉娱乐场所解封通知书
- 延边三中取录通知书
- 建新小区封闭通知书
- 开发区申请解封通知书
- 开封供电停电通知书
- 中医病证诊断疗效标准
- 教育信息化0下教学工具与翻转课堂模式的结合与应用报告
- 中小学教师中高级职称答辩备考试题及答案
- 2025年互联网+护理服务制度考核试题及答案
- 四级手术术前多学科讨论优化
- 超市供应商管理办法
- 电梯仓库配件管理办法
- 检测公司投标管理办法
- DB37-T 5329-2025 城市居民生活节水用水量标准
- 第四单元 整本书阅读 红岩公开课一等奖创新教案(表格式) 统编版语文八年级上册
- 光伏居间合同范本协议书
评论
0/150
提交评论