本文提供了使用directshow代替opencv的vfw 的源代码,与转化为iplimage格式的算法.
实验中发现opencv的cvCaptureFromCAM 使用的是vfw,采用消息机制,速度较慢,测试发现fps只有 9-12左右,太慢了. 发现经过使用directshow后速度提升到60帧/s.在opencv group上了解到这是一个普遍问题,也许有人做过转换,却没有完整的例子与代码.在此贴出.对希望提高opencv视频分析速度的有所帮助.
用法如下:
static ARFrameGrabber frameGrabber;
IplImage ds_frame;
frameGrabber.Init(0, true);
frameGrabber.SetFlippedImage(true);
for(;;)
{
IplImage *frame =0;
frameGrabber.GrabByteFrame();
BYTE *myBuffer = frameGrabber.GetByteBuffer();
int width = frameGrabber.GetWidth();
int height = frameGrabber.GetHeight();
int stride = (width * sizeof( RGBTRIPLE ) + 3) & -4;
cvInitImageHeader( &ds_frame, cvSize(width, height), 8, 3,IPL_ORIGIN_BL, 4 );
ds_frame.widthStep = stride;
cvSetData( &ds_frame, myBuffer, stride );
frame = &ds_frame;
/* 视频分析部分 */
}
以下是directshow源文件,加入工程可用.
// ARFrameGrabber.h: interface for the ARFrameGrabber class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_ARFRAMEGRABBER_H__C5553937_4BAB_4FEF_B4A6_1693AB0C99E3__INCLUDED_)
#define AFX_ARFRAMEGRABBER_H__C5553937_4BAB_4FEF_B4A6_1693AB0C99E3__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
//#include <AR/config.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <dshow.h>
//#include <streams.h>
#include <atlbase.h>
#include <qedit.h>
class SmartString
{
public:
SmartString():str(NULL) {}
SmartString(char* pStr):str(NULL)
{
if (pStr)
{
int size = int(strlen(pStr));
str = new char[size+1];
strcpy(str, pStr);
}
}
SmartString(SmartString& sStr)
{
SetString(sStr.GetBuffer());
}
~SmartString()
{
if (str)
delete[] str;
}
SmartString& operator =(char* pStr)
{
SetString(pStr);
return *this;
}
SmartString& operator =(SmartString& sStr)
{
SetString(sStr.GetBuffer());
return *this;
}
char* GetBuffer() {return str;}
protected:
void SetString(char *pStr)
{
if (str)
delete[] str;
if (!pStr)
{
str = NULL;
}
else
{
int size = int(strlen(pStr));
str = new char[size + 1];
strcpy(str, pStr);
}
}
char* str;
};
class DeviceInfo
{
public:
DeviceInfo():next(NULL), deviceId(-1)
{
}
~DeviceInfo()
{
if (next)
delete next;
}
SmartString friendlyName;
int deviceId;
DeviceInfo* next;
};
class ARFrameGrabber
{
public:
ARFrameGrabber();
virtual ~ARFrameGrabber();
void Init(int deviceId, bool displayProperties = true);
void BindFilter(int deviceId, IBaseFilter **pFilter);
void GrabFrame(long* size, long** pBuffer);
void GrabFrame();
void Grab32BitFrame();
void GrabByteFrame();
void SetCrossBar();
long GetBufferSize() {return bufferSize;}
long* GetBuffer() {return pBuffer;}
BYTE* GetByteBuffer() {return pBYTEbuffer;}
void SetFlippedImage(bool flag) {flipImage = flag;}
void DisplayProperties();
void EnumDevices(DeviceInfo *head);
int GetWidth();
int GetHeight();
protected:
CComPtr<IGraphBuilder> pGraph;
CComPtr<IBaseFilter> pDeviceFilter;
CComPtr<IMediaControl> pMediaControl;
CComPtr<IBaseFilter> pSampleGrabberFilter;
CComPtr<ISampleGrabber> pSampleGrabber;
CComPtr<IPin> pGrabberInput;
CComPtr<IPin> pGrabberOutput;
CComPtr<IPin> pCameraOutput;
CComPtr<IMediaEvent> pMediaEvent;
CComPtr<IBaseFilter> pNullFilter;
CComPtr<IPin> pNullInputPin;
void FlipImage(long* pBuf);
private:
void ReportError(char *msg);
bool flipImage;
long bufferSize;
long *pBuffer;
BYTE *pBYTEbuffer;
bool connected;
int width;
int height;
};
#endif // !defined(AFX_ARFRAMEGRABBER_H__C5553937_4BAB_4FEF_B4A6_1693AB0C99E3__INCLUDED_)
ARFrameGrabber.cpp
// ARFrameGrabber.cpp: implementation of the ARFrameGrabber class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include <assert.h>
#include "ARFrameGrabber.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
ARFrameGrabber::ARFrameGrabber()
: pBuffer(NULL), bufferSize(0), flipImage(false), connected(false), width(0), height(0)
{
}
ARFrameGrabber::~ARFrameGrabber()
{
pMediaControl->Stop();
if (pBuffer)
delete[] pBuffer;
if(pBYTEbuffer)
delete[] pBYTEbuffer;
}
void ARFrameGrabber::Init(int deviceId, bool displayProperties)
{
HRESULT hr = S_OK;
CoInitialize(NULL);
// Create the Filter Graph Manager.
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
IID_IGraphBuilder, (void **)&pGraph);
hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (LPVOID *)&pSampleGrabberFilter);
hr = pGraph->QueryInterface(IID_IMediaControl, (void **) &pMediaControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **) &pMediaEvent);
hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (LPVOID*) &pNullFilter);
hr = pGraph->AddFilter(pNullFilter, L"NullRenderer");
hr = pSampleGrabberFilter->QueryInterface(IID_ISampleGrabber, (void**)&pSampleGrabber);
AM_MEDIA_TYPE mt;
ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
mt.majortype = MEDIATYPE_Video;
mt.subtype = MEDIASUBTYPE_RGB32;
mt.formattype = FORMAT_VideoInfo;
hr = pSampleGrabber->SetMediaType(&mt);
pGraph->AddFilter(pSampleGrabberFilter, L"Grabber");
// Bind Device Filter. We know the device because the id was passed in
BindFilter(deviceId, &pDeviceFilter);
pGraph->AddFilter(pDeviceFilter, NULL);
CComPtr<IEnumPins> pEnum;
pDeviceFilter->EnumPins(&pEnum);
hr = pEnum->Reset();
hr = pEnum->Next(1, &pCameraOutput, NULL);
pEnum = NULL;
pSampleGrabberFilter->EnumPins(&pEnum);
pEnum->Reset();
hr = pEnum->Next(1, &pGrabberInput, NULL);
pEnum = NULL;
pSampleGrabberFilter->EnumPins(&pEnum);
pEnum->Reset();
pEnum->Skip(1);
hr = pEnum->Next(1, &pGrabberOutput, NULL);
pEnum = NULL;
pNullFilter->EnumPins(&pEnum);
pEnum->Reset();
hr = pEnum->Next(1, &pNullInputPin, NULL);
SetCrossBar();
if (displayProperties) {
CComPtr<ISpecifyPropertyPages> pPages;
HRESULT hr = pCameraOutput->QueryInterface(IID_ISpecifyPropertyPages, (void**)&pPages);
if (SUCCEEDED(hr))
{
PIN_INFO PinInfo;
pCameraOutput->QueryPinInfo(&PinInfo);
CAUUID caGUID;
pPages->GetPages(&caGUID);
OleCreatePropertyFrame(
NULL,
0,
0,
L"Property Sheet",
1,
(IUnknown **)&(pCameraOutput.p),
caGUID.cElems,
caGUID.pElems,
0,
0,
NULL);
CoTaskMemFree(caGUID.pElems);
PinInfo.pFilter->Release();
}
}
hr = pGraph->Connect(pCameraOutput, pGrabberInput);
hr = pGraph->Connect(pGrabberOutput, pNullInputPin);
// hr = pGraph->Render(pGrabberOutput);
if (FAILED(hr))
{
switch(hr)
{
case VFW_S_NOPREVIEWPIN :
break;
case E_FAIL :
break;
case E_INVALIDARG :
break;
case E_POINTER :
break;
}
}
pSampleGrabber->SetBufferSamples(TRUE);
pSampleGrabber->SetOneShot(TRUE);
hr = pSampleGrabber->GetConnectedMediaType(&mt);
VIDEOINFOHEADER *videoHeader;
assert(mt.formattype == FORMAT_VideoInfo);
videoHeader = reinterpret_cast<VIDEOINFOHEADER*>(mt.pbFormat);
width = videoHeader->bmiHeader.biWidth;
height = videoHeader->bmiHeader.biHeight;
connected = true;
}









