⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 single-gaussian model for the algorithm to do the moving target detection.cpp

📁 本码源是针对于单高斯模型算法做的运动目标检测
💻 CPP
字号:
/************************************************** * 背景建模,运动物体检测 *       **************************************************/#ifdef _CH_
#pragma package <opencv>
#endif

#ifndef _EiC
#include <stdio.h>#include <cv.h>#include <cxcore.h>#include <highgui.h>
#include <ctype.h>
#endif
#define FALSE 0
#define TRUE  1
#define EPS	1e-6
#define	SQUARE(x)	((x) * (x))
#define ZERO(x)		(fabs((x)) < EPS ? TRUE : FALSE)
#define LearnFrame 20    
#define NUM  20
#define PARAMETER 2.0
IplConvKernel* element = 0;

const int element_shape = CV_SHAPE_RECT;
//形态学滤波函数操作
void Opening(IplImage* src, IplImage* image, IplImage* dest, int pos);   
void Closing(IplImage* src, IplImage* image, IplImage* dest, int pos); 
void Erosion(IplImage* src, IplImage* dest, int pos);
void Dilation(IplImage* src, IplImage* dest, int pos);  

CvMemStorage* storage = 0; // temporary storage

int i;
CvPoint pt;
CvPoint pre_pt;
int N;

