www.pudn.com > Histogram.rar > Histogram.c


  /***************************************************************************** 
 * File:	Histogram.c 
 * Desc:	functions of Histogram Tracking Algorithm 
 * Author:	Xuhui Zhou  @ Carnegie Mellon University 
 * Date:	12/09/2003 
 *****************************************************************************/ 
 
#include "Histogram.h" 
 
//histogram bins 
int  RBINS = 10; 
int  GBINS = 10; 
int  BBINS = 10; 
 
//global histogram 
CvHistogram  *gHistInit; //init click hist 
CvHistogram  *gHistModel; //model hist without outer ring 
CvHistogram	 *gHistRatio;	//ratio of foreground/(foreground+background) 
CvHistogram	 *gHistDivide;	//ratio of foreground/(foreground+background) 
CvHistogram	 *gHistDiff;	//Difference of foreground-background 
 
//projection image 
IplImage	*gImgBackProj; 
IplImage	*gImgFgMask; 
IplImage	*gImgObjMask; 
 
//global path 
char		gExePath[_MAX_PATH]; 
 
POINT		gGravityCenter; 
int			gBorder = 20; //border width for outer ring box 
int			gTrackMethod = 1; //SHIFT, 2:CONV 
 
int			gMaskPixCount; 
float		gMaskFgRatio; 
 
/////////////////////////////////////////////////////////////////////////////// 
void his_PrintHistogram(CvHistogram *hist, char* filename) 
{ 
	FILE	*file; 
	float	data; 
	int 	h, s, v; 
 
	file = fopen(filename, "w"); 
	for( h = 0; h < RBINS; h++ ){			 
		for( s = 0; s < GBINS; s++ ){			 
			fprintf(file, "%02d_%02d_(0~%02d): ", h, s, BBINS-1); 
			for(v = 0; v < BBINS; v++ ){						 
				data = cvQueryHistValue_3D(hist,h,s,v); 
				fprintf(file, "%3d ", (long)data );						 
			}			 
			fprintf(file, "\n"); 
		}		 
	} 
	fclose(file);	 
} 
 
/******************************************************************************/ 
CvHistogram* his_CalcHistogram(IplImage* inImg){ 
/******************************************************************************/ 
	CvHistogram *outHist; 
	CvSize imgSize = cvGetSize(inImg);	 
	IplImage* h_plane = cvCreateImage(imgSize, 8, 1 ); 
    IplImage* s_plane = cvCreateImage(imgSize, 8, 1 ); 
    IplImage* v_plane = cvCreateImage(imgSize, 8, 1 );         
    float h_ranges[] = { 0, 255}; /* hue varies from 0 (~0°red) to 180 (~360°red again) */ 
    float s_ranges[] = { 0, 255}; /* saturation varies from 0 (black-gray-white) to 255 (pure spectrum color) */ 
	float v_ranges[] = { 0, 255};  
    int		hist_size[] = {RBINS, GBINS, BBINS}; 
	float*	ranges[] = { h_ranges, s_ranges, v_ranges}; 
	IplImage* planes[] = { h_plane, s_plane, v_plane}; 
	float max_value = 0; 
     
    cvCvtPixToPlane(inImg, h_plane, s_plane, v_plane, 0 ); 
    outHist = cvCreateHist(3, hist_size, CV_HIST_ARRAY, ranges, 1 ); 
    cvCalcHist( planes, outHist, 0, 0 ); 
 
	//nornalize histogram 
	cvNormalizeHist(outHist, 255); 
	cvGetMinMaxHistValue( outHist, 0, &max_value, 0, 0 ); 
 
	//cvThreshHist(outHist, max_value*0.5); 
	//cvGetMinMaxHistValue( outHist, 0, &max_value, 0, 0 );	 
 
	cvReleaseImage(&h_plane); 
	cvReleaseImage(&s_plane);	 
	cvReleaseImage(&v_plane);	 
	return outHist; 
} 
 
 
/******************************************************************************/ 
CvHistogram* his_HistogramFromArray(float* modelhist){ 
/******************************************************************************/		 
	CvHistogram *outHist; 
	int  d[1] = {256}; 
	int  bin; 
	float *p;		 
	float range[] = {0,255}; 
	float *ranges[] = {range};	 
	float maxVal,factor; //minVal 
	//int		minIdx, maxIdx; 
 
	outHist = cvCreateHist(1,d,CV_HIST_ARRAY,ranges,1); 
	 
	maxVal = 0; 
	for (bin=0; bin<256; bin++){		 
		p = cvGetHistValue_1D(outHist, bin); 
		//*p = modelhist[bin]; 
		*p = bin+1.0f; 
		if (modelhist[bin]>maxVal){ 
			maxVal = modelhist[bin]; 
		} 
	} 
		 
	 
	if (maxVal!=0){ 
		factor = 255; 
		cvNormalizeHist(outHist, factor); 
 	}	 
 
	return outHist; 
} 
 
