對這個運動目標檢測方法實現的結果A Hybrid Algorithm for Moving Object Detection

最近在做煙火檢測,需要用到運動檢測,看到論文A System for Video Surveillance and Monitoring中的A Hybrid Algorithm for Moving Object Detection這個方法,我用opencv將其實現,代碼下面會貼出,但是其的到的結果很差,不知道代碼哪裏出了問題,請高手給予指點,謝謝!


左圖爲原圖,有圖爲用上面論文中的方法得到前景圖像,【自己的代碼可能寫錯了,請大神們給予指點謝謝】

代碼如下:

#include <stdio.h>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
int main(int argc,char** argv)
{


CvCapture* pCapture=NULL;


cvNamedWindow("source",1);
cvNamedWindow("move_detection",1);

cvMoveWindow("source",30,0);
cvMoveWindow("move_detection",690,0);

char *szFileName = "E:\\技術總結\\視頻中的火花和煙霧的檢測\\煙的測試視頻\\Basketball_yard.avi";

if(!(pCapture=cvCaptureFromFile(szFileName)))
{
fprintf(stderr,"Can not open video file %s\n",szFileName);
return -2;
}

IplImage* pFrame = NULL;
IplImage* pFrImg = NULL;
IplImage* pBkImg = NULL;

CvMat* pFrameMat = NULL;
CvMat* pFrMat = NULL;
CvMat* pBkMat = NULL;
CvMat* pMatChannels[4] = {NULL,NULL,NULL,NULL};
CvMat* pFrameMatPre1 = NULL;
CvMat* pFrameMatPre2 = NULL;
CvMat* pFrameMatCur = NULL;
CvMat* framediff1 = NULL;
CvMat* framediff2 = NULL;
CvMat* threshold = NULL;

int nFrmNum=0;
int frame_height;
int frame_width;
int frame_channel;
int k;

while(pFrame=cvQueryFrame(pCapture))
{
nFrmNum++;
frame_height = pFrame->height;
frame_width = pFrame->width;
frame_channel = pFrame->nChannels;

if(nFrmNum==1)
{
pBkImg = cvCreateImage(cvSize(frame_width, frame_height),  IPL_DEPTH_8U,1);
pFrImg = cvCreateImage(cvSize(frame_width, frame_height),  IPL_DEPTH_8U,1);

pBkMat = cvCreateMat(frame_height, frame_width, CV_32FC1);
pFrMat = cvCreateMat(frame_height, frame_width, CV_32FC1);
pFrameMat = cvCreateMat(frame_height, frame_width, CV_32FC3);
pFrameMatPre1 = cvCreateMat(frame_height, frame_width, CV_32FC1);
pFrameMatPre2 = cvCreateMat(frame_height, frame_width, CV_32FC1);
pFrameMatCur = cvCreateMat(frame_height, frame_width, CV_32FC1);
framediff1 = cvCreateMat(frame_height, frame_width, CV_32FC1);
framediff2 = cvCreateMat(frame_height, frame_width, CV_32FC1);
threshold = cvCreateMat(frame_height, frame_width, CV_32FC1);

for(k=0;k<frame_channel;k++)
{
pMatChannels[k] = cvCreateMat(frame_height, frame_width, CV_32FC1);
}

//轉化成單通道圖像再處理
cvConvertScale(pFrame,pFrameMat,1,0);
cvSplit(pFrameMat, pMatChannels[0], pMatChannels[1], pMatChannels[2], pMatChannels[3]);
cvAddWeighted(pMatChannels[0],0.114,pMatChannels[1],0.587,0,pFrameMatPre1);
cvAddWeighted(pMatChannels[2],0.299,pFrameMatPre1,1,0,pFrameMatPre1); //轉換爲灰度圖像
cvConvert(pFrameMatPre1, pBkMat);
cvConvert(pFrameMatPre1, pFrameMatPre2);
cvZero(pFrameMatCur);
cvZero(pFrameMatPre2);
cvSet(threshold,cvScalar(5),NULL); //閾值設爲5
}
else
{
double t = (double)cvGetTickCount(); //計算每幀時間

const double alpha = 0.02;
const int threshold_wavelet = 5;
const int threshold_color = 7;
int i,j;

cvConvertScale(pFrame,pFrameMat,1,0);
cvSplit(pFrameMat, pMatChannels[0], pMatChannels[1], pMatChannels[2], pMatChannels[3]);
cvAddWeighted(pMatChannels[0],0.114,pMatChannels[1],0.587,0,pFrameMatCur);
cvAddWeighted(pMatChannels[2],0.299,pFrameMatCur,1,0,pFrameMatCur); //轉換爲灰度圖像

//當前幀跟背景圖相減
cvAbsDiff(pFrameMatCur, pFrameMatPre1, framediff1);
cvAbsDiff(pFrameMatCur, pFrameMatPre2, framediff2); //幀差法
//cvAbsDiff(pFrameMatCur, pBkMat, pFrMat);
//二值化前景圖  
for(i=0;i<frame_height;i++)
for(j=0;j<frame_width;j++)
{
if((cvmGet(framediff1,i,j) > cvmGet(threshold,i,j)) && (cvmGet(framediff2,i,j) > cvmGet(threshold,i,j)))
cvmSet(pFrMat,i,j,255.0);
else
cvmSet(pFrMat,i,j,0.0);

if(cvmGet(pFrMat,i,j))
{
double differ = abs(cvmGet(pFrameMatCur,i,j) - cvmGet(pBkMat,i,j)); //背景差分法
if(differ > cvmGet(threshold,i,j))
cvmSet(pFrMat,i,j,255); //前景像素用255表示
else
cvmSet(pFrMat,i,j,0);
}
}

//進行形態學濾波 ,連通域分析
// cvErode(pFrMat, pFrMat, 0, 1);
// cvDilate(pFrMat, pFrMat, 0, 1);
// cvMorphologyEx( pFrMat, pFrMat, 0, 0, CV_MOP_OPEN, 1 );
// cvMorphologyEx( pFrMat, pFrMat, 0, 0, CV_MOP_CLOSE, 2 );
//
// cvConvert(pFrMat, pFrImg);
// find_connected_components(pFrImg, 1, 4,NULL,NULL,NULL);
// cvConvert(pFrImg,pFrMat);

//當前幀圖像更新
cvConvert(pFrameMatPre1,pFrameMatPre2);
cvConvert(pFrameMatCur,pFrameMatPre1);

//背景更新
for(i=0;i<frame_height;i++)
for(j=0;j<frame_width;j++)
{
if(cvGetReal2D(pFrMat,i,j) == 0)
{
double temp = alpha*cvmGet(pBkMat,i,j)+(1-alpha)*cvmGet(pFrameMatCur,i,j);
cvmSet(pBkMat,i,j,temp);
double differ = alpha*cvmGet(threshold,i,j)+(1-alpha)*5*abs(cvmGet(pFrameMatCur,i,j) - cvmGet(pBkMat,i,j));
cvmSet(threshold,i,j,differ);
}
}

//轉化爲圖像格式,用以顯示
cvConvert(pBkMat, pBkImg);
cvConvert(pFrMat, pFrImg);

//把圖像正過來         
//pBkImg->origin = pFrame->origin;         
pFrImg->origin = pFrame->origin; 

// 計算運算時間
t = (double)cvGetTickCount() - t;
printf( "calculation time = %gms\n", t/((double)cvGetTickFrequency()*1000.) );

//顯示圖像
//cvWriteFrame(writerin,pFrame);
//cvWriteFrame(writerout,pResult);
cvShowImage("source", pFrame);
cvShowImage("move_detection", pFrImg);

cvSaveImage("src.bmp",pFrame);
cvSaveImage("fg.bmp",pFrImg);

//如果有按鍵事件,則跳出循環
//此等待也爲cvShowImage函數提供時間完成顯示 
//等待時間可以根據CPU速度調整 
if( cvWaitKey(10) >= 0 )   
break;
}
}
//銷燬窗口  
cvDestroyWindow("source"); 
cvDestroyWindow("move_detection"); 
//cvDestroyWindow("spatial_wavelet_detection");
cvDestroyWindow("color_detection");
cvDestroyWindow("result");
//釋放圖像和矩陣  
cvReleaseImage(&pFrImg);  
cvReleaseImage(&pBkImg); 
cvReleaseMat(&pFrMat);  
cvReleaseMat(&pBkMat); 
cvReleaseMat(&pFrameMat);
cvReleaseMat(&pFrameMatCur);
cvReleaseMat(&pFrameMatPre1);
cvReleaseMat(&pFrameMatPre2);
cvReleaseMat(&framediff1);
cvReleaseMat(&framediff2);
for(k=0;k<frame_channel;k++)
{
cvReleaseMat(&pMatChannels[k]);
}
//cvReleaseVideoWriter(&writerin);
//cvReleaseVideoWriter(&writerout);
cvReleaseCapture(&pCapture);
return 0;
}

請大家給予指點,謝謝!

對應的工程可以免費下載:http://download.csdn.net/detail/lwjaiyjk3/7452145

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章