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];
}
}