/******************************************************************************/ 
CvHistogram* his_HistogramRatio(CvHistogram* hist1_model, CvHistogram *hist2_denom) 
//ratio by probDensity 
{ 
	CvHistogram *outHist=NULL; 
	 
	cvCopyHist(hist1_model, &outHist); 
	cvClearHist(outHist); 
	cvCalcProbDensity(hist2_denom,hist1_model,outHist,255); 
		 
	return outHist; 
} 
 
/******************************************************************************/ 
CvHistogram* his_HistogramDivide(CvHistogram* hist1, CvHistogram *hist2) 
//divide and normalize 
{ 
	CvHistogram *histRst=NULL;	 
	int b1, b2, b3; 
	float   *p1, *p2, *p3; 
	float	rst; 
 
	cvCopyHist(hist1, &histRst); 
	cvClearHist(histRst); 
 
	for( b1 = 0; b1 < RBINS; b1++ ){			 
		for( b2 = 0; b2 < GBINS; b2++ ){ 
			for( b3 = 0; b3 < BBINS; b3++ ){			 
				p1 = cvGetHistValue_3D(hist1,b1,b2,b3); 
				p2 = cvGetHistValue_3D(hist2,b1,b2,b3); 
				p3 = cvGetHistValue_3D(histRst,b1,b2,b3); 
				 
				if ((*p2)==0) rst = 0; 
				else 
					rst = (*p1)/(*p2); 
				(*p3) = max(rst, 0);				 
			} 
		} 
	}					 
 
	his_HistogramNormalize(histRst); 
		 
	return histRst; 
} 
 
/******************************************************************************/ 
void his_HistogramDiff(CvHistogram* hist1, CvHistogram *hist2, CvHistogram *histRst) 
//inner minus outer; (foreground) - (foreground+background) 
{	 
	int b1, b2, b3; 
	float   *p1, *p2, *p3; 
	float	rst; 
 
	for( b1 = 0; b1 < RBINS; b1++ ){			 
		for( b2 = 0; b2 < GBINS; b2++ ){ 
			for( b3 = 0; b3 < BBINS; b3++ ){			 
				p1 = cvGetHistValue_3D(hist1,b1,b2,b3); 
				p2 = cvGetHistValue_3D(hist2,b1,b2,b3); 
				p3 = cvGetHistValue_3D(histRst,b1,b2,b3); 
				 
				rst = (*p1)*2 - (*p2); 
				(*p3) = max(rst, 0);				 
			} 
		} 
	}					 
} 
 
/******************************************************************************/ 
void his_HistogramNormalize(CvHistogram* inHist) 
//make the max as 255, multiply by 255/max 
{ 
	int b1, b2, b3; 
	float	maxVal, minVal; 
	//float	val; //histogram count value 
	float   *pix; 
 
	//get max value 
	cvGetMinMaxHistValue( inHist, &minVal, &maxVal, 0, 0 );			 
 
	if (maxVal==0) return; 
 
	//get min non-zero value 
	minVal = 255; 
	for( b1 = 0; b1 < RBINS; b1++ ){			 
		for( b2 = 0; b2 < GBINS; b2++ ){ 
			for( b3 = 0; b3 < BBINS; b3++ ){			 
				pix = cvGetHistValue_3D(inHist,b1,b2,b3); 
				if ((*pix)>0 && (*pix)0){ 
					(*pix) = ((*pix)-minVal)*255/(maxVal-minVal); 
				} 
			} 
		} 
	}					 
} 
 
