www.pudn.com > backmode824.rar > GaussianModel.cpp


// GaussianModel.cpp: implementation of the CGaussianModel class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "backmodel.h" 
#include "GaussianModel.h" 
#include "math.h" 
#include "ImageProcess.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
 
////////////////////////////////////////////////////////////////// 
//为了消除阴影,设定在HSV格式下判断当前像素点是否是阴影的阈值定义// 
////////////////////////////////////////////////////////////////// 
#define Th            0.5//0.5 
#define Ts            0.1 
#define Tv1           0.1 
#define Tv2           0.7 
#define UNDEFINEDCOLOR -1 
////////////////////////////////////////////////////////////////////// 
double* Rgb2Hsv(double R, double G, double B); 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
//============================================================ 
/*int CGaussianModel::argmin() 
{ 
	int b=4;//b 的初始值大于2 
	int i=0; 
	double sum=0; 
	while(i<3) 
	{ 
		sum+=omiga[order[i]]; 
		if(sum>thresT) 
		{ 
			b=i; 
			break; 
		} 
		i++; 
	} 
	return b; 
} 
//============================================================ 
bool CGaussianModel::checkBackground(int intensity) 
{ 
 //判断当前像素是不是背景 yes return ture; no return false; 
	//按照高斯分布的排序进行匹配操作 
	bool find=false; 
	bool isBack=true; 
	double u,lsSigma; 
	//-----先进行排序根据 omiga/sigma  由高到低排序---- 
 
	for(int i=0;i<3;i++) 
	{ 
          u=uMean[order[i]]; 
		  lsSigma=sigma[order[i]]; 
		  if(fabs(u-intensity)<2.5*lsSigma) 
		  { 
			  //与此高斯分布匹配 
			  find=true; 
			  //比较n和B 
			  int B=argmin(); 
			  if(i<=B) 
				  isBack=true; 
			  else 
				  isBack=false; 
 
			  //---update parameters------ 
 
			  uMean[order[i]]=uMean[order[i]]*(1-afa[order[i]])+afa[order[i]]*intensity; 
			  sigma[order[i]]=sqrt((1-afa[order[i]])*sigma[order[i]]*sigma[order[i]]+ 
				              afa[order[i]]*(sigma[order[i]]-intensity)*(sigma[order[i]]-intensity)); 
			  omiga[order[i]]=(1-afa[order[i]])*omiga[order[i]]+afa[order[i]]; 
 
			  // 找到后不再进行其他分布匹配 
			  break; 
 
		  } 
		  else 
		  { 
			  //---update----w---- 
			  omiga[order[i]]=(1-afa[order[i]])*omiga[order[i]]; 
		  } 
 
	} 
 
	//---都不匹配--- 
	if(!find) 
	{ 
		uMean[order[2]]=intensity; 
		sigma[order[2]]=127; 
		omiga[order[2]]=0.1; 
 
		//这种情况暂时认为是  背景 
	} 
 
	return isBack; 
}*/ 
 
//=============================================================== 
////////////////////////////////////////////////////////////////////// 
 
// zot: what should these values be? 
 
// the learning rate for weights (0.0 -> 1.0)//alpha学习率即更新率 
#define alphaweight          0.01 
// the learning rate for means (0.0 -> 1.0)//alphamean 
#define alphamean            0.8 
// the learning rate for variances (0.0 -> 1.0)//alphavar 
//#define alphavar             0.8 
 
// minimum portion of data accounted for by background (0.0 -> 1.0) 
//  (1 - bgT) should be greater than (1 / K_MODELS) 
//  otherwise all models could account for the background 
#define bgT               0.9//0.79//???? 
 
// initial weight should be pretty low//初始权重非常小 
#define InitialWeight      0.001//0.02 
 
// initial variance should be rather high//初始 
#define InitialDeviation   12.0 
#define InitialVariance    ((InitialDeviation)*(InitialDeviation)) 
 
// a vector within  standard deviations of a model 
//  is "explained" by that model 
#define SigmaFactor        2.5 
#define SFSquared          ((SigmaFactor)*(SigmaFactor)) 
 
UINT PixelModel::gid = 100L;//? 
 
 
 
////////////////////////////////////////////////////////////////////// 
 
PixelProcess::PixelProcess() 
{ 
   int i;//, j; 
   for(i=0; iweight = InitialWeight;//初始化权重0.001//初始化权重0.02 
      //ProcessFirst(m_lpBackImage); 
	  //for(j=0; j<3; j++) model[i]->mean[j] = -999.0;//初始化均值为-999.0??? 
      model[i]->dev = 20.0;//350.0; 
      model[i]->var = model[i]->dev * model[i]->dev;//初始化标准差?? 
   }    
 
   NormalizeWeights(); 
 
   // again, we start by assuming everything is part of the background 
   // 假设初始每个像素都属于背景 
   pmMatch = model[0]; 
   lastCategory = PC_Background; 
    
} 
 
////////////////////////////////////////////////////////////////////// 
 
PixelProcess::~PixelProcess() 
{ 
   int i; 
   for(i=0; ivar * pm->var * pm->var;//k=3 
   a = 1.0 / (c1 * sqrt(det)); 
 
   // calc the exponent 
   b = -0.5 * pm->mah2; 
 
   v = a * exp(b); 
 
   return v; 
} 
 
////////////////////////////////////////////////////////////////////// 
 
PixelCategory PixelProcess::Process(BYTE *fgr,int frame_num) 
{ 
   if (!fgr) return PC_Error; 
   else return Process(*(fgr+2), *(fgr+1), *(fgr),frame_num); 
} 
 
////////////////////////////////////////////////////////////////////// 
//作用于第一幅图像 
PixelProcess::ProcessFirst(BYTE *fgr) 
{ 
    MeanInitial(*(fgr+2), *(fgr+1), *(fgr)); 
} 
 
 
 
 
 
 
 
 
 
 
 
/////////////////////////////////////////////////////////////////////// 
PixelCategory PixelProcess::Process(BYTE fcr, BYTE fcg, BYTE fcb,int frame_num) 
{ 
   double fpixel[3]; 
   double v[3]; 
   double fHSV[3]; 
   double bHSV[3]; 
//当前的图像像素值 
   fpixel[0] = (double)fcr; 
   fpixel[1] = (double)fcg; 
   fpixel[2] = (double)fcb; 
   double alphavar=0.8; 
 
    int i, j; 
   int k_num=0,temp=0; 
   double d, rho; 
 
 
   
      // we want to check each model in order of ascending variance 
   SortModelsByVariance(); 
 
   // see if the current pixel matches any of the models 
   //判断像素中是否有匹配于模型的 
   for(i=0; ((imean[j]; 
	  } 
 
      // calculate the squared distance, d = |v|^2 
      model[i]->dist2 = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; 
 
      // zot: this is only equal to mahalanobis distance 
      //   when covariance matrix = vI 
      //   (v = scalar variance for all channels) 
      model[i]->mah2 = model[i]->dist2 / model[i]->var;//|z-u|^2/sigma^2 
       
      // see if X is close enough to this model//看看是否匹配:距离<2.5*sigma 
      if (model[i]->mah2 < SFSquared) {k_num=i;temp++;break;}//自己修改了一下,k_num为存储模式数的变量 
   } 
 
 
//如果在设定的模型数内满足匹配条件,则调整高斯参数和权重 
   if ((k_num 
      double weightSum = 0.0; 
      for(j=0; jweight; 
 
         if (weightSum > bgT) break;//权重之和大于bgT的作为背景模型 
      } 
 
      // determine if the matched model is part of the bg(背景) or fg(前景) 
      lastCategory = PC_Background; 
      for(i=j+1; iweight = d * model[i]->weight + alphaweight; 
         } 
         else{ 
            // this is not the matched model, so M = 0 
            model[i]->weight = d * model[i]->weight; 
         } 
      } 
 
      // update the parameters for the matched model 
      rho = Gauss(pmMatch); 
      //rho = alpha * 0.75; 
	  d = 1.0 - alphamean*rho; 
 
      // first we update the mean 
      for(i=0; i<3; i++) 
      { 
         pmMatch->mean[i] = (d * pmMatch->mean[i]) + (rho * fpixel[i]); 
      } 
 
      //according the time(the number of the frame)//new add 824 
	  if(frame_num!=0) alphavar=1/frame_num; 
	  if((frame_num>10)&&((alphavar>0.001)&&(frame_num!=0))) alphavar=1/frame_num; 
	  else alphavar=0.01; 
	  //two update rates of the mean and variance should be different  
	  d=1.0-alphavar*rho; 
      // and then we update the variance 
      pmMatch->var = (d * pmMatch->var) + (rho * pmMatch->dist2); 
      pmMatch->dev = sqrt(pmMatch->var); 
 
   } 
   else{ 
      // we didn't match anything 
      pmMatch = GetLeastProbableModel();     
 
      // replace least probable model with the current data 
      pmMatch->weight = InitialWeight; 
      for(j=0; j<3; j++) pmMatch->mean[j] = fpixel[j]; 
      pmMatch->dev = InitialDeviation; 
      pmMatch->var = InitialVariance; 
       
      // we assume the 'new' model is foreground 
      lastCategory = PC_Foreground; 
   }    
 
   // we adjusted the weights during the update, so we need to normalize 
   NormalizeWeights(); 
   
    
 
 
//判断当前像素是否是属于阴影部分.根据HSV格式的各个分量与背景图像的对应点进行比较, 
//   满足阈值条件的认为是阴影区域,并认为是背景 
   //效果不明显 
   if(lastCategory == PC_Foreground) 
   { 
	   //把当前的RGB图像转换成HSV格式 
       fHSV[0]=Rgb2Hsv(fpixel[0],fpixel[1],fpixel[2])[0]; 
       fHSV[1]=Rgb2Hsv(fpixel[0],fpixel[1],fpixel[2])[1]; 
       fHSV[2]=Rgb2Hsv(fpixel[0],fpixel[1],fpixel[2])[2]; 
 
       //把作为背景的RGB图像转换成HSV格式 
       bHSV[0]=Rgb2Hsv(model[0]->r,model[0]->g,model[0]->b)[0]; 
       bHSV[1]=Rgb2Hsv(model[0]->r,model[0]->g,model[0]->b)[1]; 
       bHSV[2]=Rgb2Hsv(model[0]->r,model[0]->g,model[0]->b)[2]; 
 
  
	    
	   if(fHSV[2]Tv1)) 
				 {lastCategory = PC_Background;}//阴影的颜色与背景相差不大,就是亮度变暗了 
	   } 
   } 
 
    //new add 822 
   //if(lastCategory == PC_Background) 
   //{ 
	   for(i=0; ir= fpixel[0]; 
		   model[i]->g= fpixel[1]; 
		   model[i]->b= fpixel[2]; 
	   } 
   //} 
 
 
     
   return lastCategory; 
} 
 
