www.pudn.com > PrimeBackgroundDetection.rar > PrimeBackgroundDetection.cpp
// BKDetection.cpp: implementation of the CBKDetection class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "APCount.h"
#include "BKDetection.h"
#include "math.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CBKDetection::CBKDetection()
{
m_bInitStatus = FALSE;
m_dwImageWidth = m_dwImageHeight = 0;
m_dwRowBytes = m_dwMidBytes = 0;
m_byThreshold = 40;
m_pMedFilter = NULL;
m_pExtremumBits = NULL;
m_pAdvBKBits = NULL;
m_pUnchgCount = NULL;
m_pUnchgSum = NULL;
m_pDiffHist = NULL;
}
CBKDetection::~CBKDetection()
{
DeleteMem();
}
void CBKDetection::DeleteMem()
{
if ( m_pMedFilter != NULL )
{
delete[] m_pMedFilter;
m_pMedFilter = NULL;
}
if ( m_pExtremumBits != NULL )
{
delete[] m_pExtremumBits;
m_pExtremumBits = NULL;
}
if ( m_pAdvBKBits != NULL )
{
delete[] m_pAdvBKBits;
m_pAdvBKBits = NULL;
}
if ( m_pUnchgCount != NULL )
{
delete[] m_pUnchgCount;
m_pUnchgCount = NULL;
}
if ( m_pUnchgSum != NULL )
{
delete[] m_pUnchgSum;
m_pUnchgSum = NULL;
}
if ( m_pDiffHist != NULL )
{
delete[] m_pDiffHist;
m_pDiffHist = NULL;
}
}
void CBKDetection::CreateGausTab_2( )
{
DWORD dwDibSize = m_dwImageWidth * m_dwImageHeight;
double dbCoff_1 = 0.0,
dbCoff_2 = 0.0;
ULONGLONG ulPowerSum = 0,
ulTempVal = 0;
for ( int i = 0; i < DOUBLE_GAUS_VAR; ++ i )
{
dbCoff_1 = dwDibSize / ( i + 2.0 );
dbCoff_2 = 2.0 / ( ( i + 2 ) * ( i + 2 ) );
m_dwGausTab[ i ][ 0 ] = (DWORD)( dbCoff_1 * 1.7320508075688772935274463415059 + 0.5 );
dbCoff_1 += dbCoff_1;
ulPowerSum = 0;
for ( int j = 1; j < MAX_GAUS_WDTH; ++ j )
{
m_dwGausTab[ i ][ j ] = (DWORD)( dbCoff_1 * exp( -j * j * dbCoff_2 ) + 0.5 );
ulTempVal = m_dwGausTab[ i ][ j ];
ulPowerSum += ulTempVal * ulTempVal * ulTempVal;
}
m_ulGausPowerSum[ i ] = ulPowerSum / 65536;
}
}
void CBKDetection::CreateGausTab_3( )
{
DWORD dwDibSize = m_dwImageWidth * m_dwImageHeight;
double dbCoff_1 = 0.0,
dbCoff_2 = 0.0;
ULONGLONG ulPowerSum = 0,
ulTempVal = 0;
for ( int i = 0; i < TRIPLE_GAUS_VAR; ++ i )
{
dbCoff_1 = dwDibSize / ( i + 2.0 );
dbCoff_2 = 4.5 / ( ( i + 2 ) * ( i + 2 ) );
m_dwGausTab[ i ][ 0 ] = (DWORD)( dbCoff_1 * 1.7320508075688772935274463415059 + 0.5 );
dbCoff_1 += dbCoff_1;
ulPowerSum = 0;
for ( int j = 1; j < MAX_GAUS_WDTH; ++ j )
{
m_dwGausTab[ i ][ j ] = (DWORD)( dbCoff_1 * exp( -j * j * dbCoff_2 ) + 0.5 );
ulTempVal = m_dwGausTab[ i ][ j ];
ulPowerSum += ulTempVal * ulTempVal * ulTempVal;
}
m_ulGausPowerSum[ i ] = ulPowerSum / 65536;
}
}
inline void CBKDetection::GetDoubleVar( BYTE &byDoubleVar )
{
/* LONGLONG lngThisVar = 0;
DWORD dwMinVar = 4294967295,
dwThisVar = 0;
BYTE byMinVar = 0;
for ( BYTE w = 1; w < MAX_GAUS_WDTH; ++ w )
{
lngThisVar += m_pDiffHist[ w ] * m_pDiffHist[ w ];
}
double dbHistMean = sqrt( (double)lngThisVar );
for ( BYTE byX = 0; byX < DOUBLE_GAUS_VAR; ++ byX )
{
lngThisVar = 0;
//两场相等的点不需要比较
for ( BYTE byY = 1; byY < MAX_GAUS_WDTH; ++ byY )
{
lngThisVar += m_pDiffHist[ byY ] * m_dwGausTab[ byX ][ byY ];
}
dwThisVar = (DWORD)fabs( (double)lngThisVar / ( dbHistMean * m_dwGausTab[ byX ][ 0 ] ) * 256.0 - 256.0 );
if ( dwThisVar < dwMinVar )
{
dwMinVar = dwThisVar;
byMinVar = byX;
}
}
*/
ULONGLONG ulHistVal = 0,
ulGausVal = 0,
ulMaxVal = 0,
ulGausStat = 0,
ulHistStat = 0,
ulHistGaus = 0,
ulThisVal = 0,
ulMinVal = 18446744073709551615;
BYTE byMinVar = 0;
for ( BYTE byX = 0; byX < DOUBLE_GAUS_VAR; ++ byX )
{
ulGausStat = ulHistStat = ulHistGaus = 0;
for ( BYTE byY = 1; byY < MAX_GAUS_WDTH; ++ byY )
{
ulHistVal = m_pDiffHist[ byY ];
ulGausVal = m_dwGausTab[ byX ][ byY ];
ulMaxVal = max( m_pDiffHist[ byY ], m_dwGausTab[ byX ][ byY ] );
ulGausStat += ulGausVal * ulGausVal * ulMaxVal;
ulHistStat += ulHistVal * ulHistVal * ulMaxVal;
ulHistGaus += ulHistVal * ulGausVal * ulMaxVal;
}
ulGausStat /= 65536;
ulHistStat /= 65536;
ulHistGaus /= 65536;
ulThisVal = ulGausStat - ulHistGaus * ulHistGaus / ulHistStat;
if ( ulThisVal < ulMinVal )
{
ulMinVal = ulThisVal;
byMinVar = byX;
}
}
byDoubleVar = byMinVar + 2;
memset( m_pDiffHist, 0, 256 * sizeof( DWORD ) );
}
inline void CBKDetection::GetTripleVar( BYTE &byTripleVar )
{
/* LONGLONG lngThisVar = 0;
DWORD dwMinVar = 4294967295,
dwThisVar = 0;
BYTE byMinVar = 0;
for ( BYTE w = 1; w < MAX_GAUS_WDTH; ++ w )
{
lngThisVar += m_pDiffHist[ w ] * m_pDiffHist[ w ];
}
double dbHistMean = sqrt( (double)lngThisVar );
for ( BYTE byX = 0; byX < TRIPLE_GAUS_VAR; ++ byX )
{
lngThisVar = 0;
//两场相等的点不需要比较
for ( BYTE byY = 1; byY < MAX_GAUS_WDTH; ++ byY )
{
lngThisVar += m_pDiffHist[ byY ] * m_dwGausTab[ byX ][ byY ];
}
dwThisVar = (DWORD)fabs( (double)lngThisVar / ( dbHistMean * m_dwGausTab[ byX ][ 0 ] ) * 256.0 - 256.0 );
if ( dwThisVar < dwMinVar )
{
dwMinVar = dwThisVar;
byMinVar = byX;
}
}
*/
DWORD dwMaxHist = m_pDiffHist[ 1 ] + m_pDiffHist[ 2 ] + m_pDiffHist[ 3 ];
BYTE byOffset = 2;
for ( BYTE i = 3; i < 250; ++ i )
{
if ( dwMaxHist < m_pDiffHist[ i - 1 ] + m_pDiffHist[ i ] + m_pDiffHist[ i + 1 ] )
{
dwMaxHist = m_pDiffHist[ i - 1 ] + m_pDiffHist[ i ] + m_pDiffHist[ i + 1 ];
byOffset = i;
}
}
ULONGLONG ulHistVal = 0,
ulGausVal = 0,
ulMaxVal = 0,
ulGausStat = 0,
ulHistStat = 0,
ulHistGaus = 0,
ulThisVal = 0,
ulMinVal = 18446744073709551615;
for ( BYTE byX = 0; byX < TRIPLE_GAUS_VAR; ++ byX )
{
ulGausStat = ulHistStat = ulHistGaus = 0;
ulThisVal = 0;
for ( BYTE byY = 1, i = byOffset; ( byY < MAX_GAUS_WDTH ) && ( i < 250 ); ++ byY, ++ i )
{
ulHistVal = m_pDiffHist[ i ];
ulGausVal = m_dwGausTab[ byX ][ byY ];
ulMaxVal = max( m_pDiffHist[ i ], m_dwGausTab[ byX ][ byY ] );
ulGausStat += ulGausVal * ulGausVal * ulMaxVal;
ulHistStat += ulHistVal * ulHistVal * ulMaxVal;
ulHistGaus += ulHistVal * ulGausVal * ulMaxVal;
ulThisVal += ulMaxVal;
}
if ( ulThisVal > 0 )
{
ulGausStat /= ulThisVal;
ulHistStat /= ulThisVal;
ulHistGaus /= ulThisVal;
}
while ( ulHistGaus > 4294967295 )
{
ulGausStat >>= 1;
ulHistStat >>= 1;
ulHistGaus >>= 1;
}
ulThisVal = ulGausStat - ulHistGaus * ulHistGaus / ulHistStat;
if ( ulThisVal < ulMinVal )
{
ulMinVal = ulThisVal;
byTripleVar = byX;
}
}
byTripleVar += 1 + byOffset;
memset( m_pDiffHist, 0, 256 * sizeof( DWORD ) );
}
DWORD CBKDetection::BKParamInit( DWORD dwImageWidth, DWORD dwImageHeight )
{
/*如果没有进行参数初始化,才可以对参数进行进行初始化*/
if ( m_bInitStatus == FALSE )
{
/*释放系统已经占用的资源*/
DeleteMem();
/*每场图像的大小*/
DWORD dwDibSize = dwImageWidth * dwImageHeight;
m_pMedFilter = new BYTE[ dwDibSize * MEM_NUMBER ];
if ( m_pMedFilter == NULL )
{
return FAILURE;
}
memset( m_pMedFilter, 0, dwDibSize * MEM_NUMBER );
/*相临场无显著变化的场计数*/
m_pUnchgCount = new BYTE[ dwDibSize * RAW_BYTES * 2 ];
if ( m_pUnchgCount == NULL )
{
return FAILURE;
}
memset( m_pUnchgCount, 0, dwDibSize * RAW_BYTES * 2 );
/*相临场无显著变化的场信号之和*/
m_pUnchgSum = new WORD[ dwDibSize * RAW_BYTES ];
if ( m_pUnchgSum == NULL )
{
return FAILURE;
}
memset( m_pUnchgSum, 0, dwDibSize * RAW_BYTES * sizeof( WORD ) );
/*保存图像的峰谷点的值*/
m_pExtremumBits = new BYTE[ dwDibSize * RAW_BYTES ];
if ( m_pExtremumBits == NULL )
{
return FAILURE;
}
memset( m_pExtremumBits, 0, dwDibSize * RAW_BYTES );
/*保存预背景值*/
m_pAdvBKBits = new BYTE[ dwDibSize * RAW_BYTES ];
if ( m_pAdvBKBits == NULL )
{
return FAILURE;
}
memset( m_pAdvBKBits, 0, dwDibSize * RAW_BYTES );
/*相临的两场图像之绝对差的投影直方图*/
m_pDiffHist = new DWORD[ 256 ];
if ( m_pDiffHist == NULL )
{
return FAILURE;
}
memset( m_pDiffHist, 0, 256 * sizeof( DWORD ) );
/*保存图像的宽、高、每行的字节总数和求中值运算的内存每行的字节总数等参数*/
m_dwImageWidth = dwImageWidth;
m_dwImageHeight = dwImageHeight;
m_dwRowBytes = m_dwImageWidth * RAW_BYTES;
m_dwMidBytes = m_dwImageWidth * MEM_NUMBER;
/*高斯分布系数初始化,用于拟和直方图的分布参数*/
CreateGausTab_3();
m_byThreshold = 40;
/*置参数初始化标志成功*/
m_bInitStatus = TRUE;
}
return SUCCESS;
}
void CBKDetection::ObjBKUpdate( LPBYTE lpBKBits, LPBYTE lpMaskBits )
{
m_dwUpdateCount_1 = m_dwUpdateCount_2 = m_dwUpdateCount_3 = m_dwUpdateCount_4 = 0;
LPBYTE pBK = lpBKBits,
pMask = lpMaskBits;
LPBYTE pAdvBK = m_pAdvBKBits,
pMed = m_pMedFilter;
LPBYTE pCount_1 = m_pUnchgCount,
pCount_2 = m_pUnchgCount + m_dwRowBytes * m_dwImageHeight;
WORD *pSum = m_pUnchgSum;
LPBitsOper pBitsOper = (LPBitsOper)( m_pMedFilter + MEM_NUMBER - 1 );
for ( DWORD h = 0; h < m_dwImageHeight; ++ h )
{
for ( DWORD w = 0, x = 0; w < m_dwRowBytes; w += RAW_BYTES, x += MEM_NUMBER )
{
if ( pMask[ w ] == FORE_GROUND )
{//***
if ( pCount_2[ w ] > MIN_CONTINUOUS_COUNT )
{//**
if ( pCount_2[ w ] > pMed[ x + 1 ] )
{//*
pMed[ x ] = pAdvBK[ w ];
pMed[ x + 1 ] = pCount_2[ w ];
pMed[ x + 3 ] = 0;
pBitsOper[ x ].byBits0_3 = 0;
++m_dwUpdateCount_1;
}//*
else
{//*
if ( pBitsOper[ x ].byBits0_3 == 8 )
{
if ( pCount_2[ w ] < pMed[ x + 3 ] )
{
pMed[ x ] = pMed[ x + 2 ];
pMed[ x + 1 ] = pMed[ x + 3 ];
pMed[ x + 2 ] = pAdvBK[ w ];
pMed[ x + 3 ] = pCount_2[ w ];
pBitsOper[ x ].byBits0_3 = pBitsOper[ x ].byBits4_6;
pBitsOper[ x ].byBits4_6 = 0;
}
else
{
pMed[ x ] = pAdvBK[ w ];
pMed[ x + 1 ] = pCount_2[ w ];
pMed[ x + 3 ] = 0;
pBitsOper[ x ].byBits0_3 = 0;
}
++m_dwUpdateCount_2;
}
else
{
if ( pMed[ x + 3 ] > 0 )
{
if ( pCount_2[ w ] >= pMed[ x + 3 ] )
{
pMed[ x + 2 ] = pAdvBK[ w ];
pMed[ x + 3 ] = pCount_2[ w ];
}
++pBitsOper[ x ].byBits4_6;
}
else
{
pMed[ x + 2 ] = pAdvBK[ w ];
pMed[ x + 3 ] = pCount_2[ w ];
pBitsOper[ x ].byBits4_6 = 0;
}
++pBitsOper[ x ].byBits0_3;
++m_dwUpdateCount_3;
}
}//*
}//**
pBitsOper[ x ].byFlgBits7 = FOREGROUND_FLG;
pCount_2[ w ] = 0;
}//***
else
{//***
if ( pCount_1[ w ] > MAX_CONTINUOUS_COUNT )
{
pMed[ x ] = (BYTE)( pSum[ w ] / pCount_1[ w ] );
pMed[ x + 1 ] = pCount_1[ w ];
pMed[ x + 3 ] = 0;
pBitsOper[ x ].byBits0_3 = 0;
pSum[ w ] = 0;
pCount_1[ w ] = 0;
++m_dwUpdateCount_4;
}
}//***
pBK[ w ] = pMed[ x ];
}
pAdvBK += m_dwRowBytes;
pBK += m_dwRowBytes;
pMask += m_dwRowBytes;
pCount_1 += m_dwRowBytes;
pCount_2 += m_dwRowBytes;
pSum += m_dwRowBytes;
pMed += m_dwMidBytes;
pBitsOper += m_dwMidBytes;
}
}
void CBKDetection::BKUpdate( LPBYTE lpThisBits, LPBYTE lpPreBits,
LPBYTE lpBKBits, LPBYTE lpMaskBits )
{
m_dwUpdateCount_1 = m_dwUpdateCount_2 = m_dwUpdateCount_3 = m_dwUpdateCount_4 = 0;
int dwRowBytes = m_dwRowBytes;
LPBYTE pThis = lpThisBits,
pPre = lpPreBits,
pExtr = m_pExtremumBits,
pCount_1 = m_pUnchgCount,
pCount_2 = m_pUnchgCount + m_dwRowBytes * m_dwImageHeight,
pBK = lpBKBits + m_dwRowBytes,
pAdvBK = m_pAdvBKBits,
pMed = m_pMedFilter;
WORD *pSum = m_pUnchgSum;
LPBitsOper pBitsOper = (LPBitsOper)( m_pMedFilter + 5 );
BYTE byDiff = 0;
for ( DWORD h = 0; h < m_dwImageHeight; ++ h )
{
for ( DWORD w = 0, x = 0; w < m_dwRowBytes; w += RAW_BYTES, x += MEM_NUMBER )
{
if ( pThis[ w ] > pPre[ w ] )
{
if ( pExtr[ w ] > pPre[ w ] )
{
pExtr[ w ] = pPre[ w ];
if ( ( pBitsOper[ x ].byFlgBits7 == BACKGROUND_FLG ) && ( pCount_1[ w ] > 0 ) )
{
pAdvBK[ w ] = (BYTE)( pSum[ w ] / pCount_1[ w ] );
pCount_2[ w ] = pCount_1[ w ];
}
else
{
pSum[ w ] = pThis[ w ];
pCount_1[ w ] = 1;
pBitsOper[ x ].byFlgBits7 = BACKGROUND_FLG;
}
}
else if ( pBitsOper[ x ].byFlgBits7 == BACKGROUND_FLG )
{
pSum[ w ] += pThis[ w ];
++pCount_1[ w ];
}
byDiff = pThis[ w ] - pExtr[w ];
if ( pThis[ w ] > pPre[ w ] + 8 )
{
pPre[ w ] = 255;
}
else
{
pPre[ w ] = 0;
}
}
else if ( pThis[ w ] < pPre[ w ] )
{
if ( pExtr[ w ] < pPre[ w ] )
{
pExtr[ w ] = pPre[ w ];
if ( ( pBitsOper[ x ].byFlgBits7 == BACKGROUND_FLG ) && ( pCount_1[ w ] > 0 ) )
{
pAdvBK[ w ] = (BYTE)( pSum[ w ] / pCount_1[ w ] );
pCount_2[ w ] = pCount_1[ w ];
}
else
{
pSum[ w ] = pThis[ w ];
pCount_1[ w ] = 1;
pBitsOper[ x ].byFlgBits7 = BACKGROUND_FLG;
}
}
else if ( pBitsOper[ x ].byFlgBits7 == BACKGROUND_FLG )
{
pSum[ w ] += pThis[ w ];
++pCount_1[ w ];
}
byDiff = pExtr[ w ] - pThis[ w ];
if ( pThis[ w ] + 8 < pPre[ w ] )
{
pPre[ w ] = 127;
}
else
{
pPre[ w ] = 0;
}
}
else
{
pSum[ w ] += pThis[ w ];
++pCount_1[ w ];
byDiff = pPre[ w ] = 0;
}
++m_pDiffHist[ byDiff ];
}
pThis += m_dwRowBytes;
pPre += m_dwRowBytes;
pExtr += m_dwRowBytes;
pAdvBK += m_dwRowBytes;
pCount_1 += m_dwRowBytes;
pCount_2 += m_dwRowBytes;
pSum += m_dwRowBytes;
pBitsOper += m_dwMidBytes;
}
pPre = lpPreBits + m_dwRowBytes;
pSum = m_pUnchgSum + m_dwRowBytes;
pCount_1 = m_pUnchgCount + m_dwRowBytes;
pCount_2 = m_pUnchgCount + m_dwRowBytes * ( m_dwImageHeight + 1 );
pAdvBK = m_pAdvBKBits + m_dwRowBytes;
pMed = m_pMedFilter + m_dwRowBytes;
pBitsOper = ( LPBitsOper )( m_pMedFilter + m_dwRowBytes + 5 );
for ( h = 1; h < m_dwImageHeight - 1; ++ h )
{
for ( int w = 3, x = MEM_NUMBER; w < dwRowBytes - 3; w += RAW_BYTES, x += MEM_NUMBER )
{
if ( ( pPre[ w ] != 0 )
&& ( pPre[ w ] == pPre[ w - 3 ] )
&& ( pPre[ w ] == pPre[ w + 3 ] )
&& ( pPre[ w ] == pPre[ w - dwRowBytes - 3 ] )
&& ( pPre[ w ] == pPre[ w - dwRowBytes ] )
&& ( pPre[ w ] == pPre[ w - dwRowBytes + 3 ] )
&& ( pPre[ w ] == pPre[ w + dwRowBytes - 3 ] )
&& ( pPre[ w ] == pPre[ w + dwRowBytes ] )
&& ( pPre[ w ] == pPre[ w + dwRowBytes + 3 ] ) )
{
if ( pCount_2[ w ] > MIN_CONTINUOUS_COUNT )
{//***
if ( pCount_2[ w ] > pMed[ x + 1 ] )
{//**
pMed[ x ] = pAdvBK[ w ];
pMed[ x + 1 ] = pCount_2[ w ];
pMed[ x + 3 ] = 0;
pBitsOper[ x ].byBits0_3 = 0;
++m_dwUpdateCount_2;
}//**
else
{//**
if ( pBitsOper[ x ].byBits0_3 == 8 )
{//*
if ( pCount_2[ w ] < pMed[ x + 3 ] )
{
pMed[ x ] = pMed[ x + 2 ];
pMed[ x + 1 ] = pMed[ x + 3 ];
pMed[ x + 2 ] = pAdvBK[ w ];
pMed[ x + 3 ] = pCount_2[ w ];
pBitsOper[ x ].byBits0_3 = pBitsOper[ x ].byBits4_6;
pBitsOper[ x ].byBits4_6 = 0;
}
else
{
pMed[ x ] = pAdvBK[ w ];
pMed[ x + 1 ] = pCount_2[ w ];
pMed[ x + 3 ] = 0;
pBitsOper[ x ].byBits0_3 = 0;
}
++m_dwUpdateCount_3;
}//*
else
{//*
if ( pMed[ x + 3 ] > 0 )
{
if ( pCount_2[ w ] >= pMed[ x + 3 ] )
{
pMed[ x + 2 ] = pAdvBK[ w ];
pMed[ x + 3 ] = pCount_2[ w ];
}
if ( pBitsOper[ x ].byBits4_6 == 7 )
{
AfxMessageBox( "" );
}
++pBitsOper[ x ].byBits4_6;
}
else
{
pMed[ x + 2 ] = pAdvBK[ w ];
pMed[ x + 3 ] = pCount_2[ w ];
pBitsOper[ x ].byBits4_6 = 0;
}
++pBitsOper[ x ].byBits0_3;
++m_dwUpdateCount_4;
}//*
}//**
}//***
pBitsOper[ x ].byFlgBits7 = FOREGROUND_FLG;
pCount_2[ w ] = 0;
}
else
{
if ( pCount_1[ w ] > MAX_CONTINUOUS_COUNT )
{
pMed[ x ] = (BYTE)( pSum[ w ] / pCount_1[ w ] );
pMed[ x + 1 ] = pCount_1[ w ];
pMed[ x + 3 ] = 0;
pBitsOper[ x ].byBits0_3 = 0;
pSum[ w ] = 0;
pCount_1[ w ] = 0;
++m_dwUpdateCount_1;
}
}
pBK[ w ] = pMed[ x ];
}
pPre += m_dwRowBytes;
pCount_1 += m_dwRowBytes;
pCount_2 += m_dwRowBytes;
pSum += m_dwRowBytes;
pAdvBK += m_dwRowBytes;
pBK += m_dwRowBytes;
pMed += m_dwMidBytes;
pBitsOper += m_dwMidBytes;
}
}