/******************************************************************************/ 
void his_HistogramThresholdUp(CvHistogram* inHist, float thresholdVal) 
//make pix 255 if above threshold 
{ 
	int b1, b2, b3; 
	float	max_value = 0; 
	//float	val; //histogram count value 
	float   *pix; 
 
	//get max value 
	cvGetMinMaxHistValue( gHistModel, 0, &max_value, 0, 0 );			 
 
	//normalize 
	for( b1 = 0; b1 < RBINS; b1++ ){			 
		for( b2 = 0; b2 < GBINS; b2++ ){ 
			for( b3 = 0; b3 < BBINS; b3++ ){			 
				pix = cvGetHistValue_3D(inHist,b1,b2,b3); 
				if (*pix>thresholdVal){ 
					(*pix) = 255;			 
				} 
			} 
		} 
	}					 
} 
 
/******************************************************************************/ 
CvHistogram* his_HistogramAdd(CvHistogram* hist1, CvHistogram *hist2, float weight){ 
/******************************************************************************/ 
	CvHistogram *outHist=NULL;	 
	int	h,s,v; 
	float h1, h2,*p; 
 
	cvCopyHist(hist1, &outHist); 
 
	for( h = 0; h < RBINS; h++ ){			 
		for( s = 0; s < GBINS; s++ ){ 
			for( v = 0; v < BBINS; v++ ){			 
				h1 = cvQueryHistValue_3D(hist1,h,s,v); 
				h2 = cvQueryHistValue_3D(hist2,h,s,v); 
				p = cvGetHistValue_3D(outHist,h,s,v); 
				(*p) = h1*(1-weight) + h2*weight; 
			} 
		} 
	}			 
		 
	return outHist; 
} 
/******************************************************************************/ 
void his_BackProject(BYTE *imgin, BYTE *imgout, CvHistogram *hist){ 
/******************************************************************************/ 
	int		imgWidth, imgHeight;	 
	IplImage* imgSrc[CV_MAX_DIM]; 
	IplImage* imgRst = cvCreateImage( cvSize(320,243), IPL_DEPTH_8U, 1 ); 
	IplImage* tmp	=	cvCreateImage( cvSize(320,243), IPL_DEPTH_8U, 1 ); 
 
	imgSrc[0] = cvCreateImage( cvSize(320,243), IPL_DEPTH_8U, 1 ); 
	//copy input image 
	imgWidth = 320; 
	imgHeight = 243;	 
	memcpy(imgSrc[0]->imageData, imgin, imgWidth*imgHeight);	 
 
	//calculate backproject 
	cvCalcBackProject(imgSrc, imgRst, hist); 
 
//	//debug display		 
//	cvSaveImage("result/imgsrc.bmp", imgSrc[0]); 
//	cvSaveImage("result/imgRst.bmp", imgRst); 
//	img_Output_C1_float(imgRst->imageData, imgWidth, imgWidth, imgHeight, "result/imgRst.txt");	 
 
	//copy to output 
	memcpy(imgout,imgRst->imageData,imgWidth*imgHeight); 
	 
	//clear memory 
	cvReleaseImage( &imgSrc[0]); 
	cvReleaseImage( &imgRst); 
} 
 
