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