在運動目標檢測中,爲了完善當前構建的背景模型,更好的策略就是更新背景模型。 如果model是當前背景模型,cur是當前幀,則新的模型爲:
modelnew = (1-a)*model+a*cur (a爲學習率),隨着時間的推移,之前的建模圖片權重越來越小。Opencv中提供了cvRunningAvg函數,其中調用了accumulateWeighted函數(源代碼可參考accum.cpp)。
做了一個實驗,在二幀幀差法使用背景更新。二幀幀差法將前一幀作爲背景,前後兩幀間如果目標運動幅度不是很大,則存在大部分的區域重疊,從而導致檢測出來的運動目標存在“空洞”現象。
部分代碼如下:
IplImage * pFrame=NULL; //當前幀
IplImage * pFrImg=NULL; //前景
IplImage * pBkImg=NULL; //背景
CvMat* pFrameMat=NULL;
CvMat* pFrMat=NULL;
CvMat* pBkMat=NULL;
CvCapture * pCapture;
int nFrmNum=0;
cvNamedWindow("視頻",1);
cvNamedWindow("背景",1);
cvNamedWindow("前景",1);
pCapture =cvCreateFileCapture(…………………………)
while(pFrame=cvQueryFrame(pCapture))
{
if(!pFrame) //判斷幀是否有效
break;
nFrmNum++;
//如果是第一幀,需要申請內存,並初始化
if(nFrmNum==1)
{
pBkImg=cvCreateImage(cvSize(pFrame->width, pFrame->height),8,1);
pFrImg=cvCreateImage(cvSize(pFrame->width, pFrame->height),8,1);
pBkMat=cvCreateMat(pFrame->height,pFrame->width,CV_32FC1);
pFrMat=cvCreateMat(pFrame->height,pFrame->width,CV_32FC1);
pFrameMat=cvCreateMat(pFrame->height,pFrame->width,CV_32FC1);
cvCvtColor(pFrame,pBkImg,CV_BGR2GRAY);
cvCvtColor(pFrame,pFrImg,CV_BGR2GRAY);
cvConvert(pFrImg,pFrameMat);
cvConvert(pFrImg,pFrMat);
cvConvert(pFrImg,pBkMat);
}
else
{
//將幀圖像轉化爲灰度圖像
cvCvtColor(pFrame,pFrImg, CV_BGR2GRAY);
cvConvert(pFrImg,pFrameMat);
cvAbsDiff(pFrameMat,pBkMat,pFrMat);
cvThreshold(pFrMat, pFrImg, 60, 255.0, CV_THRESH_BINARY);
cvRunningAvg(pFrameMat,pBkMat,0.005,0);// 移動背景跟新
cvConvert(pBkMat,pBkImg);
//在視頻窗口中顯示幀圖像,進行視頻播放
cvShowImage("視頻",pFrame);
cvShowImage("前景",pFrImg);
cvShowImage("背景",pBkImg);
//爲了觀察效果,人爲控制視頻播放速度
char c=cvWaitKey(30);
if(c==27) //按下Esc鍵退出視頻播放
break;
}
}
cvDestroyWindow("視頻");
cvDestroyWindow("前景");
cvDestroyWindow("背景");
截取開始時背景 和 經過一段時間後的背景
可以看出的是,對於一直有運動目標的視頻,背景更新能夠還原出靜止的路面狀況。
背景更新提出是基於統計平均背景法,計算滑動平均值,我的想法是在計算出前多少幀的平均背景之後,根據當前幀更新圖像累積庫,重新計算平均值。【之後補充這部分代碼和實驗結果】