int main(  ){  //声明当前帧IplImage指针  IplImage* pFrame = NULL;   IplImage* pFrImg = NULL;  IplImage* pBkImg = NULL;
  IplImage* pCurImg = NULL;
  IplImage* pFirstImg = NULL;
  IplImage* pTempImg = NULL;  CvMat* MeanValue = NULL;
  CvMat* SigmaValue = NULL;
  CvMat* NumBack = NULL;
 
  IplImage** buf = NULL;
  
  CvCapture* Capture = NULL;    int nFrmNum = 0;
  int i,j,w,x;
  double temp[NUM];
  int countframe=0;
  double mean = 0.0;             //均值

  #define MeanValueMat(ROW,COL) ((float *)(MeanValue->data.fl + MeanValue->step/sizeof(float) *(ROW)))[(COL)]
  #define SigmaValueMat(ROW,COL) ((float *)(SigmaValue->data.fl + SigmaValue->step/sizeof(float) *(ROW)))[(COL)]

  #define NumBackMAT(ROW,COL) ((uchar *)(NumBack->data.ptr + NumBack->step *(ROW)))[(COL)]

  #define BufMAT(NUMBER,ROW,COL) ((uchar*)(buf[(NUMBER)]->imageData + buf[(NUMBER)]->widthStep*(ROW)))[(COL)]
 
  #define BkImg(ROW,COL) ((uchar*)(pBkImg->imageData + pBkImg->widthStep*(ROW)))[(COL)]
  #define FrImg(ROW,COL) ((uchar*)(pFrImg->imageData + pFrImg->widthStep*(ROW)))[(COL)]
  #define TempImg(ROW,COL) ((uchar*)(pTempImg->imageData + pTempImg->widthStep*(ROW)))[(COL)]
  #define CurImg(ROW,COL) ((uchar*)(pCurImg->imageData + pCurImg->widthStep*(ROW)))[(COL)]
  #define FirstImg(ROW,COL) ((uchar*)(pFirstImg->imageData + pFirstImg->widthStep*(ROW)))[(COL)]
  
  //创建窗口  cvNamedWindow("videos", 1);  cvNamedWindow("back",1);  cvNamedWindow("fore",1);
  cvNamedWindow("temp",1);
    Capture =cvCaptureFromCAM(0);
//  Capture = cvCaptureFromFile("I:\\经典运动检测\\video8_vlong.avi");  pFrame = cvQueryFrame( Capture );
  
  //使窗口有序排列
  cvMoveWindow("videos", 30, 20);
  cvMoveWindow("back", 50+2*pFrame->width, 20);
  cvMoveWindow("fore", 30, 110+2*pFrame->height);
  cvMoveWindow("temp", 50+2*pFrame->width, 110+2*pFrame->height);

  //申请内存,并初始化
  //背景、前景、临时图像
  pBkImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,1);
  pFrImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,1);
  pTempImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,1);
  pCurImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,1);
  pFirstImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,1);
  //均值矩阵、方差矩阵
  MeanValue = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
  SigmaValue = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
  NumBack = cvCreateMat(pFrame->height, pFrame->width, CV_8UC1);
  cvZero(MeanValue);cvZero(SigmaValue);cvZero(NumBack);

  //初始化时使用的NUM帧数据
  buf = (IplImage**)malloc(NUM*sizeof(buf[0]));
  memset( buf, 0, NUM * sizeof(buf[0]) );
  for( i = 0; i < NUM; i++ ) 
  {
      buf[i] = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,1);
      cvZero( buf[i] );
  }

  storage = cvCreateMemStorage(0);
	        //逐帧读取视频  while(pFrame = cvQueryFrame( Capture ))  {            if(countframe<80)
	  {
		  countframe++;
		  continue;
	  }            if(nFrmNum<LearnFrame)//背景模型初始化	  {	      
	      //转化成单通道图像再处理	      cvCvtColor(pFrame, pTempImg, CV_BGR2GRAY);
	      //中值滤波 
          cvSmooth( pTempImg, pCurImg, CV_MEDIAN , 3, 0, 0 );//CV_GAUSSIAN or CV_MEDIAN
	
          cvFlip( pCurImg, pCurImg, 0 );
		  cvCopy( pCurImg, buf[nFrmNum], 0 );
		  nFrmNum++;
		  printf("frame= %d \n",nFrmNum);
	      continue;	  }
	  else if (nFrmNum==LearnFrame)   //建立 单Gaussian 背景模型
	  {
		  nFrmNum++;
		  cvCvtColor(pFrame, pTempImg, CV_BGR2GRAY);
		  cvFlip( pTempImg, pTempImg, 0 );
	      //中值滤波 
		  int width = pFrame->width;
          int height = pFrame->height;
          cvSmooth( pTempImg, pCurImg, CV_MEDIAN , 3, 0, 0 );//CV_GAUSSIAN or CV_MEDIAN
          for (w = 1; w < NUM; w++)
              cvCopy( buf[w], buf[w-1], 0 );
          cvCopy( pCurImg, buf[NUM-1], 0 );

		  for ( i = 0; i < height; i++)
		  {
		     for ( j = 0; j < width; j++)
			 {   
				 double temp_deviation[NUM];
				 int tmp;
				 temp[0] = BufMAT(0,i,j);
				 //临时存储
				 for ( w = 1; w < NUM; w++)
				 {
				    temp[w] = BufMAT(w,i,j);
					temp_deviation[w-1] = abs(temp[w]-temp[w-1]);      //临时离差
				 }
                 //排序取其数据的中值
				 for (w = 0; w < NUM; w++)
				 {
				    for ( x = 0; x < NUM - w - 1; x++)
					{
					    if (temp[x] > temp[x + 1])
						 {
						    tmp = temp[x];
						    temp[x] = temp[x + 1];
						    temp[x + 1] = tmp;
						}
					}
				 }
				 //对离差进行排序
				 for (w = 0; w < NUM-1; w++)
				 {
				    for ( x = 0; x < NUM - w - 2; x++)
					{
						if (temp_deviation[x] > temp_deviation[x + 1])
						 {
						    tmp = temp_deviation[x];
						    temp_deviation[x] = temp_deviation[x + 1];
						    temp_deviation[x + 1] = tmp;
						}
					}
				 }
			     //得到中值数,以及中值离差,利用中值滤波,剔除非背景点
			     tmp = temp[NUM / 2];
			     int countback=0;
			     for (w = 0; w < NUM; w++)
				 {
				    if (abs(BufMAT(w,i,j) - tmp) < 3 * temp_deviation[(NUM-1)/2])
					{
					    temp[countback] = BufMAT(w,i,j);
					    countback++;
					}
				 }
				 //重新计算背景参数,均值、方差
				 
				 int mean=temp[0];
				 for ( w = 1; w < countback-1; w++)
					mean += 1.0*( temp[w] - mean) / (w+1);
				 double variance=0.0;            //标准方差
				 for (w = 0; w < countback-1; w++)
				 {
				      tmp = (temp[w] - mean);
                      variance += (tmp * tmp - variance) / (w + 1);
				 }
				 variance=sqrt(1.0 * variance * (countback-1)/ (countback-2) );
				 
				 
		         if (variance<PARAMETER)
					 variance=PARAMETER;
				 
				 //背景参数均值方差
			     SigmaValueMat(i,j) = variance;                          //标准方差	
			     MeanValueMat(i,j) = mean;                               //均值
			     BkImg(i,j) = mean;                                      //背景值
				 NumBackMAT(i,j) = countback-1;                          //是背景的数目
				 //
             }//for
		  }//for
		  printf("initialization ofbackground model is completed!\n");
	  }//if      else        //背景减并进行背景更新
	  {       
		  countframe++;
		  printf(" The current frame is %d ; \n",countframe);
		  //提取前景目标
		  cvCvtColor(pFrame, pTempImg, CV_BGR2GRAY);
		  cvFlip( pTempImg, pTempImg, 0 );
	      //中值滤波 
          cvSmooth( pTempImg, pCurImg, CV_MEDIAN , 3, 0, 0 );//CV_GAUSSIAN or CV_MEDIAN  	      	   

		  cvZero(pFrImg);
		  for (int i = 0; i < pFrame->height; i++)
		  {
			for (int j = 0; j < pFrame->width; j++)
			{
				int tt=CurImg(i,j);
				int cc=MeanValueMat(i,j);
				int mm=SigmaValueMat(i,j);

				if ( abs(CurImg(i,j) - MeanValueMat(i,j)) < 3*SigmaValueMat(i,j) )
				{
					TempImg(i,j)=0;    //背景					
				}
				else
				{
					TempImg(i,j)=255;   //前景
					FrImg(i,j)=CurImg(i,j);
				}
			}
		  }	  
		  //进行形态学滤波,去掉噪音  
	      Opening(pBkImg, pBkImg, pBkImg, 1);   
	      Closing(pBkImg, pBkImg, pBkImg, 1); 
		  Opening(pFrImg, pFrImg, pFrImg, 1);   
	      Closing(pFrImg, pFrImg, pFrImg, 1); 
		  Opening(pTempImg, pTempImg, pTempImg, 1);   
	      Closing(pTempImg, pTempImg, pTempImg, 1); 
		  cvShowImage("videos", pCurImg);  //视频
	  
	      cvShowImage("back", pBkImg);    //背景图像
	      cvShowImage("fore", pFrImg);    //仅有目标的图像
          cvShowImage("temp", pTempImg);  //二值化目标提取
		  cvCopy( buf[0], pFirstImg , 0 );
		  for (w = 1; w < NUM; w++)
             cvCopy( buf[w], buf[w-1], 0 );
	      cvCopy( pCurImg, buf[NUM-1], 0 );
		  //根据参数更新背景
	      
		  for ( i = 0; i < pFrame->height; i++)
		  {
		     for ( j = 0; j < pFrame->width; j++)
			 { 	   
				 int countback=0;
				 int tmp,tmp1 ;
				 double mean=0.0;
				 double variance=0.0;            //标准方差
				 
				 //仅对无运动的像素进行更新
				 if ( abs(BufMAT( NUM-1, i,j) - MeanValueMat(i,j)) < 3*SigmaValueMat(i,j) )
				 {
					 //当第一帧对均值方差有贡献时,重新计算均值方差
					 if( abs(FirstImg(i,j) - MeanValueMat(i,j)) < 3*SigmaValueMat(i,j) )
					 {
                         mean = 1.0*( MeanValueMat(i,j)*NumBackMAT(i,j)-FirstImg(i,j)+BufMAT(NUM-1,i,j) ) / (NumBackMAT(i,j));
					     tmp = (FirstImg(i,j) - mean);
					     tmp1= (BufMAT(NUM-1,i,j)- mean);
                         variance = sqrt( 1.0*( (NumBackMAT(i,j)-1)*variance-tmp * tmp+ tmp1*tmp1) / (NumBackMAT(i,j)-1) );
					 }
				     else 
					 {
                         mean = 1.0*( MeanValueMat(i,j)*NumBackMAT(i,j)-FirstImg(i,j) ) / (NumBackMAT(i,j)-1);
					     tmp1= (BufMAT(NUM-1,i,j)- mean);
                         variance = sqrt( 1.0*( (NumBackMAT(i,j)-1)*variance+ tmp1*tmp1) / (NumBackMAT(i,j)) );
						 NumBackMAT(i,j)+=1;                          //是背景的数目
					 }
				 
/*
				 for ( w = 0; w < NUM; w++)
				 {	    
					 if ( ( abs(BufMAT(w,i,j) - MeanValueMat(i,j)) < 3*SigmaValueMat(i,j) ) )
					 {
					     temp[countback] = BufMAT(w,i,j);     //背景像素
					     countback++;
					 }
				 }
                 //利用中值作为背景
				 for (w = 0; w < countback; w++)
				 {
					    for (int x = 0; x < countback - w - 1; x++)
						{
						    if (temp[x] > temp[x+1])
							{
							    tmp = temp[x];
							    temp[x] = temp[x + 1];
							    temp[x+1] = tmp;
							}
						}
				 }			 
				 
		*/		  
				     if (variance<PARAMETER)
				         variance=PARAMETER;
					
				     //更新背景参数
			         SigmaValueMat(i,j) = variance;                             //标准方差	
			         MeanValueMat(i,j) = mean;                                  //均值
				     BkImg(i,j)=mean;//temp[(countback-1)/2];                   //背景值
				     
				 }
		
			 }//for
		  }//for
	  }//else  
	  //如果有按键事件,则跳出循环	  //此等待也为cvShowImage函数提供时间完成显示	  //等待时间可以根据CPU速度调整	  if( cvWaitKey(2) >= 0 )	    break;  }//while
    for( i = 0; i < NUM; i++ ) 
  {
     cvReleaseImage( &buf[i] );
  }	  
  cvReleaseCapture( &Capture );      
  //销毁窗口  cvDestroyWindow("videos");  cvDestroyWindow("back");  cvDestroyWindow("fore");  cvDestroyWindow("temp");
  //释放图像和矩阵
  cvReleaseImage(&pFrame);
    cvReleaseImage(&pFrImg);  cvReleaseImage(&pBkImg);  cvReleaseImage(&pTempImg);
  
  cvReleaseMat(&MeanValue);
  cvReleaseMat(&SigmaValue);
  return 0;}