////////////////////////////////////////////////////////////////////// 
 
/* 
 All weights should sum to one 
 */ 
void PixelProcess::NormalizeWeights() 
{ 
   double total = 0.0; 
   int i; 
   for(i=0; iweight; 
   for(i=0; iweight /= total; 
} 
 
////////////////////////////////////////////////////////////////////// 
 
/* 
 Sort by descending key, where key = weight(i) / stddev(i) 
 */ 
void PixelProcess::SortModelsByKey() 
{    
   int i, j; 
   double t; 
   double key[K_MODELS]; 
   PixelModel *pm; 
 
   for(i=0; iweight / model[i]->dev; 
   } 
 
   // zot: selection sort is crap 
 
   for(i=0; ivar > model[j]->var) 
         { 
            pm = model[i]; model[i] = model[j]; model[j] = pm; 
         } 
      } 
   } 
} 
 
////////////////////////////////////////////////////////////////////// 
 
PixelCategory PixelProcess::GetLastCategory() 
{ 
   return lastCategory; 
} 
 
////////////////////////////////////////////////////////////////////// 
 
/* 
 Least probable model is that with the lowest weight 
 */ 
PixelModel* PixelProcess::GetLeastProbableModel() 
{ 
   int i, j = 0; 
   double m = model[0]->weight; 
   for(i=1; iweight <= m) 
      { 
         m = model[i]->weight; 
         j = i; 
      } 
   } 
   return model[j]; 
} 
 
////////////////////////////////////////////////////////////////////// 
//rgb转换为hsv 
double* Rgb2Hsv(double R, double G, double B) 
{ 
     // r,g,b values are from 0 to 1 
    // h = [0,360], s = [0,1], v = [0,1] 
    // if s == 0, then h = -1 (undefined) 
 
    double min, max, delta,tmp,H,S,V; 
	double HSV[3]; 
    tmp = min(R, G); 
    min = min( tmp, B ); 
    tmp = max( R, G); 
    max = max(tmp, B ); 
     
    V = max; // v 
 
    delta = max - min; 
 
    if( max != 0 ) 
      S = delta / max; // s 
    else 
    { 
       // r = g = b = 0 // s = 0, v is undefined 
      S = 0; 
      H = UNDEFINEDCOLOR; 
      
    } 
    if( R == max ) 
        H = ( G - B ) / delta; // between yellow & magenta 
   else if( G == max ) 
        H = 2 + ( B - R ) / delta; // between cyan & yellow 
   else 
        H = 4 + ( R - G ) / delta; // between magenta & cyan 
 
  //根据matlab的函数做了修改,不知道是否正确 
   //H/=6;  
   H *= 60; // degrees 
    if( H < 0 ) H += 360;//H++; 
	if(H == 360) 
		{ 
			H = 0; 
		} 
 
    HSV[0]=H; 
	HSV[1]=S; 
	HSV[2]=V; 
	return HSV; 
} 
 
////////////////////////////////////////////////////////////////////// 
//模型的初始化均值为第一幅图像的像素值 
//模型的rgb值初始化//new add 
void PixelProcess::MeanInitial(BYTE cr, BYTE cg, BYTE cb) 
{ 
	double bpixel[3]; 
   
	//以第一幅图像的像素值初始化高斯模型均值mean 
   bpixel[0] = (double)cr; 
   bpixel[1] = (double)cg; 
   bpixel[2] = (double)cb; 
 
   int i, j; 
   for(i=0; imean[j] = bpixel[j];//初始化均值为第一幅图像的像素值 
       //模型的rgb值初始化//new add 
	   model[i]->r=bpixel[0]; 
	   model[i]->b=bpixel[1]; 
	   model[i]->g=bpixel[2]; 
   } 
    
}