/******************************************************************************/ 
IplImage* his_CalcBackProject(IplImage *inImgHSV, CvHistogram *inHist){ 
/******************************************************************************/		 
	//calculate back project		 
	CvSize imgSize = cvGetSize(inImgHSV);	 
	IplImage*	h_plane = cvCreateImage(imgSize, 8, 1 ); 
	IplImage*	s_plane = cvCreateImage(imgSize, 8, 1 ); 
	IplImage*	v_plane = cvCreateImage(imgSize, 8, 1 ); 
	IplImage*	planes[] = { h_plane, s_plane, v_plane };    	 
	IplImage*	bpRst = cvCreateImage(imgSize, 8, 1 );	 
		 
	//seperate HSV planes 
	cvCvtPixToPlane(inImgHSV, h_plane, s_plane, v_plane, 0 ); 
     
	//calculate backproject 
	cvCalcBackProject(planes, bpRst, inHist); 
 
	//cvThreshold(outImgBP, outImgBP, 50, 255, CV_THRESH_TOZERO ); 
	 
	//debug display	 
//	{ 
//		IplImage* tmp = cvCreateImage(imgSize, 8, 1 ); 
//		cvFlip(inImgHSV,NULL,0); 
//		cvSaveImage("result/inImgHSV.bmp",inImgHSV); 
//		cvFlip(outImgBP,tmp,0); 
//		cvSaveImage("result/outImgBP.bmp",tmp);		 
//	} 
	 
	//clear memory 
	cvReleaseImage( &h_plane); 
	cvReleaseImage( &s_plane); 
	cvReleaseImage( &v_plane); 
	return bpRst; 
} 
 
/******************************************************************************/ 
void his_CalcForeground2(IplImage *inImgHSV, CvHistogram *inHist, CvRect inRect, IplImage *outImgFg){ 
/******************************************************************************/		 
	int			border; 
	CvRect		rectSearch;	 //search window in tracking 
	IplImage	*imgsrc = cvCloneImage(inImgHSV);		 
	IplImage	*imgrst;		 
	double		dRstMax; 
	int			row, col; 
	double		pixval; 
	 
	//extent neighboring search window 
	border = gBorder; 
	rectSearch.x = inRect.x - border; 
	rectSearch.y = inRect.y - border; 
	rectSearch.width = inRect.width+2*border; 
	rectSearch.height = inRect.height+2*border; 
	his_CheckBoundRect(&rectSearch, inImgHSV->width, inImgHSV->height);		 
	 
	//get back project		 
	imgrst = his_CalcBackProject(imgsrc, inHist); 
 
	//scale to 0~255 
	cvMinMaxLoc(imgrst,NULL, &dRstMax, NULL,NULL,NULL);	 
	if (dRstMax!=0){		 
		cvConvertScale(imgrst, imgrst, 255/dRstMax,0); 
	} 
	 
	//copy imgrst to outImgFg 
	cvSetZero(outImgFg); 
	for (col=rectSearch.x; colx <0) rect->x=0; 
	if (rect->x >imgWidth) rect->x = imgWidth; 
	if (rect->y <0) rect->y=0; 
	if (rect->y >imgHeight) rect->y = imgHeight; 
 
	if (rect->width >=imgWidth - rect->x) 
		rect->width = imgWidth -1 - rect->x; 
	if (rect->height>=imgHeight - rect->y) 
		rect->height = imgHeight -1 - rect->y; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
IplImage* his_GetBackProjImage() 
{ 
	return gImgBackProj; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
void his_ReadHistBinsFromFile(){ 
	FILE *filein; 
	char *binfile = "histogram.txt"; 
	char prompt[10]; 
	//int i; 
	//char buffer[_MAX_PATH]; 
	 
	//_getcwd(buffer, _MAX_PATH); 
 
	filein = fopen(binfile, "r"); 
	if (filein==NULL){ 
		return; 
	} 
		 
	fscanf(filein, "%s", &prompt); 
	fscanf(filein, "%d", &RBINS); 
	fscanf(filein, "%s", &prompt); 
	fscanf(filein, "%d", &GBINS); 
	fscanf(filein, "%s", &prompt); 
	fscanf(filein, "%d", &BBINS); 
	 
	fclose(filein); 
 
	//in case of wrong setting 
	if(RBINS<=0)  
		RBINS = 10; 
	if(GBINS<=0)  
		GBINS = 10; 
	if(BBINS<=0)  
		BBINS = 10; 
 
//	//debug  
//	RBINS = 50; 
//	GBINS = 50; 
//	BBINS = 50; 
} 
 
///////////////////////////////////////////////////////////////////////////////////////// 
void his_CheckBoxBound(RECT *inRect, int imgWidth, int imgHeight) 
//check whether the box (left, right, top, bottm) is out of bound 
{ 
	inRect->left	= max(inRect->left, 0); 
	inRect->right	= min(inRect->right, imgWidth-1); 
	inRect->top		= max(inRect->top, 0); 
	inRect->bottom	= min(inRect->bottom, imgHeight-1);	 
 
	inRect->right = (inRect->right>inRect->left? inRect->right: inRect->left); 
	inRect->bottom = (inRect->bottom>inRect->top? inRect->bottom: inRect->top); 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
void his_CountBoxHistogram(IplImage* inImg, RECT inRect, CvHistogram *outHist) 
//count histogram within a rect box 
{ 
	int		row, col; 
	BYTE	pixH, pixS, pixV; 
	int		binH, binS, binV; 
	float	*pix; 
	 
	IplImage* h_plane = cvCreateImage(cvGetSize(inImg), 8, 1 ); 
    IplImage* s_plane = cvCreateImage(cvGetSize(inImg), 8, 1 ); 
    IplImage* v_plane = cvCreateImage(cvGetSize(inImg), 8, 1 ); 
 
	//Divide image into planes 
	cvCvtPixToPlane(inImg, h_plane, s_plane, v_plane, 0 ); 
 
	//count histogram 
	cvClearHist(outHist);		 
	for (row=inRect.top;row<=inRect.bottom;row++){	 
		for (col=inRect.left; col<=inRect.right; col++){								 
			//calculate histogram 
			pixH = (BYTE)cvGetReal2D(h_plane,row,col); 
			pixS = (BYTE)cvGetReal2D(s_plane,row,col); 
			pixV = (BYTE)cvGetReal2D(v_plane,row,col); 
			binH = (int)(RBINS*pixH/256); 
			binS = (int)(GBINS*pixS/256); 
			binV = (int)(BBINS*pixV/256); 
 
			pix = cvGetHistValue_3D(outHist,binH,binS,binV); 
			(*pix)++; 
		} 
	} 
	cvReleaseImage( &h_plane); 
	cvReleaseImage( &s_plane); 
	cvReleaseImage( &v_plane); 
} 
 
/******************************************************************************/ 
void his_CalcGravityCenter2(IplImage* inImg, RECT blobBox, POINT *outCenter) 
//get blob weight center  
{		 
	int		row, col; 
	int		border = 10; 
	BYTE	pixel; 
	float	sumRow, sumCol, sumPix; 
	POINT	center; 
	int		dx, dy; 
 
	//get outer ring box 
	center.x = (blobBox.left+blobBox.right)/2; 
	center.y = (blobBox.top+blobBox.bottom)/2; 
 
	sumRow = 0; 
	sumCol = 0; 
	sumPix = 0; 
	for (col=blobBox.left; colx = center.x + dx; 
	outCenter->y = center.y + dy; 
} 
 
/******************************************************************************/ 
void his_CalcGravityCenter(IplImage* inImg, POINT *outCenter) 
//get blob weight center by moments 
{	 
	CvMoments moments;	 
 
	cvMoments(inImg, &moments, 0); 
	outCenter->x = (int)fn_Round(moments.m10/moments.m00); 
	outCenter->y = (int)fn_Round(moments.m01/moments.m00);		 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
void his_BlobCenterShift(IplImage* inImg, RECT *inRect, int range) 
//shift to track blob center movement 
{	 
	RECT	shiftBox;  
	int		row, col; 
	BYTE	pixel; 
	float	sumRow, sumCol, sumPix; 
	POINT	center, inCenter; 
	//int		halfWidth, halfHeight; 
	int		dx, dy; 
	int		loopCount;	 
 
	//get outer ring box 
	shiftBox.left = inRect->left; 
	shiftBox.right = inRect->right; 
	shiftBox.top = inRect->top; 
	shiftBox.bottom = inRect->bottom; 
	his_CheckBoxBound(&shiftBox, inImg->width, inImg->height); 
	inCenter.x = (shiftBox.left+shiftBox.right)/2; //input Rect center 
	inCenter.y = (shiftBox.top+shiftBox.bottom)/2; 
	center.x = inCenter.x; //shift center 
	center.y = inCenter.y;  
 
	loopCount=0; 
	dx=1; 
	dy=1; 
	while (abs(dx)+abs(dy)>=1 && loopCount<10){		 
		sumRow = 0; 
		sumCol = 0; 
		sumPix = 0; 
		for (col=shiftBox.left; colwidth, inImg->height); 
		center.x = (shiftBox.left+shiftBox.right)/2; 
		center.y = (shiftBox.top+shiftBox.bottom)/2; 
 
		loopCount++; 
	} 
	//output shift result 
	dx = center.x - inCenter.x; 
	dy = center.y - inCenter.y; 
	if (dx<-range)	dx = -range; 
	if (dx>range)	dx = range; 
	if (dy<-range)	dy = -range; 
	if (dy>range)	dy = range; 
 
	inRect->left	= inRect->left + dx; 
	inRect->right	= inRect->right + dx; 
	inRect->top		= inRect->top + dy; 
	inRect->bottom	= inRect->bottom + dy; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
void his_TrackInit_Bins(IplImage *inImg, IplImage *inMask, RECT inRect, int nbins1, int nbins2, int nbins3) 
//tracker init with RGB bins parameters 
{ 
	//set histogram bins 
	RBINS = nbins1; 
	GBINS = nbins2; 
	BBINS = nbins3; 
 
	//init tracker 
	his_TrackInit(inImg, inMask, inRect); 
} 
 
 
/////////////////////////////////////////////////////////////////////////////// 
void his_TrackInit(IplImage *inImg, IplImage *inMask, RECT inRect) 
//tracker init with mask image 
{ 
	//histogram variable 
	float	h_ranges[] = { 0, 255}; /* hue varies from 0 (~0°red) to 180 (~360°red again) */ 
    float	s_ranges[] = { 0, 255}; /* saturation varies from 0 (black-gray-white) to 255 (pure spectrum color) */ 
	float	v_ranges[] = { 0, 255};  
    int		hist_size[] = {RBINS, GBINS, BBINS}; 
	float	max_value = 0; 
	float*	ranges[] = { h_ranges, s_ranges, v_ranges};	    	 
	int		row, col; 
	BYTE	pixR, pixG, pixB; 
	float	*pix; 
	int		binR, binG, binB; 
	BOOL	bResult =0; 
	BYTE    maskPix; 
	CvScalar	pixel; 
 
	//check whether input is valid 
	if (inImg==NULL) return; 
	utl_RectCheckBound(&inRect, inImg->width, inImg->height); 
 
	//release memeory in case re-initialize 
	his_TrackCleanUp(); 
 
	gHistInit = cvCreateHist(3, hist_size, CV_HIST_ARRAY, ranges, 1 ); 
	gHistModel = cvCreateHist(3, hist_size, CV_HIST_ARRAY, ranges, 1 );			 
	//create histogram		 
	gImgBackProj = cvCreateImage(cvGetSize(inImg), 8, 1); 
	gImgFgMask = cvCreateImage(cvGetSize(inImg), 8, 1); 
	gImgObjMask = cvCreateImage(cvGetSize(inImg), 8, 3); 
 
	//clear histogram array 
	cvClearHist(gHistInit); 
	//count index image 
	gMaskPixCount = 0; 
	for (row=inRect.top;row<=inRect.bottom;row++){ 
		for (col=inRect.left; col<=inRect.right; col++){		 
			//bResult = PtInRegion(hRegion, col, row); 
			maskPix = (BYTE)cvGetReal2D(inMask, row, col); 
			if (maskPix>0){			 
				gMaskPixCount++; 
				//calculate histogram 
				pixel = cvGet2D(inImg, row, col); 
				pixR = (BYTE)pixel.val[0]; 
				pixG = (BYTE)pixel.val[1]; 
				pixB = (BYTE)pixel.val[2]; 
				binR = (int)(RBINS*pixR/256); 
				binG = (int)(GBINS*pixG/256); 
				binB = (int)(BBINS*pixB/256); 
				pix = cvGetHistValue_3D(gHistInit,binR,binG,binB); 
				(*pix)++; 
			}			 
		} 
	} 
		 
	gMaskFgRatio = (float)gMaskPixCount/((inRect.right-inRect.left)*(inRect.bottom-inRect.top)); 
		 
	//get outer box histogram 
	cvClearHist(gHistModel);	 
	{ 
		//outer ring Box 
		RECT outerBox; 
 
		//get outer ring box 
		outerBox.left	= inRect.left-gBorder; 
		outerBox.right	= inRect.right+gBorder; 
		outerBox.top	= inRect.top-gBorder; 
		outerBox.bottom	= inRect.bottom +gBorder; 
		his_CheckBoxBound(&outerBox, inImg->width, inImg->height); 
 
		//count index image 
		for (row=outerBox.top;row<=outerBox.bottom;row++){	 
			for (col=outerBox.left; col<=outerBox.right; col++){								 
				//calculate histogram 
				pixel = cvGet2D(inImg, row, col); 
				pixR = (BYTE)pixel.val[0]; 
				pixG = (BYTE)pixel.val[1]; 
				pixB = (BYTE)pixel.val[2]; 
				binR = (int)(RBINS*pixR/256); 
				binG = (int)(GBINS*pixG/256); 
				binB = (int)(BBINS*pixB/256); 
 
				pix = cvGetHistValue_3D(gHistModel,binR,binG,binB); 
				(*pix)++; 
			} 
		}			 
	} 
		 
	//get back project image 
	{			 
		CvRect	trackRect;			 
 
		//ratio histogram			 
		//gHistRatio = his_HistogramRatio(gHistInit, gHistModel); 
		gHistRatio = his_HistogramDivide(gHistInit, gHistModel); 
 
		//debug - print out rst 
//		{ 
//			_chdir(gExePath);		 
//			his_PrintHistogram(gHistInit, "result/gHistInit.txt"); 
//			his_PrintHistogram(gHistModel, "result/gHistModel.txt"); 
//			his_PrintHistogram(gHistRatio, "result/gHistRatio.txt"); 
//		} 
			 
		//get foreground 
		trackRect.x			= inRect.left; 
		trackRect.y			= inRect.top; 
		trackRect.width		= inRect.right - inRect.left; 
		trackRect.height	= inRect.bottom - inRect.top; 
		his_CalcForeground2(inImg, gHistRatio, trackRect, gImgBackProj); 
 
		//get the foreground gravity center 
		//his_CalcGravityCenter(gImgBackProj, &gGravityCenter);		 
 
		//release memory 
		cvReleaseHist(&gHistRatio); 
	} 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
void his_TrackNextFrame(IplImage* inImg, RECT inRect, TkResult *outResult) 
//move gravity center by histogram ratio 
{ 
	CvRect	trackRect; 
	RECT	outerBox; 
	float	score=1; 
	//int		countPix; 
 
	//check whether input is valid 
	if (inImg==NULL) return; 
	utl_RectCheckBound(&inRect, inImg->width, inImg->height); 
 
	trackRect.x			= inRect.left; 
	trackRect.y			= inRect.top; 
	trackRect.width		= inRect.right - inRect.left; 
	trackRect.height	= inRect.bottom - inRect.top; 
 
	//get outer ring box 
	outerBox.left	= inRect.left-gBorder; 
	outerBox.right	= inRect.right+gBorder; 
	outerBox.top	= inRect.top-gBorder; 
	outerBox.bottom = inRect.bottom +gBorder; 
	his_CheckBoxBound(&outerBox, inImg->width, inImg->height); 
 
	//get histogram Model of outerBox 
	his_CountBoxHistogram(inImg, outerBox, gHistModel); 
 
	//get Histogram Ratio 
	gHistRatio = his_HistogramRatio(gHistInit, gHistModel);	 
	gHistDivide = his_HistogramDivide(gHistInit, gHistModel);	 
	 
	//normalize histogram 
	//cvThreshHist(gHistRatio, 60);	 
	//his_HistogramNormalize(gHistRatio); 
	 
	//get back projection image based on ratio histogram	 
	his_CalcForeground2(inImg, gHistDivide, trackRect, gImgBackProj); 
 
	//find blobCenter				 
	his_BlobCenterShift(gImgBackProj, &inRect, 15); 
 
	//calculate tracking score 
	score = his_CountFGPixel(gImgBackProj, inRect); 
 
	//update foreground image for display purpose 
	his_CalcForeground2(inImg, gHistRatio, trackRect, gImgBackProj); 
	cvThreshold(gImgBackProj, gImgBackProj, 5, 0, CV_THRESH_TOZERO); 
	 
	//get FG object mask image 
	{ 
		CvRect  roi;	 
		cvSetZero(gImgFgMask);	 
		cvSetZero(gImgObjMask);	 
		roi.x = inRect.left; 
		roi.y = inRect.top; 
		roi.width = inRect.right-inRect.left; 
		roi.height = inRect.bottom-inRect.top; 
		cvSetImageROI(gImgBackProj, roi); 
		cvSetImageROI(gImgFgMask, roi);		 
		cvSetImageROI(inImg, roi); 
		cvSetImageROI(gImgObjMask, roi);		 
		cvThreshold(gImgBackProj, gImgFgMask, 50, 255, CV_THRESH_BINARY); 
		cvCopy(inImg, gImgObjMask, gImgFgMask); 
		cvResetImageROI(gImgBackProj); 
		cvResetImageROI(gImgFgMask); 
		cvResetImageROI(inImg);		 
		cvResetImageROI(gImgObjMask);	 
	} 
 
	//assign returning results 
	outResult->targetBox = inRect; 
	outResult->FGImage	= gImgBackProj; 
	outResult->FGMask	= gImgFgMask; 
	outResult->ObjMask	= gImgObjMask; 
	outResult->score	= score;		 
	outResult->occlusion = (score<0.5? TRUE:FALSE);	 
	 
	//clear histogram 
	cvReleaseHist(&gHistRatio); 
	cvReleaseHist(&gHistDivide); 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
float his_CountFGPixel(IplImage *inImg, RECT inRect) 
//cout foreground pixel number to find score 
{ 
	int pixCount; 
	float score; 
	CvRect crectRoi;	 
 
	//count foreground points 
	crectRoi.x = inRect.left; 
	crectRoi.y = inRect.top; 
	crectRoi.width = inRect.right - inRect.left; 
	crectRoi.height = inRect.bottom - inRect.top; 
	cvSetImageROI(inImg, crectRoi); 
	pixCount = cvCountNonZero(inImg); 
	inImg->roi = NULL; 
	 
	score = (float)pixCount/(crectRoi.width*crectRoi.height);		 
	//score = (float)pixCount/gMaskPixCount; 
	score = score/gMaskFgRatio; 
	score = min(1, score); 
 
	return score; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
void his_TrackCleanUp() 
//release memory 
{ 
	//clear histogram 
	cvReleaseHist(&gHistInit); 
	cvReleaseHist(&gHistModel); 
	cvReleaseHist(&gHistRatio); 
	cvReleaseHist(&gHistDivide); 
 
	//projection image 
	cvReleaseImage(&gImgBackProj); 
	cvReleaseImage(&gImgFgMask); 
	cvReleaseImage(&gImgObjMask); 
}