这是很早以前写的一个算法(貌似先前是参照某本书来写的),现贴出来。
转帖,请注明出处:
http://cvchina.net/blog-423-182.html
这是该算法的.h文件:
class StatAverageModel
{
public:
StatAverageModel();
StatAverageModel(CvCapture* pCapture,int Iteration);
void Detect(IplImage* frame,float highSclae,float lowScale);// default value high=7.0,low=6.0
IplImage* getForeground(){return pForeImg;};
virtual ~StatAverageModel();
private:
void setHighThreshold(float scale);
void setLowThreshold(float scale);
IplImage* pFrame;
IplImage* pavgF,* pdiffF,*pprevf,*pHif,*plowF;
IplImage* pscratch,*pscratch2;
IplImage* pgray1,*pgray2,*pgray3;
IplImage* plow1,*plow2,*plow3;
IplImage* phi1,*phi2,*phi3;
IplImage* pmaskt;
IplImage* pForeImg;
int gIteration;
int gHeight;
int gWidth;
int tmpNum;
};
下面是该算法的.cpp文件:
/*
if you use the mean and variation to model the background ,you can do as follows:
1. calculate the sum of image sequences, you can apply the function: cvAcc();
2. also have another choice: cvRunningAvg();
for the variation of each pixel, we can compute the accumulate squre image with the function
cvSquareAcc();
then the variation cam be computed with : simga^2= 1/N(x1^2+x2^2+...+xn^2)-(1/N(x1+x2+...+xn)^2)
统计平均法的基本思想:
计算每个像素的平均值和标准差(或者相似的,但计算速度更快的平均差值)作为背景模型。
*/
StatAverageModel::StatAverageModel()
{
}
StatAverageModel::StatAverageModel(CvCapture* pCapture,int Iteration)
{
pFrame=cvQueryFrame(pCapture);
pFrame=cvQueryFrame(pCapture);
gIteration=Iteration;
gHeight=pFrame->height;
gWidth=pFrame->width;
CvSize size=cvGetSize(pFrame);
pavgF=cvCreateImage(size,IPL_DEPTH_32F,3);
pdiffF=cvCreateImage(size,IPL_DEPTH_32F,3);
pprevf=cvCreateImage(size,IPL_DEPTH_32F,3);
plowF=cvCreateImage(size,IPL_DEPTH_32F,3);
pHif=cvCreateImage(size,IPL_DEPTH_32F,3);
pscratch=cvCreateImage(size,IPL_DEPTH_32F,3);
pscratch2=cvCreateImage(size,IPL_DEPTH_32F,3);
plow1=cvCreateImage(size,IPL_DEPTH_32F,1);
plow2=cvCreateImage(size,IPL_DEPTH_32F,1);
plow3=cvCreateImage(size,IPL_DEPTH_32F,1);
phi1=cvCreateImage(size,IPL_DEPTH_32F,1);
phi2=cvCreateImage(size,IPL_DEPTH_32F,1);
phi3=cvCreateImage(size,IPL_DEPTH_32F,1);
pgray1=cvCreateImage(size,IPL_DEPTH_32F,1);
pgray2=cvCreateImage(size,IPL_DEPTH_32F,1);
pgray3=cvCreateImage(size,IPL_DEPTH_32F,1);
pmaskt=cvCreateImage(size,IPL_DEPTH_8U,1);
pForeImg=cvCreateImage(size,IPL_DEPTH_8U,1);
tmpNum=1;
cvConvertScale(pFrame,pscratch,1.0,0);
cvCopy(pscratch,pprevf);
}
void StatAverageModel::setHighThreshold(float scale)
{
cvConvertScale(pdiffF,pscratch,scale);
cvAdd(pscratch,pavgF,pHif);
cvSplit(pHif,phi1,phi2,phi3,NULL);
}
void StatAverageModel::setLowThreshold(float scale)
{
cvConvertScale(pdiffF,pscratch,scale);
cvAdd(pscratch,pavgF,plowF);
cvSplit(plowF,plow1,plow2,plow3,NULL);
}
void StatAverageModel::Detect(IplImage* frame,float highScale,float lowScale)
{
cvZero(pscratch);
cvConvertScale(frame,pscratch,1.0,0);
if (tmpNum<=gIteration)
{
cvAcc(pscratch,pavgF);
cvAbsDiff(pscratch,pprevf,pscratch2);
cvAcc(pscratch2,pdiffF);
tmpNum++;
if (tmpNum==gIteration)
{
cvConvertScale(pavgF,pavgF,(double)(1.0/gIteration));//均值
cvConvertScale(pdiffF,pdiffF,(double)(1.0/gIteration));//累积差值的均值代替标准差
cvAddS(pdiffF,cvScalar(1.0,1.0,1.0),pdiffF);
cvCopy(pscratch,pprevf);
setHighThreshold(highScale);
setLowThreshold(lowScale);
}
cvCopy(pscratch,pprevf);
}
else
{
cvSplit(pscratch,pgray1,pgray2,pgray3,NULL);
cvInRange(pgray1,plow1,phi1,pForeImg);
cvInRange(pgray2,plow2,phi2,pmaskt);
cvOr(pmaskt,pForeImg,pForeImg);
cvZero(pmaskt);
cvInRange(pgray3,plow3,phi3,pmaskt);
cvOr(pmaskt,pForeImg,pForeImg);
cvSubRS(pForeImg,cvScalar(255,0,0),pForeImg);
}
}
StatAverageModel::~StatAverageModel()
{
cvReleaseImage(&pFrame);
cvReleaseImage(&pavgF);
cvReleaseImage(&pdiffF);
cvReleaseImage(&pprevf);
cvReleaseImage(&pHif);
cvReleaseImage(&plowF);
cvReleaseImage(&pscratch);
cvReleaseImage(&pscratch2);
cvReleaseImage(&pgray1);
cvReleaseImage(&pgray2);
cvReleaseImage(&pgray3);
cvReleaseImage(&plow1);
cvReleaseImage(&plow2);
cvReleaseImage(&plow3);
cvReleaseImage(&phi1);
cvReleaseImage(&phi2);
cvReleaseImage(&phi3);
cvReleaseImage(&pmaskt);
cvReleaseImage(&pForeImg);
}
/*
调用例子:
// default value high=7.0,low=6.0
StatAverageModel* pInstance=new StatAverageModel(pCapture,100);
while(pFrame=cvQueryFrame(pCapture))
{
FrmNum++;
pInstance->Detect(pFrame,7.0,6.0);
pForeImg=pInstance->getForeground();
pForeImg->origin=1;
cvShowImage("frame",pFrame);
cvShowImage("fore",pForeImg);
cvWaitKey(5);
}
*/