MFC窗口视频显示方法--OpenCV DirectShow模式
2013-10-31 17:35
651 查看
OpenCV DirectShow模式,中文OpenCv提供了一个 CameraDS类
代码如下:
CameraDS.h
CameraDS.cpp
1:将这两个文件复制到您的项目,同时复制有DirectShow的Include目录
2:在项目属性设置包含目录
3:在代码中
#include <cv.h>
#include <highgui.h>
#include "camerads.h"
4:代码实现如下
代码如下:
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设置的摄像头的宽和高,如果摄像头不支持所设定的宽度和高度,则返回false bool 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 in BindFilter(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 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 <= 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_Composite void 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 changed if (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 devices CComPtr<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 devices CComPtr<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; //ScreenToClient int 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); else cvFlip( 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 VFW模式
- opencv2 在mfc窗口中显示关于cv::Mat 的解决方法
- 【MFC两种视频图像采集方法】DirectShow与Opencv
- 利用MFC和opencv读取视频显示图像方法
- 【MFC两种视频图像採集方法】DirectShow与Opencv
- 在MFC中通过opencv显示摄像头视频或者文件视频
- OpenCV学习笔记(5)在单个窗口中显示多个视频子窗口
- 在mfc中利用opencv打开摄像头并显示在窗口上
- 彻底解决显示Opencv中Mat图像到Mfc窗口问题
- (转)SDL2.0在mfc窗口中显示yuv的一种方法
- 在MFC控件中显示opencv库中的图像或者视频
- OpenCV+DirectShow+MFC显示两个摄像机
- OpenCV在Qt中显示视频的两种方法
- 【转载】SDL2.0在mfc窗口中显示yuv的一种方法 分类: ffmpeg-SDL-VLC-Live555 2013-08-28 11:33 1124人阅读 评论(0) 收藏
- 转 SDL2.0在mfc窗口中显示yuv的一种方法
- SDL2.0在mfc窗口中显示yuv的一种方法
- opencv::将两幅图像合并后,在同一个窗口显示;并将合并的图像流保存成视频文件
- SDL2.0在mfc窗口中显示yuv的一种方法
- VS2017 MFC的Picture Control控件显示opencv3.3图片的方法
- 【转载】SDL2.0在mfc窗口中显示yuv的一种方法