这是很早以前写的一个算法(貌似先前是参照某本书来写的),现贴出来。
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; };
/* 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); } */