void Opening(IplImage* src, IplImage* image, IplImage* dest, int pos)   
{
    element = cvCreateStructuringElementEx( pos*2+1, pos*2+1, pos, pos, element_shape, 0 );
    cvErode(src,image,element,1);
    cvDilate(image,dest,element,1);
    cvReleaseStructuringElement(&element);
}   

// implements closing 
void Closing(IplImage* src, IplImage* image, IplImage* dest, int pos)   
{
    element = cvCreateStructuringElementEx( pos*2+1, pos*2+1, pos, pos, element_shape, 0 );
    cvDilate(src,image,element,1);
    cvErode(image,dest,element,1);
    cvReleaseStructuringElement(&element);
}

// implements erosion 
void Erosion(IplImage* src, IplImage* dest, int pos)   
{
    element = cvCreateStructuringElementEx( pos*2+1, pos*2+1, pos, pos, element_shape, 0 );
    cvErode(src,dest,element,1);
    cvReleaseStructuringElement(&element);
}

// implements dilation
void Dilation(IplImage* src, IplImage* dest, int pos)   
{
    element = cvCreateStructuringElementEx( pos*2+1, pos*2+1, pos, pos, element_shape, 0 );
    cvDilate(src,dest,element,1);
    cvReleaseStructuringElement(&element);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -