📄 backgroundsubtraction.c
字号:
void ABS_InitBackGround(BYTE *lpBack)
{
BYTE *p = lpBack;
INT** pmd = g_lpaABSModel;
USHORT *ptw = g_iaABSTotalWeight;
INT i;
for(i=0; i<g_iABSPixelNum; i++)
{
Pixel_InitModel(*(p), pmd, ptw);
p ++;
pmd += K_MODELS;
ptw ++;
}
}
/** Estimate the constancy of the scene, how long has a pixel been the same color.
* @param previmg pointer to the buffer of previous frame
* @param curimg pointer to the buffer of current frame
* @param constimg the period that each pixel is not changed
* @return void
* @author Gengyu Ma
*/
// modified to use difference image
void ABS_ComputeConstancy(signed char* diffimg, BYTE* constimg)
{
BYTE* consadd = constimg;
int diff;
INT i;
for (i=0; i<g_iABSPixelNum; i++)
{
diff = EMA_ABS(*(diffimg++));
if (diff<24)
{
if (*consadd<200) (*consadd)++;
}
else
*consadd = 0;
consadd ++;
}
}
/* old code
void ABS_ComputeConstancy(BYTE* previmg, BYTE* curimg, BYTE* constimg)
{
BYTE* prevadd = previmg;
BYTE* curadd = curimg;
BYTE* consadd = constimg;
BYTE diff;
INT i;
for (i=0; i<g_iABSPixelNum; i++)
{
diff = (*prevadd>*curadd)? *prevadd-*curadd : *curadd-*prevadd;
if (diff<24)
{
if (*consadd<200) (*consadd)++;
}
else
*consadd = 0;
prevadd ++;
curadd ++;
consadd ++;
}
}
*/
/** Verify Theft pixels by using the constancy image
* @param labelimg the address of label data, store each pixel's type
* @param constimg the period that each pixel has been still
* @param labelimg some theft pixels are changed to FG
* @return void
* @author Gengyu Ma
*/
void ABS_VerifyTheftByConstancy(BYTE* labelimg, BYTE* constimg)
{
BYTE* labadd = labelimg;
BYTE* consadd = constimg;
INT i;
for (i=0; i<g_iABSPixelNum; i++)
{
if ((*labadd)==THEFTPIXEL && (*consadd)<64)
(*labadd) = BACKGROUND;
labadd ++;
consadd ++;
}
}
/** only update model, without comparison
* @param g pixel color
* @param lpmodel MoG model
* @param totalweight sum up weight of each model
* @param updatefactor how fast the model is updated
* @param lpmodel MoG model
* @author Gengyu Ma
*/
void Pixel_ModelUpdate(BYTE g, INT** lpmodel, USHORT* totalweight, INT updatefactor)
{
BYTE i, match;
INT dist2, v, pixel;
INT* pmMatch;
pixel = g;
pixel = pixel << 4;
// see if the current pixel matches any of the models
for (match=0; match<K_MODELS; match++)
{
// calculate the vector, v = (X - u)
v = pixel - lpmodel[match][0];
// calculate the squared distance, d = |v|^2
dist2 = abs(v);
// see if X is close enough to this model
if ((dist2<<3) < SigmaM8 * lpmodel[match][1]) break;
}
if (match<K_MODELS)
{
// we matched an existing model
pmMatch = lpmodel[match];
if (pmMatch[3]<1024) pmMatch[3] += updatefactor;
// now we need to update the models
// update the weights (we normalize later)
pmMatch[2] += updatefactor;
(*totalweight) += updatefactor;
if ( (*totalweight) > 2048 )
{
(*totalweight) = 0;
for (i=0; i<K_MODELS; i++)
{
lpmodel[i][2] = lpmodel[i][2] >> 1;
(*totalweight) += lpmodel[i][2];
}
}
// update the parameters for the matched model
// first we update the mean
pmMatch[0] = ((pmMatch[0]<<10) - pmMatch[0] + pixel + 512) >> 10;
// and then we update the variance
if ( !( pmMatch[1]<=128 && dist2<pmMatch[1] )
&& !( pmMatch[1]>=2048 && dist2>pmMatch[1]) )
{
pmMatch[1] = ((pmMatch[1]<<10) - (pmMatch[1]<<3) + (dist2<<3) + 512) >> 10;
}
// re-sort the models, only update necessary one
Pixel_UpdateSortByKey(lpmodel, match);
}
else
{
// we didn't match anything
pmMatch = lpmodel[K_MODELS-1];
// replace least probable model with the current data
(*totalweight) = (*totalweight) - pmMatch[2] + InitialWeight;
pmMatch[2] = InitialWeight;
pmMatch[0] = pixel;
pmMatch[1] = InitialVariance << 4;
}
}
/** Compare new pixel with background model and update the model
* @param g pixel color
* @param lpmodel MoG model
* @param totalweight sum up weight of each model
* @param updatefactor how fast the model is updated
* @param senstivity control the sensitivity by adjusting the matching range
* @param lpdiff save the difference to the Pixel_Diffs
* @param lpmodel MoG model
* @return pixel type
* @author Gengyu Ma
*/
INT Pixel_Compare_Update(BYTE g, INT** lpmodel, USHORT* totalweight, INT updatefactor, BYTE* lpdiff, BYTE senstivity)
{
BYTE i, match;
BYTE cat;
USHORT bgThr, weightSum;
INT pixel, dist2, realdist;
INT* pmMatch;
pixel = g; pixel = pixel << 4;
// find which models account for the bg by summing the
// model's weights until we exceed <bgThr>
weightSum = 0;
bgThr = ((*totalweight) * bgT) >> 4;
// the leading a fews are both theft and background
i=0;
for (i=0; i<3; i++)
{
weightSum += lpmodel[i][2];
if (lpmodel[i][3]<1024) lpmodel[i][3] += updatefactor;
if (weightSum > bgThr) break;
}
// the middle severals are background, but not theft
// the other models are foreground
for (i++; i<K_MODELS; i++)
lpmodel[i][3] = 0;
(*lpdiff) = 255; // min difference to background model
// see if the current pixel matches any of the models
for(match=0; match<K_MODELS; match++)
{
// calculate the vector, v = (X - u)
// calculate the squared distance, d = |v|^2
dist2 = EMA_DIFF(pixel, lpmodel[match][0]);
// find min dist
realdist = (dist2>>3);
realdist = EMA_MIN(255, realdist);
if ((*lpdiff)>realdist && lpmodel[match][3]>THEFT_DURARION)
*lpdiff = (BYTE)realdist;
// see if X is close enough to this model
if ( (dist2<<3) < lpmodel[match][1]*senstivity*SigmaM8 )
break;
}
if (match<K_MODELS)
{
// we matched an existing model
pmMatch = lpmodel[match];
// determine if the matched model is part of the bg or fg
if (pmMatch[3]==0)
cat = FOREPIXEL; // foreground
else if (pmMatch[3]<THEFT_DURARION)
cat = THEFTPIXEL; // background
else
cat = BACKGROUND; // theft
// now that we've classified, we need to update the models
// update the weights (we normalize later)
pmMatch[2] += updatefactor;
(*totalweight) += updatefactor;
if ( (*totalweight) > 2048 )
{
(*totalweight) = 0;
for (i=0; i<K_MODELS; i++)
{
lpmodel[i][2] = lpmodel[i][2] >> 1;
(*totalweight) += lpmodel[i][2];
}
}
// update the parameters for the matched model
// first we update the mean
pmMatch[0] = ((pmMatch[0]<<7) - pmMatch[0] + pixel + 64) >> 7;
// and then we update the variance
if ( !( pmMatch[1]<=128 && dist2<pmMatch[1] )
&& !( pmMatch[1]>=2048 && dist2>pmMatch[1]) )
{
pmMatch[1] = ((pmMatch[1]<<7) - (pmMatch[1]) + (dist2) + 64) >> 7;
}
// re-sort the models, only update necessary one
Pixel_UpdateSortByKey(lpmodel, match);
}
else
{
// we didn't match anything
pmMatch = lpmodel[K_MODELS-1];
// replace least probable model with the current data
(*totalweight) = (*totalweight) - pmMatch[2] + InitialWeight;
pmMatch[0] = pixel;
pmMatch[1] = InitialVariance << 4;
pmMatch[2] = InitialWeight;
pmMatch[3] = 0;
// we assume the 'new' model is foreground
cat = FOREPIXEL;
}
return cat;
}
/** Compare new pixel with background model and update the model
* @param g pixel color
* @param lpmodel MoG model
* @param totalweight sum up weight of each model
* @param updatefactor how fast the model is updated
* @param senstivity control the sensitivity by adjusting the matching range
* @param lpdiff save the difference to the Pixel_Diffs
* @param lpmodel MoG model
* @return pixel type
* @author Gengyu Ma
*/
INT Pixel_Compare(BYTE g, INT** lpmodel, USHORT* totalweight, BYTE senstivity)
{
BYTE i, match;
BYTE cat;
USHORT bgThr, weightSum;
INT pixel, dist2;
INT* pmMatch;
pixel = g; pixel = pixel << 4;
// find which models account for the bg by summing the
// model's weights until we exceed <bgThr>
weightSum = 0;
bgThr = ((*totalweight) * bgT) >> 4;
// the leading a fews are both theft and background
i=0;
for (i=0; i<3; i++)
{
weightSum += lpmodel[i][2];
if (weightSum > bgThr) break;
}
// see if the current pixel matches any of the models
for(match=0; match<K_MODELS; match++)
{
// calculate the vector, v = (X - u)
// calculate the squared distance, d = |v|^2
dist2 = EMA_DIFF(pixel, lpmodel[match][0]);
// see if X is close enough to this model
if ( (dist2<<3) < lpmodel[match][1]*senstivity*SigmaM8 )
break;
}
if (match<K_MODELS)
{
// we matched an existing model
pmMatch = lpmodel[match];
// determine if the matched model is part of the bg or fg
if (pmMatch[3]==0)
cat = FOREPIXEL; // foreground
else if (pmMatch[3]<THEFT_DURARION)
cat = THEFTPIXEL; // background
else
cat = BACKGROUND; // theft
}
else
cat = FOREPIXEL;
return cat;
}
/** Sort the gaussians in a pixel by order
* @param lpmodel MoG model
* @param mi the gaussian whose weight is changed
* @param lpmodel MoG model
* @return void
* @author Gengyu Ma
*/
void Pixel_UpdateSortByKey(INT** lpmodel, BYTE mi)
{
CHAR i;
INT mikey, key;
INT *pm = lpmodel[mi];
mikey = (lpmodel[mi][2]<<4);// / (lpmodel[mi][1]>>4);
for (i=mi-1; i>=0; i--)
{
key = (lpmodel[i][2]<<4);// / (lpmodel[i][1]>>4);
if (key<mikey)
lpmodel[i+1] = lpmodel[i];
else break;
}
lpmodel[i+1] = pm;
}
/** Initialize pixel color model
* @param g pixel color
* @param lpmodel MoG model
* @param totalweight sum up weight of each model
* @param lpmodel MoG model
* @author Gengyu Ma
*/
void Pixel_InitModel(BYTE g, INT** lpmodel, USHORT* totalweight)
{
BYTE i;
// init model 0
lpmodel[0][0] = ((USHORT)g) << 4; // average
lpmodel[0][1] = InitialVariance << 4; // var
lpmodel[0][2] = 1024 - K_MODELS*32; // weight
lpmodel[0][3] = 1024; // duration
// init other models
for (i=1; i<K_MODELS; i++)
{
lpmodel[i][0] = 0x7FFFFF;
lpmodel[i][1] = InitialVariance << 4;
lpmodel[i][2] = 32;
lpmodel[i][3] = 0;
}
(*totalweight) = 1024;
}
#ifdef __cplusplus
} // extern "C" {
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -