MFC窗口视频显示方法--OpenCV DirectShow模式
来源:互联网 发布:北京大学软件共享平台 编辑:程序博客网 时间:2024/06/12 18:30
OpenCV DirectShow模式,中文OpenCv提供了一个 CameraDS类
代码如下:
CameraDS.h
//////////////////////////////////////////////////////////////////////// Video Capture using DirectShow// Author: Shiqi Yu (shiqi.yu@gmail.com)// Thanks to://HardyAI@OpenCV China//flymanbox@OpenCV China (for his contribution to function CameraName, and frame width/height setting)// Last modification: April 9, 2009////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 使用说明:// 1. 将CameraDS.h CameraDS.cpp以及目录DirectShow复制到你的项目中// 2. 菜单 Project->Settings->Settings for:(All configurations)->C/C++->Category(Preprocessor)->Additional include directories// 设置为 DirectShow/Include// 3. 菜单 Project->Settings->Settings for:(All configurations)->Link->Category(Input)->Additional library directories// 设置为 DirectShow/Lib//////////////////////////////////////////////////////////////////////#ifndef CCAMERA_H#define CCAMERA_H#define WIN32_LEAN_AND_MEAN#include <windows.h>#include <atlbase.h>#include <cxcore.h>#include "DirectShow/Include/qedit.h"#include "DirectShow/Include/dshow.h"#define MYFREEMEDIATYPE(mt){if ((mt).cbFormat != 0)\{CoTaskMemFree((PVOID)(mt).pbFormat);\(mt).cbFormat = 0;\(mt).pbFormat = NULL;\}\if ((mt).pUnk != NULL)\{\(mt).pUnk->Release();\(mt).pUnk = NULL;\}}class CCameraDS {private:IplImage * m_pFrame;bool m_bConnected;int m_nWidth;int m_nHeight;bool m_bLock;bool m_bChanged;long m_nBufferSize;CComPtr<IGraphBuilder> m_pGraph;CComPtr<IBaseFilter> m_pDeviceFilter;CComPtr<IMediaControl> m_pMediaControl;CComPtr<IBaseFilter> m_pSampleGrabberFilter;CComPtr<ISampleGrabber> m_pSampleGrabber;CComPtr<IPin> m_pGrabberInput;CComPtr<IPin> m_pGrabberOutput;CComPtr<IPin> m_pCameraOutput;CComPtr<IMediaEvent> m_pMediaEvent;CComPtr<IBaseFilter> m_pNullFilter;CComPtr<IPin> m_pNullInputPin;private:bool BindFilter(int nCamIDX, IBaseFilter **pFilter);void SetCrossBar();public:CCameraDS();virtual ~CCameraDS();//打开摄像头,nCamID指定打开哪个摄像头,取值可以为0,1,2,...//bDisplayProperties指示是否自动弹出摄像头属性页//nWidth和nHeight设置的摄像头的宽和高,如果摄像头不支持所设定的宽度和高度,则返回falsebool CCameraDS::OpenCamera(int nCamID, bool bDisplayProperties=true, int nWidth=320, int nHeight=240);//关闭摄像头,析构函数会自动调用这个函数void CloseCamera();//返回摄像头的数目//可以不用创建CCameraDS实例,采用int c=CCameraDS::CameraCount();得到结果。static int CameraCount(); //根据摄像头的编号返回摄像头的名字//nCamID: 摄像头编号//sName: 用于存放摄像头名字的数组//nBufferSize: sName的大小//可以不用创建CCameraDS实例,采用CCameraDS::CameraName();得到结果。static int CCameraDS::CameraName(int nCamID, char* sName, int nBufferSize);//返回图像宽度int GetWidth(){return m_nWidth;} //返回图像高度int GetHeight(){return m_nHeight;}//抓取一帧,返回的IplImage不可手动释放!//返回图像数据的为RGB模式的Top-down(第一个字节为左上角像素),即IplImage::origin=0(IPL_ORIGIN_TL)IplImage * QueryFrame();};#endif
CameraDS.cpp
//////////////////////////////////////////////////////////////////////// Video Capture using DirectShow// Author: Shiqi Yu (shiqi.yu@gmail.com)// Thanks to://HardyAI@OpenCV China//flymanbox@OpenCV China (for his contribution to function CameraName, and frame width/height setting)// Last modification: April 9, 2009////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 使用说明:// 1. 将CameraDS.h CameraDS.cpp以及目录DirectShow复制到你的项目中// 2. 菜单 Project->Settings->Settings for:(All configurations)->C/C++->Category(Preprocessor)->Additional include directories// 设置为 DirectShow/Include// 3. 菜单 Project->Settings->Settings for:(All configurations)->Link->Category(Input)->Additional library directories// 设置为 DirectShow/Lib//////////////////////////////////////////////////////////////////////// CameraDS.cpp: implementation of the CCameraDS class.////////////////////////////////////////////////////////////////////////#include "CameraDS.h"#pragma comment(lib,"Strmiids.lib") //////////////////////////////////////////////////////////////////////// Construction/Destruction//////////////////////////////////////////////////////////////////////CCameraDS::CCameraDS(){m_bConnected = false;m_nWidth = 0;m_nHeight = 0;m_bLock = false;m_bChanged = false;m_pFrame = NULL;m_nBufferSize = 0;m_pNullFilter = NULL;m_pMediaEvent = NULL;m_pSampleGrabberFilter = NULL;m_pGraph = NULL;CoInitialize(NULL);}CCameraDS::~CCameraDS(){CloseCamera();CoUninitialize();}void CCameraDS::CloseCamera(){if(m_bConnected)m_pMediaControl->Stop();m_pGraph = NULL;m_pDeviceFilter = NULL;m_pMediaControl = NULL;m_pSampleGrabberFilter = NULL;m_pSampleGrabber = NULL;m_pGrabberInput = NULL;m_pGrabberOutput = NULL;m_pCameraOutput = NULL;m_pMediaEvent = NULL;m_pNullFilter = NULL;m_pNullInputPin = NULL;if (m_pFrame)cvReleaseImage(&m_pFrame);m_bConnected = false;m_nWidth = 0;m_nHeight = 0;m_bLock = false;m_bChanged = false;m_nBufferSize = 0;}bool CCameraDS::OpenCamera(int nCamID, bool bDisplayProperties, int nWidth, int nHeight){HRESULT hr = S_OK;CoInitialize(NULL);// Create the Filter Graph Manager.hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,IID_IGraphBuilder, (void **)&m_pGraph);hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (LPVOID *)&m_pSampleGrabberFilter);hr = m_pGraph->QueryInterface(IID_IMediaControl, (void **) &m_pMediaControl);hr = m_pGraph->QueryInterface(IID_IMediaEvent, (void **) &m_pMediaEvent);hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER,IID_IBaseFilter, (LPVOID*) &m_pNullFilter);hr = m_pGraph->AddFilter(m_pNullFilter, L"NullRenderer");hr = m_pSampleGrabberFilter->QueryInterface(IID_ISampleGrabber, (void**)&m_pSampleGrabber);AM_MEDIA_TYPE mt;ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));mt.majortype = MEDIATYPE_Video;mt.subtype = MEDIASUBTYPE_RGB24;mt.formattype = FORMAT_VideoInfo; hr = m_pSampleGrabber->SetMediaType(&mt);MYFREEMEDIATYPE(mt);m_pGraph->AddFilter(m_pSampleGrabberFilter, L"Grabber"); // Bind Device Filter. We know the device because the id was passed inBindFilter(nCamID, &m_pDeviceFilter);m_pGraph->AddFilter(m_pDeviceFilter, NULL);CComPtr<IEnumPins> pEnum;m_pDeviceFilter->EnumPins(&pEnum); hr = pEnum->Reset();hr = pEnum->Next(1, &m_pCameraOutput, NULL); pEnum = NULL; m_pSampleGrabberFilter->EnumPins(&pEnum);pEnum->Reset();hr = pEnum->Next(1, &m_pGrabberInput, NULL); pEnum = NULL;m_pSampleGrabberFilter->EnumPins(&pEnum);pEnum->Reset();pEnum->Skip(1);hr = pEnum->Next(1, &m_pGrabberOutput, NULL); pEnum = NULL;m_pNullFilter->EnumPins(&pEnum);pEnum->Reset();hr = pEnum->Next(1, &m_pNullInputPin, NULL);//SetCrossBar();if (bDisplayProperties) {CComPtr<ISpecifyPropertyPages> pPages;HRESULT hr = m_pCameraOutput->QueryInterface(IID_ISpecifyPropertyPages, (void**)&pPages);if (SUCCEEDED(hr)){PIN_INFO PinInfo;m_pCameraOutput->QueryPinInfo(&PinInfo);CAUUID caGUID;pPages->GetPages(&caGUID);OleCreatePropertyFrame(NULL, 0, 0,L"Property Sheet", 1,(IUnknown **)&(m_pCameraOutput.p),caGUID.cElems,caGUID.pElems,0, 0, NULL);CoTaskMemFree(caGUID.pElems);PinInfo.pFilter->Release();}pPages = NULL;}else {//////////////////////////////////////////////////////////////////////////////// 加入由 lWidth和lHeight设置的摄像头的宽和高 的功能,默认320*240// by flymanbox @2009-01-24////////////////////////////////////////////////////////////////////////////// int _Width = nWidth, _Height = nHeight; IAMStreamConfig* iconfig; iconfig = NULL; hr = m_pCameraOutput->QueryInterface(IID_IAMStreamConfig, (void**)&iconfig); AM_MEDIA_TYPE* pmt; if(iconfig->GetFormat(&pmt) !=S_OK) { //printf("GetFormat Failed ! \n"); return false; } VIDEOINFOHEADER* phead; if ( pmt->formattype == FORMAT_VideoInfo) { phead=( VIDEOINFOHEADER*)pmt->pbFormat; phead->bmiHeader.biWidth = _Width; phead->bmiHeader.biHeight = _Height; if(( hr=iconfig->SetFormat(pmt)) != S_OK ) {return false;}} iconfig->Release(); iconfig=NULL; MYFREEMEDIATYPE(*pmt);}hr = m_pGraph->Connect(m_pCameraOutput, m_pGrabberInput);hr = m_pGraph->Connect(m_pGrabberOutput, m_pNullInputPin);if (FAILED(hr)){switch(hr){case VFW_S_NOPREVIEWPIN :break;case E_FAIL :break;case E_INVALIDARG :break;case E_POINTER :break;}}m_pSampleGrabber->SetBufferSamples(TRUE);m_pSampleGrabber->SetOneShot(TRUE); hr = m_pSampleGrabber->GetConnectedMediaType(&mt);if(FAILED(hr))return false;VIDEOINFOHEADER *videoHeader;videoHeader = reinterpret_cast<VIDEOINFOHEADER*>(mt.pbFormat);m_nWidth = videoHeader->bmiHeader.biWidth;m_nHeight = videoHeader->bmiHeader.biHeight;m_bConnected = true;pEnum = NULL;return true;}bool CCameraDS::BindFilter(int nCamID, IBaseFilter **pFilter){if (nCamID < 0)return false; // enumerate all video capture devicesCComPtr<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 <= nCamID) {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 == nCamID){pM->BindToObject(0, 0, IID_IBaseFilter, (void**)pFilter);}SysFreeString(var.bstrVal);}pBag->Release();}pM->Release();index++; }pCreateDevEnum = NULL;return true;}//将输入crossbar变成PhysConn_Video_Compositevoid CCameraDS::SetCrossBar(){int i;IAMCrossbar *pXBar1 = NULL;ICaptureGraphBuilder2 *pBuilder = NULL; HRESULT hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&pBuilder);if (SUCCEEDED(hr)){hr = pBuilder->SetFiltergraph(m_pGraph);}hr = pBuilder->FindInterface(&LOOK_UPSTREAM_ONLY, NULL, m_pDeviceFilter,IID_IAMCrossbar, (void**)&pXBar1);if (SUCCEEDED(hr)) { long OutputPinCount;long InputPinCount;long PinIndexRelated;long PhysicalType;long inPort = 0;long outPort = 0;pXBar1->get_PinCounts(&OutputPinCount,&InputPinCount);for( i =0;i<InputPinCount;i++){pXBar1->get_CrossbarPinInfo(TRUE,i,&PinIndexRelated,&PhysicalType);if(PhysConn_Video_Composite==PhysicalType) {inPort = i;break;}}for( i =0;i<OutputPinCount;i++){pXBar1->get_CrossbarPinInfo(FALSE,i,&PinIndexRelated,&PhysicalType);if(PhysConn_Video_VideoDecoder==PhysicalType) {outPort = i;break;}} if(S_OK==pXBar1->CanRoute(outPort,inPort)){pXBar1->Route(outPort,inPort);}pXBar1->Release(); }pBuilder->Release();}/*The returned image can not be released.*/IplImage* CCameraDS::QueryFrame(){long evCode;long size = 0;m_pMediaControl->Run();m_pMediaEvent->WaitForCompletion(INFINITE, &evCode); m_pSampleGrabber->GetCurrentBuffer(&size, NULL);//if the buffer size changedif (size != m_nBufferSize){if (m_pFrame)cvReleaseImage(&m_pFrame);m_nBufferSize = size;m_pFrame = cvCreateImage(cvSize(m_nWidth, m_nHeight), IPL_DEPTH_8U, 3);}m_pSampleGrabber->GetCurrentBuffer(&m_nBufferSize, (long*)m_pFrame->imageData);cvFlip(m_pFrame);return m_pFrame;}int CCameraDS::CameraCount(){int count = 0; CoInitialize(NULL); // enumerate all video capture devicesCComPtr<ICreateDevEnum> pCreateDevEnum; HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void**)&pCreateDevEnum); CComPtr<IEnumMoniker> pEm; hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEm, 0); if (hr != NOERROR) {return count; } pEm->Reset(); ULONG cFetched; IMoniker *pM; while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK) {count++; }pCreateDevEnum = NULL;pEm = NULL;return count;}int CCameraDS::CameraName(int nCamID, char* sName, int nBufferSize){int count = 0; CoInitialize(NULL); // enumerate all video capture devicesCComPtr<ICreateDevEnum> pCreateDevEnum; HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void**)&pCreateDevEnum); CComPtr<IEnumMoniker> pEm; hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEm, 0); if (hr != NOERROR) return 0; pEm->Reset(); ULONG cFetched; IMoniker *pM; while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK) {if (count == nCamID){IPropertyBag *pBag=0;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) { //获取设备名称WideCharToMultiByte(CP_ACP,0,var.bstrVal,-1,sName, nBufferSize ,"",NULL); SysFreeString(var.bstrVal); } pBag->Release();}pM->Release();break;}count++; }pCreateDevEnum = NULL;pEm = NULL;return 1;}
1:将这两个文件复制到您的项目,同时复制有DirectShow的Include目录
2:在项目属性设置包含目录
3:在代码中
#include <cv.h>
#include <highgui.h>
#include "camerads.h"
4:代码实现如下
void CEVisionDlg::OpenVideo_CDS(){int cam_count= CCameraDS::CameraCount();//仅仅获取摄像头数目if(cam_count==0) return ;CCameraDS camera;HWND hWnd;HWND hParent;RECT rcDlg; //ScreenToClientint vWndType1Height;int vWndType1Windth;int intCamSRCWidth,intCamSRCHeight;int intImgSRCHeight,intImgSRCWindth;intCamSRCWidth=640;intCamSRCHeight=480;intImgSRCWindth=640;intImgSRCHeight=480;//打开第一个摄像头//if(! camera.OpenCamera(0, true)) //弹出属性选择窗口if(! camera.OpenCamera(0, false, intCamSRCWidth,intCamSRCHeight)) return ;//不弹出属性选择窗口,用代码制定图像宽和高GetDlgItem(IDC_SHOW_IMG)->GetWindowRect(&rcDlg);vWndType1Windth = rcDlg.right - rcDlg.left -10;vWndType1Height = vWndType1Windth * intImgSRCHeight;vWndType1Height = vWndType1Height / intImgSRCWindth; cvNamedWindow("AIWndSrcCamera", CV_WINDOW_AUTOSIZE);//创建一个新窗口hWnd = (HWND) cvGetWindowHandle("AIWndSrcCamera"); //通过名字获取窗口句柄hParent = ::GetParent(hWnd);//该函数获得一个指定子窗口的父窗口句柄::SetParent(hWnd, GetDlgItem(IDC_SHOW_IMG)->m_hWnd); //该函数改变某个子窗口的父窗口,HWND SetParent(HWND hWndChild,HWND hWndNewParent);::ShowWindow(hParent, SW_HIDE);cvResizeWindow("AIWndSrcCamera", vWndType1Windth,vWndType1Height);IplImage* m_pFrame = cvCreateImage( cvSize(intImgSRCWindth,intImgSRCHeight), IPL_DEPTH_8U, 3);while (true){m_CameraFrame =camera.QueryFrame();if(!m_CameraFrame)return;else{if( m_CameraFrame->origin == IPL_ORIGIN_TL )cvResize (m_CameraFrame, m_pFrame, CV_INTER_NN);elsecvFlip( m_CameraFrame, m_pFrame, 0 );cvShowImage("AIWndSrcCamera", m_pFrame);if ((cvWaitKey(10) & 255) == 27 ) return ; }}camera.CloseCamera(); //可不调用此函数,CCameraDS析构时会自动关闭摄像头cvReleaseImage(&m_pFrame);cvDestroyWindow("AIWndSrcCamera");}
- MFC窗口视频显示方法--OpenCV DirectShow模式
- MFC窗口视频显示方法--OpenCV VFW模式
- 【MFC两种视频图像采集方法】DirectShow与Opencv
- DirectShow下视频显示窗口设置
- OpenCV+DirectShow+MFC显示两个摄像机
- 利用MFC和opencv读取视频显示图像方法
- OpenCV+MFC显示图像/视频
- OpenCV+MFC显示图像/视频
- opencv + MFC 视频图像显示
- MFC调用Opencv显示视频
- 基于mfc 通过openCV播放avi视频及多显示窗口实现
- MFC DirectShow视频预览
- OpenCv显示窗口移植到MFC
- mfc窗口显示视频+抓图
- mfc中显示opencv单通道视频
- MFC+openCV对话框中显示视频
- 在mfc中用opencv显示视频
- MFC中用OpenCV库显示视频
- 去掉字符串末尾的逗号
- 观察者模式
- Oracle 日期格式类型和日期函数 java操作数据库
- 不用安装oracle客户端访问数据库
- Android 恢复出厂设置的流程
- MFC窗口视频显示方法--OpenCV DirectShow模式
- 简单数组
- Performing Data Pump Exports and Imports
- TFS - 重建Analysis数据库或者修改Analysis数据库文件位置
- 用Maven构建Hadoop项目
- eclipse中修改m2_maven路径
- 解决ubuntu13.10在启动eclipse时菜单栏失效的问题
- 简单分析Linux-3.2.0中断系统
- HTML5 webapp框架