📄 backgroundsubtraction.c
字号:
LONG avgval = 0;
memset(edgeimg, 1, g_iABSPixelNum);
for (y=1; y<g_iImageHeight-1; y++)
{
edgeadd = edgeimg + g_iImageWStep*y;
pmd = g_lpaABSModel + g_iImageWidth*K_MODELS*y;
for (x=1; x<g_iImageWidth-1; x++)
{
v1 = pmd[0][0];
avgval += v1;
// left
pmdadj = pmd-K_MODELS;
v2 = pmdadj[0][0];
grad = (v1>v2)? v1-v2 : v2-v1;
ming = grad;
v2 = pmdadj[1][0];
grad = (v1>v2)? v1-v2 : v2-v1;
ming = EMA_MIN(grad, ming);
maxg = ming;
// right
pmdadj = pmd + K_MODELS;
v2 = pmdadj[0][0];
grad = (v1>v2)? v1-v2 : v2-v1;
ming = grad;
v2 = pmdadj[1][0];
grad = (v1>v2)? v1-v2 : v2-v1;
ming = EMA_MIN(grad, ming);
maxg = EMA_MAX(maxg, ming);
// top
pmdadj = pmd - K_MODELS*g_iImageWidth;
v2 = pmdadj[0][0];
grad = (v1>v2)? v1-v2 : v2-v1;
ming = grad;
v2 = pmdadj[1][0];
grad = (v1>v2)? v1-v2 : v2-v1;
ming = EMA_MIN(grad, ming);
maxg = EMA_MAX(maxg, ming);
//bottom
pmdadj = pmd - K_MODELS*g_iImageWidth;
v2 = pmdadj[0][0];
grad = (v1>v2)? v1-v2 : v2-v1;
ming = grad;
v2 = pmdadj[1][0];
grad = (v1>v2)? v1-v2 : v2-v1;
ming = EMA_MIN(grad, ming);
maxg = EMA_MAX(maxg, ming);
*edgeadd = ((maxg+48)>>7)+1;
edgeadd ++;
pmd += K_MODELS;
}
}
avgval /= (g_iImageWidth-2)*(g_iImageHeight-2);
if (avgval<THR_DARK)
ABS_SetParameters(SCENE_BRIGHT_OR_DARK, 1);
else
ABS_SetParameters(SCENE_BRIGHT_OR_DARK, 0);
}
/** Compare new image with background model
* @param lpimg a new frame in the sequence
* @param lpdiff the difference between current input and saved model.
* @param lplabel an image stores the type of each pixel. FG,BG,THEFT,SHADOW,etc
* @return void
* @author Gengyu Ma
*/
void ABS_ExtractForeground(BYTE *lpimg, BYTE* lplabel, BYTE* lpdiff, INT updatefactor)
{
//ptrs
BYTE *p = lpimg;
INT **pmd = g_lpaABSModel; // poINTer to the model of one pixel
USHORT *ptw = g_iaABSTotalWeight; // poINTer to the total weight of one pixel
BYTE *pdiff = lpdiff; // poINTer to the difference of one pixel
BYTE *fg = lplabel;
BYTE lastp;
SHORT x,y;
static BYTE ti;
ti = (ti+1)%2;
for (y=0; y<g_iImageHeight; y++)
{
if (y%2==ti) // 0 2 4 6 8
{
lastp = 1;
for (x=0; x<=g_iImageWidth-2; x+=2)
{
*fg = Pixel_Compare_Update(*p, pmd, ptw, updatefactor, pdiff, 1);
if (*fg!=BACKGROUND)
{
if (lastp==0)
*(fg-1) = Pixel_Compare_Update(*(p-1), pmd-K_MODELS, (ptw-1), updatefactor, pdiff-1, 1);
*(fg+1) = Pixel_Compare_Update(*(p+1), pmd+K_MODELS, (ptw+1), updatefactor, pdiff+1, 1);
lastp = 1;
}
else
{
*(fg+1) = BACKGROUND;
*(pdiff+1) = *pdiff;
lastp = 0;
}
p += 2;
pdiff += 2;
fg += 2;
pmd += K_MODELS<<1;
ptw += 2;
}
}
else // 1 3 5 7 9
{
lastp = 0;
p ++;
pmd += K_MODELS;
ptw ++;
*pdiff = 0; pdiff ++;
*fg = 0; fg ++;
lastp = 0;
for (x=1; x<=g_iImageWidth-3; x+=2)
{
*fg = Pixel_Compare_Update(*p, pmd, ptw, updatefactor, pdiff, 1);
if (*fg!=BACKGROUND)
{
if (lastp==0)
*(fg-1) = Pixel_Compare_Update(*(p-1), pmd-K_MODELS, (ptw-1), updatefactor, pdiff-1, 1);
*(fg+1) = Pixel_Compare_Update(*(p+1), pmd+K_MODELS, (ptw+1), updatefactor, pdiff+1, 1);
lastp = 1;
}
else
{
*(fg+1) = BACKGROUND;
*(pdiff+1) = *pdiff;
lastp = 0;
}
p += 2;
pdiff += 2;
fg += 2;
pmd += K_MODELS<<1;
ptw += 2;
}
*fg = Pixel_Compare_Update(*p, pmd, ptw, updatefactor, pdiff, 1);
if (*fg!=BACKGROUND)
{
if (lastp==0)
*(fg-1) = Pixel_Compare_Update(*(p-1), pmd-K_MODELS, (ptw-1), updatefactor, pdiff-1, 1);
}
p ++;
pdiff ++;
fg ++;
pmd += K_MODELS;
ptw ++;
}
}
}
/** Compute the sharpness of the difference image. Result will be used in shadow removal
* @param lpdiff the difference between current input and saved model.
* @param lpsharpness the sharpness of the difference image
* @return void
* @author Gengyu Ma
*/
void ABS_Sharpness(BYTE* lpdiff, BYTE* lpsharpness)
{
USHORT w = g_iImageWidth;
USHORT h = g_iImageHeight;
BYTE* diffaddr = lpdiff + w + w + w;
BYTE* sharpaddr = lpsharpness + w + w + w;
USHORT y,x;
USHORT v1, v2, v3, v4, v5; // 5 positions to calculate sharpness
USHORT lg1, lg2, lg3, lg; // 3 candidate large gradients and the final value
USHORT sg1, sg2, sg3, sg; // large gradient and small gradient
INT hsharp, vsharp, sharp;
memset(lpsharpness, 0, g_iImageWStep*g_iImageHeight);
for (y=3; y<=h-4; y++)
{
for (x=3; x<=w-4; x++)
{
// verify if the difference is big
if (diffaddr[x]<24) continue;
if (diffaddr[x]>SHADOW_MAXDIFF)
{
sharpaddr[x] = 255;
continue;
}
vsharp = hsharp = 0;
// vertical
v1 = (UINT)diffaddr[x-w-w-w-1] + (UINT)diffaddr[x-w-w-w] + (UINT)diffaddr[x-w-w-w+1];
v2 = (UINT)diffaddr[x-w-1] + (UINT)diffaddr[x-w] + (UINT)diffaddr[x-w+1];
v3 = (UINT)diffaddr[x-1] + (UINT)diffaddr[x] + (UINT)diffaddr[x+1];
v4 = (UINT)diffaddr[x+w-1] + (UINT)diffaddr[x+w] + (UINT)diffaddr[x+w+1];
v5 = (UINT)diffaddr[x+w+w+w-1] + (UINT)diffaddr[x+w+w+w] + (UINT)diffaddr[x+w+w+w+1];
lg1 = abs(v3-v1); lg2 = abs(v5-v3); lg3 = abs(v5-v1);
lg = EMA_MAX(lg1, lg2); lg = EMA_MAX(lg, lg3);
sg1 = abs(v3-v2); sg2 = abs(v4-v3); sg3 = abs(v4-v2);
sg = EMA_MAX(sg1, sg2); sg = EMA_MIN(sg, sg3);
if (sg>SHADOW_MAXGRAD<<3)
{ vsharp = 255; continue; }
else if (lg>=sg && sg>SHADOW_MAXGRAD)
vsharp = (sg<<4) / ((lg+16)>>3);
// horizontal
v1 = (UINT)diffaddr[x-w-3] + (UINT)diffaddr[x-3] + (UINT)diffaddr[x+w-3];
v2 = (UINT)diffaddr[x-w-1] + (UINT)diffaddr[x-1] + (UINT)diffaddr[x+w-1];
v3 = (UINT)diffaddr[x-w] + (UINT)diffaddr[x] + (UINT)diffaddr[x+w];
v4 = (UINT)diffaddr[x-w+1] + (UINT)diffaddr[x+1] + (UINT)diffaddr[x+w+1];
v5 = (UINT)diffaddr[x-w+3] + (UINT)diffaddr[x+3] + (UINT)diffaddr[x+w+3];
lg1 = abs(v3-v1); lg2 = abs(v5-v3); lg3 = abs(v5-v1);
lg = EMA_MAX(lg1, lg2); lg = EMA_MAX(lg, lg3);
sg1 = abs(v3-v2); sg2 = abs(v4-v3); sg3 = abs(v4-v2);
sg = EMA_MAX(sg1, sg2); sg = EMA_MIN(sg, sg3);
if (sg>SHADOW_MAXGRAD<<3)
{ hsharp = 255; continue; }
if (lg>=sg && sg>SHADOW_MAXGRAD)
hsharp = (sg<<4) / ((lg+16)>>3);
sharp = vsharp + hsharp;
sharp = EMA_MIN(sharp, 255);
sharpaddr[x] = (BYTE)sharp;
}
diffaddr += w;
sharpaddr += w;
}
}
/** When potential camera shift occured, call this function to verify each FG pixel in this verification, the threshold used to classify pixel types depends on the background gradient
* @param lpimg a new frame in the sequence
* @param lplabel only FG pixels are processed
* @param lpgrad using background gradeint to set the threshold for model comparison
* @param lpdiff the difference between current input and saved model.
* @param lplabel updated label image
* @return void
* @author Gengyu Ma
*/
void ABS_ExtractWithMask(BYTE *lpimg, BYTE* lplabel, BYTE* lpgrad)
{
//ptrs
BYTE *p = lpimg;
INT **pmd = g_lpaABSModel; // pointer to the model of one pixel
USHORT *ptw = g_iaABSTotalWeight; // pointer to the total weight of one pixel
BYTE *grad = lpgrad; // gradient in the background model
BYTE *fg = lplabel;
INT i;
for (i=0; i<g_iABSPixelNum; i++)
{
if (*grad>1 && (*fg==FOREPIXEL||*fg==THEFTPIXEL))
*fg = Pixel_Compare(*p, pmd, ptw, *grad);
p ++;
fg ++;
grad ++;
pmd += K_MODELS;
ptw ++;
}
}
/** Get model information for visualization
* @param sort the nth gaussian model to be loaded
* @param lpbgimg the center of the nth model
* @param lpweightimg the weight of the nth model
* @return void
* @author Gengyu Ma
*/
void ABS_GetBackGround(INT sort, BYTE *lpbgimg, BYTE* lpweightimg)
{
INT pi;
BYTE* iaddr = lpbgimg;
BYTE* waddr = lpweightimg;
for (pi=0; pi<g_iABSPixelNum; pi++)
{
if (lpweightimg)
{
waddr[0] = (BYTE)((float)g_lpaABSModel[pi*K_MODELS+sort][2]*255 / g_iaABSTotalWeight[pi]);
waddr ++;
}
if (lpbgimg)
{
iaddr[0] = (BYTE)(g_lpaABSModel[pi*K_MODELS+sort][0] >> 4);
iaddr ++;
}
}
}
/** Set some of the FG pixels to SHADOW, according to difference image and sharpness image
* @param lplabel the address of label data, store each pixel's type
* @param lpdiff the difference between current input and saved model.
* @param lpsharp the address of label data, store each pixel's type
* @param lplabel Some pixels are SHADOW after the procedure
* @return void
* @author Gengyu Ma
*/
void ABS_RemoveShadow(BYTE* lplabel, BYTE* lpdiff, BYTE* lpsharp)
{
USHORT x, y, xs, xe, y2;
// horizontal scan
BYTE* labeladdr = lplabel + g_iImageWidth*3;
BYTE* diffaddr = lpdiff + g_iImageWidth*3;
BYTE* sharpaddr = lpsharp + g_iImageWidth*3;
BYTE* sharpaddr2, *labeladdr2, *diffaddr2;
for (y=3; y<g_iImageHeight-3; y++)
{
for (x=3; x<g_iImageWidth-3; x++)
{
if (labeladdr[x]==BACKGROUND)
{
// forward scan
xe = x+1;
while (xe<g_iImageWidth-1 && labeladdr[xe]==BACKGROUND) xe++;
if (xe-x<32 && x>3 && xe<g_iImageWidth-3) // too short background is not considered
goto gap_end_h;
while (xe<g_iImageWidth-1 && sharpaddr[xe]<SHADOW_MAXSHARP+4)
{
if (labeladdr[xe]==FOREPIXEL)
labeladdr[xe] = SHADOW;
xe ++;
}
// backward scan
xs = x-1;
while (xs>0 && sharpaddr[xs]<SHADOW_MAXSHARP+4 && labeladdr[xs]==FOREPIXEL)
{
labeladdr[xs] = SHADOW;
xs--;
}
gap_end_h:
x = xe;
}
}
labeladdr += g_iImageWidth;
diffaddr += g_iImageWidth;
sharpaddr += g_iImageWidth;
}
// vertical scan
for (x=3; x<g_iImageWidth-3; x++)
{
labeladdr = lplabel + g_iImageWidth*3 + x;
sharpaddr = lpsharp + g_iImageWidth*3 + x;
diffaddr = lpdiff + g_iImageWidth*3 + x;
for (y=3; y<g_iImageHeight-3; y++)
{
if (*labeladdr==BACKGROUND)
{
// forward scan
sharpaddr2 = sharpaddr + g_iImageWidth;
labeladdr2 = labeladdr + g_iImageWidth;
diffaddr2 = diffaddr + g_iImageWidth;
for (y2=y+1; y2<g_iImageHeight-1; y2++)
{
if (*labeladdr2==BACKGROUND)
{
labeladdr2 += g_iImageWidth;
sharpaddr2 += g_iImageWidth;
diffaddr2 += g_iImageWidth;
continue;
}
if (y>3 && y2-y<32)
goto gap_end_v;
if (*sharpaddr2<SHADOW_MAXSHARP)
*labeladdr2 = SHADOW;
else
break;
sharpaddr2 += g_iImageWidth;
labeladdr2 += g_iImageWidth;
diffaddr2 += g_iImageWidth;
}
gap_end_v:
y = y2;
labeladdr = labeladdr2;
sharpaddr = sharpaddr2;
diffaddr = diffaddr2;
}
else
{
labeladdr += g_iImageWidth;
sharpaddr += g_iImageWidth;
diffaddr += g_iImageWidth;
}
}
}
}
/** Update the background model from an image
* @param lpimg the address of image data buffer
* @param updatefactor control the speed of update, bigger value means faster speed
* @return void
* @author Gengyu Ma
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -