本文提供了使用directshow代替opencv的vfw 的源代码,与转化为iplimage格式的算法.
实验中发现opencv的cvCaptureFromCAM 使用的是vfw,采用消息机制,速度较慢,测试发现fps只有 9-12左右,太慢了. 发现经过使用directshow后速度提升到60帧/s.在opencv group上了解到这是一个普遍问题,也许有人做过转换,却没有完整的例子与代码.在此贴出.对希望提高opencv视频分析速度的有所帮助.
http://hardy.gigcities.com/Directshow_Opencv.rar 下载代码
用法如下:
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(DeviceInf