Ejemplo n.º 1
0
/*
 * @src Frame image
 * @contour  contour processing
 * @testImageHistogram histogram from model image
 * @h_bins number of hue bins
 * @s_bins number of sat bins 
 * @min minimum similarity to achieve when comparing histograms
 */
int Contours::histogramMatchingFilter(IplImage * src, CvHistogram * testImageHistogram,int h_bins,int s_bins, double min){
	CvRect box;
	CvMemStorage* mem = cvCreateMemStorage(0);
	
	double val;
	
	
	//get contour bounding box
	box=cvBoundingRect(this->c,0);
	
	//printf("box x:%d y:%d \n",box.x,box.y);
	
	IplImage * src_bbox=cvCreateImage(cvSize(box.width,box.height),src->depth,src->nChannels);
	
	//gets subimage bounded by box
    cvGetSubArr( src,(CvMat*)src_bbox, box );

	//gets subimage histogram
	utils::Histogram * h = new Histogram(h_bins,s_bins);
	CvHistogram* hist = h->getHShistogramFromRGB(src_bbox);
	//compares with object histogram
	val=cvCompareHist(hist,testImageHistogram,CV_COMP_BHATTACHARYYA);
	
	cvReleaseHist(&hist);
	cvReleaseImage(&src_bbox);
	cvReleaseMemStorage(&mem);
	delete h;
	
	return (val<min);
}
Ejemplo n.º 2
0
CV_IMPL  double
cvPseudoInv( CvArr* srcarr, CvArr* dstarr, int flags )
{
    uchar* buffer = 0;
    int local_alloc = 0;
    double condition_number = 0;

    CV_FUNCNAME( "cvPseudoInv" );

    __BEGIN__;

    CvMat astub, *a = (CvMat*)srcarr;
    CvMat bstub, *b = (CvMat*)dstarr;
    CvMat ustub, *u = &ustub;
    CvMat vstub, *v = &vstub;
    CvMat tmat;
    uchar* tw = 0;
    int type, n, m, nm, mn;
    int buf_size, pix_size;

    if( !CV_IS_ARR( a ))
        CV_CALL( a = cvGetMat( a, &astub ));

    if( !CV_IS_ARR( b ))
        CV_CALL( b = cvGetMat( b, &bstub ));

    if( !CV_ARE_TYPES_EQ( a, b ))
        CV_ERROR( CV_StsUnmatchedSizes, "" );

    n = a->width;
    m = a->height;

    nm = MIN( n, m );
    mn = MAX( n, m );

    if( n != b->height || m != b->width )
        CV_ERROR( CV_StsUnmatchedSizes, "" );

    type = CV_ARR_TYPE( a->type );
    pix_size = icvPixSize[type];

    buf_size = nm*2 + mn + m*mn + n*n;

    if( !(flags & CV_SVD_MODIFY_A) )
        buf_size += m*n;

    buf_size *= pix_size;

    if( buf_size <= CV_MAX_LOCAL_SIZE )
    {
        buffer = (uchar*)alloca( buf_size );
        local_alloc = 1;
    }
    else
    {
        CV_CALL( buffer = (uchar*)cvAlloc( buf_size ));
    }

    if( !(flags & CV_SVD_MODIFY_A) )
    {
        cvInitMatHeader( &tmat, a->height, a->width, type,
                         buffer + buf_size - n*m*pix_size );
        cvCopy( a, &tmat );
        a = &tmat;
    }

    tw = buffer + (nm + mn)*pix_size;

    cvInitMatHeader( u, m, m, type, tw + nm*pix_size );
    cvInitMatHeader( v, n, n, type, u->data.ptr + m*mn*pix_size );

    if( type == CV_32FC1 )
    {
        IPPI_CALL( icvSVD_32f( a->data.fl, a->step/sizeof(float), (float*)tw,
                               u->data.fl, u->step/sizeof(float),
                               v->data.fl, v->step/sizeof(float),
                               icvGetMatSize(a), (float*)buffer ));
    }
    else if( type == CV_64FC1 )
    {
        IPPI_CALL( icvSVD_64f( a->data.db, a->step/sizeof(double), (double*)tw,
                               u->data.db, u->step/sizeof(double),
                               v->data.db, v->step/sizeof(double),
                               icvGetMatSize(a), (double*)buffer ));
    }
    else
    {
        CV_ERROR( CV_StsUnsupportedFormat, "" );
    }

    cvT( v, v );
    cvGetRow( u, &tmat, 0 );

    if( type == CV_32FC1 )
    {
        for( int i = 0; i < nm; i++ )
        {
            double t = ((float*)tw)[i];
            tmat.data.ptr = u->data.ptr + i*u->step;
            t = t > FLT_EPSILON ? 1./t : 0;
            if( i == mn - 1 )
                condition_number = t != 0 ? ((float*)tw)[0]*t : DBL_MAX;
            cvScale( &tmat, &tmat, t );
        }
    }
    else
    {
        for( int i = 0; i < nm; i++ )
        {
            double t = ((double*)tw)[i];
            tmat.data.ptr = u->data.ptr + i*u->step;
            t = t > DBL_EPSILON ? 1./t : 0;
            if( i == mn - 1 )
                condition_number = t != 0 ? ((double*)tw)[0]*t : DBL_MAX;
            cvScale( &tmat, &tmat, t );
        }
    }

    u->height = n;
    if( n > m )
    {
        cvGetSubArr( u, &tmat, cvRect( 0, m, m, n - m ));
        cvSetZero( &tmat );
    }
    
    cvMatMulAdd( v, u, 0, b );

    CV_CHECK_NANS( b );

    __END__;

    if( buffer && !local_alloc )
        cvFree( (void**)&buffer );

    return condition_number;
}
Ejemplo n.º 3
0
static CvStatus
icvSnake8uC1R( unsigned char *src,
               int srcStep,
               CvSize roi,
               CvPoint * pt,
               int n,
               float *alpha,
               float *beta,
               float *gamma,
               int coeffUsage, CvSize win, CvTermCriteria criteria, int scheme )
{
    int i, j, k;
    int neighbors = win.height * win.width;

    int centerx = win.width >> 1;
    int centery = win.height >> 1;

    float invn;
    int iteration = 0;
    int converged = 0;
	

    float *Econt;
    float *Ecurv;
    float *Eimg;
    float *E;

    float _alpha, _beta, _gamma;

    /*#ifdef GRAD_SNAKE */
    float *gradient = NULL;
    uchar *map = NULL;
    int map_width = ((roi.width - 1) >> 3) + 1;
    int map_height = ((roi.height - 1) >> 3) + 1;
    CvSepFilter pX, pY;
    #define WTILE_SIZE 8
    #define TILE_SIZE (WTILE_SIZE + 2)        
    short dx[TILE_SIZE*TILE_SIZE], dy[TILE_SIZE*TILE_SIZE];
    CvMat _dx = cvMat( TILE_SIZE, TILE_SIZE, CV_16SC1, dx );
    CvMat _dy = cvMat( TILE_SIZE, TILE_SIZE, CV_16SC1, dy );
    CvMat _src = cvMat( roi.height, roi.width, CV_8UC1, src );

    /* inner buffer of convolution process */
    //char ConvBuffer[400];

    /*#endif */


    /* check bad arguments */
    if( src == NULL )
        return CV_NULLPTR_ERR;
    if( (roi.height <= 0) || (roi.width <= 0) )
        return CV_BADSIZE_ERR;
    if( srcStep < roi.width )
        return CV_BADSIZE_ERR;
    if( pt == NULL )
        return CV_NULLPTR_ERR;
    if( n < 3 )
        return CV_BADSIZE_ERR;
    if( alpha == NULL )
        return CV_NULLPTR_ERR;
    if( beta == NULL )
        return CV_NULLPTR_ERR;
    if( gamma == NULL )
        return CV_NULLPTR_ERR;
    if( coeffUsage != CV_VALUE && coeffUsage != CV_ARRAY )
        return CV_BADFLAG_ERR;
    if( (win.height <= 0) || (!(win.height & 1)))
        return CV_BADSIZE_ERR;
    if( (win.width <= 0) || (!(win.width & 1)))
        return CV_BADSIZE_ERR;

    invn = 1 / ((float) n);

    if( scheme == _CV_SNAKE_GRAD )
    {
        pX.init_deriv( TILE_SIZE+2, CV_8UC1, CV_16SC1, 1, 0, 3 );
        pY.init_deriv( TILE_SIZE+2, CV_8UC1, CV_16SC1, 0, 1, 3 );

        gradient = (float *) cvAlloc( roi.height * roi.width * sizeof( float ));

        if( !gradient )
            return CV_OUTOFMEM_ERR;
        map = (uchar *) cvAlloc( map_width * map_height );
        if( !map )
        {
            cvFree( &gradient );
            return CV_OUTOFMEM_ERR;
        }
        /* clear map - no gradient computed */
        memset( (void *) map, 0, map_width * map_height );
    }
    Econt = (float *) cvAlloc( neighbors * sizeof( float ));
    Ecurv = (float *) cvAlloc( neighbors * sizeof( float ));
    Eimg = (float *) cvAlloc( neighbors * sizeof( float ));
    E = (float *) cvAlloc( neighbors * sizeof( float ));

    while( !converged )
    {
        float ave_d = 0;
        int moved = 0;

        converged = 0;
        iteration++;
        /* compute average distance */
        for( i = 1; i < n; i++ )
        {
            int diffx = pt[i - 1].x - pt[i].x;
            int diffy = pt[i - 1].y - pt[i].y;

            ave_d += cvSqrt( (float) (diffx * diffx + diffy * diffy) );
        }
        ave_d += cvSqrt( (float) ((pt[0].x - pt[n - 1].x) *
                                  (pt[0].x - pt[n - 1].x) +
                                  (pt[0].y - pt[n - 1].y) * (pt[0].y - pt[n - 1].y)));

        ave_d *= invn;
        /* average distance computed */
        for( i = 0; i < n; i++ )
        {
            /* Calculate Econt */
            float maxEcont = 0;
            float maxEcurv = 0;
            float maxEimg = 0;
            float minEcont = _CV_SNAKE_BIG;
            float minEcurv = _CV_SNAKE_BIG;
            float minEimg = _CV_SNAKE_BIG;
            float Emin = _CV_SNAKE_BIG;

            int offsetx = 0;
            int offsety = 0;
            float tmp;

            /* compute bounds */
            int left = MIN( pt[i].x, win.width >> 1 );
            int right = MIN( roi.width - 1 - pt[i].x, win.width >> 1 );
            int upper = MIN( pt[i].y, win.height >> 1 );
            int bottom = MIN( roi.height - 1 - pt[i].y, win.height >> 1 );

            maxEcont = 0;
            minEcont = _CV_SNAKE_BIG;
            for( j = -upper; j <= bottom; j++ )
            {
                for( k = -left; k <= right; k++ )
                {
                    int diffx, diffy;
                    float energy;

                    if( i == 0 )
                    {
                        diffx = pt[n - 1].x - (pt[i].x + k);
                        diffy = pt[n - 1].y - (pt[i].y + j);
                    }
                    else
                    {
                        diffx = pt[i - 1].x - (pt[i].x + k);
                        diffy = pt[i - 1].y - (pt[i].y + j);
                    }
                    Econt[(j + centery) * win.width + k + centerx] = energy =
                        (float) fabs( ave_d -
                                      cvSqrt( (float) (diffx * diffx + diffy * diffy) ));

                    maxEcont = MAX( maxEcont, energy );
                    minEcont = MIN( minEcont, energy );
                }
            }
            tmp = maxEcont - minEcont;
            tmp = (tmp == 0) ? 0 : (1 / tmp);
            for( k = 0; k < neighbors; k++ )
            {
                Econt[k] = (Econt[k] - minEcont) * tmp;
            }

            /*  Calculate Ecurv */
            maxEcurv = 0;
            minEcurv = _CV_SNAKE_BIG;
            for( j = -upper; j <= bottom; j++ )
            {
                for( k = -left; k <= right; k++ )
                {
                    int tx, ty;
                    float energy;

                    if( i == 0 )
                    {
                        tx = pt[n - 1].x - 2 * (pt[i].x + k) + pt[i + 1].x;
                        ty = pt[n - 1].y - 2 * (pt[i].y + j) + pt[i + 1].y;
                    }
                    else if( i == n - 1 )
                    {
                        tx = pt[i - 1].x - 2 * (pt[i].x + k) + pt[0].x;
                        ty = pt[i - 1].y - 2 * (pt[i].y + j) + pt[0].y;
                    }
                    else
                    {
                        tx = pt[i - 1].x - 2 * (pt[i].x + k) + pt[i + 1].x;
                        ty = pt[i - 1].y - 2 * (pt[i].y + j) + pt[i + 1].y;
                    }
                    Ecurv[(j + centery) * win.width + k + centerx] = energy =
                        (float) (tx * tx + ty * ty);
                    maxEcurv = MAX( maxEcurv, energy );
                    minEcurv = MIN( minEcurv, energy );
                }
            }
            tmp = maxEcurv - minEcurv;
            tmp = (tmp == 0) ? 0 : (1 / tmp);
            for( k = 0; k < neighbors; k++ )
            {
                Ecurv[k] = (Ecurv[k] - minEcurv) * tmp;
            }

            /* Calculate Eimg */
            for( j = -upper; j <= bottom; j++ )
            {
                for( k = -left; k <= right; k++ )
                {
                    float energy;

                    if( scheme == _CV_SNAKE_GRAD )
                    {
                        /* look at map and check status */
                        int x = (pt[i].x + k)/WTILE_SIZE;
                        int y = (pt[i].y + j)/WTILE_SIZE;

                        if( map[y * map_width + x] == 0 )
                        {
                            int l, m;							

                            /* evaluate block location */
                            int upshift = y ? 1 : 0;
                            int leftshift = x ? 1 : 0;
                            int bottomshift = MIN( 1, roi.height - (y + 1)*WTILE_SIZE );
                            int rightshift = MIN( 1, roi.width - (x + 1)*WTILE_SIZE );
                            CvRect g_roi = { x*WTILE_SIZE - leftshift, y*WTILE_SIZE - upshift,
                                leftshift + WTILE_SIZE + rightshift, upshift + WTILE_SIZE + bottomshift };
                            CvMat _src1;
                            cvGetSubArr( &_src, &_src1, g_roi );

                            pX.process( &_src1, &_dx );
                            pY.process( &_src1, &_dy );

                            for( l = 0; l < WTILE_SIZE + bottomshift; l++ )
                            {
                                for( m = 0; m < WTILE_SIZE + rightshift; m++ )
                                {
                                    gradient[(y*WTILE_SIZE + l) * roi.width + x*WTILE_SIZE + m] =
                                        (float) (dx[(l + upshift) * TILE_SIZE + m + leftshift] *
                                                 dx[(l + upshift) * TILE_SIZE + m + leftshift] +
                                                 dy[(l + upshift) * TILE_SIZE + m + leftshift] *
                                                 dy[(l + upshift) * TILE_SIZE + m + leftshift]);
                                }
                            }
                            map[y * map_width + x] = 1;
                        }
                        Eimg[(j + centery) * win.width + k + centerx] = energy =
                            gradient[(pt[i].y + j) * roi.width + pt[i].x + k];
                    }
                    else
                    {
                        Eimg[(j + centery) * win.width + k + centerx] = energy =
                            src[(pt[i].y + j) * srcStep + pt[i].x + k];
                    }

                    maxEimg = MAX( maxEimg, energy );
                    minEimg = MIN( minEimg, energy );
                }
            }

            tmp = (maxEimg - minEimg);
            tmp = (tmp == 0) ? 0 : (1 / tmp);

            for( k = 0; k < neighbors; k++ )
            {
                Eimg[k] = (minEimg - Eimg[k]) * tmp;
            }

            /* locate coefficients */
            if( coeffUsage == CV_VALUE)
            {
                _alpha = *alpha;
                _beta = *beta;
                _gamma = *gamma;
            }
            else
            {                   
                _alpha = alpha[i];
                _beta = beta[i];
                _gamma = gamma[i];
            }

            /* Find Minimize point in the neighbors */
            for( k = 0; k < neighbors; k++ )
            {
                E[k] = _alpha * Econt[k] + _beta * Ecurv[k] + _gamma * Eimg[k];
            }
            Emin = _CV_SNAKE_BIG;
            for( j = -upper; j <= bottom; j++ )
            {
                for( k = -left; k <= right; k++ )
                {

                    if( E[(j + centery) * win.width + k + centerx] < Emin )
                    {
                        Emin = E[(j + centery) * win.width + k + centerx];
                        offsetx = k;
                        offsety = j;
                    }
                }
            }

            if( offsetx || offsety )
            {
                pt[i].x += offsetx;
                pt[i].y += offsety;
                moved++;
            }
        }
        converged = (moved == 0);
        if( (criteria.type & CV_TERMCRIT_ITER) && (iteration >= criteria.max_iter) )
            converged = 1;
        if( (criteria.type & CV_TERMCRIT_EPS) && (moved <= criteria.epsilon) )
            converged = 1;
    }

    cvFree( &Econt );
    cvFree( &Ecurv );
    cvFree( &Eimg );
    cvFree( &E );

    if( scheme == _CV_SNAKE_GRAD )
    {
        cvFree( &gradient );
        cvFree( &map );
    }
    return CV_OK;
}
Ejemplo n.º 4
0
static CvStatus
icvSnakeTrack8uC1R( unsigned char *src,
				   int srcStep,
				   CvSize roi,
				   CvPoint * pt,
				   int n,
				   float *alpha,
				   float *beta,
				   float *gamma,
				   int coeffUsage, CvSize win, CvTermCriteria criteria, int scheme
				   , unsigned char *osrc, //original image where contours are generated.
				   CvPoint *opt,
				    //weights of the original fit
				   float *oalpha, float *obeta, float *ogamma, float *oteta, float *ozeta, float *oomega,
				   IplImage *dux, IplImage *odux, IplImage *duy, IplImage *oduy, 
				   float *oEarc_static = NULL, bool oEarc_static_ready = false,
				   int *iterations = NULL)
{
	int i, j, k;
	int neighbors = win.height * win.width;

	int centerx = win.width >> 1;
	int centery = win.height >> 1;

	float invn;
	int iteration = 0;
	int converged = 0;


	float *E;

	float _alpha=*alpha, _beta=*beta, _gamma=*gamma;

	/*#ifdef GRAD_SNAKE */
	float *gradient = NULL;
	uchar *map = NULL;
	int map_width = ((roi.width - 1) >> 3) + 1;
	int map_height = ((roi.height - 1) >> 3) + 1;
	CvSepFilter pX, pY;
#define WTILE_SIZE 8
#define TILE_SIZE (WTILE_SIZE + 2)
	short dx[TILE_SIZE*TILE_SIZE], dy[TILE_SIZE*TILE_SIZE];
	CvMat _dx = cvMat( TILE_SIZE, TILE_SIZE, CV_16SC1, dx );
	CvMat _dy = cvMat( TILE_SIZE, TILE_SIZE, CV_16SC1, dy );
	CvMat _src = cvMat( roi.height, roi.width, CV_8UC1, src );

	/* inner buffer of convolution process */
	//char ConvBuffer[400];

	/*#endif */


	/* check bad arguments */
	if( src == NULL )
		return CV_NULLPTR_ERR;
	if( osrc == NULL )
		return CV_NULLPTR_ERR;
	if( (roi.height <= 0) || (roi.width <= 0) )
		return CV_BADSIZE_ERR;
	if( srcStep < roi.width )
		return CV_BADSIZE_ERR;
	if( pt == NULL )
		return CV_NULLPTR_ERR;
	if( n < 3 )
		return CV_BADSIZE_ERR;
	if( alpha == NULL )
		return CV_NULLPTR_ERR;
	if( beta == NULL )
		return CV_NULLPTR_ERR;
	if( gamma == NULL )
		return CV_NULLPTR_ERR;
	if( oalpha == NULL )
		return CV_NULLPTR_ERR;
	if( obeta == NULL )
		return CV_NULLPTR_ERR;
	if( ogamma == NULL )
		return CV_NULLPTR_ERR;
	if( oteta == NULL )
		return CV_NULLPTR_ERR;
	if( ozeta == NULL )
		return CV_NULLPTR_ERR;
	if( coeffUsage != CV_VALUE && coeffUsage != CV_ARRAY )
		return CV_BADFLAG_ERR;
	if( (win.height <= 0) || (!(win.height & 1)))
		return CV_BADSIZE_ERR;
	if( (win.width <= 0) || (!(win.width & 1)))
		return CV_BADSIZE_ERR;

	invn = 1 / ((float) n);

	if( scheme == _CV_SNAKE_GRAD )
	{
		pX.init_deriv( TILE_SIZE+2, CV_8UC1, CV_16SC1, 1, 0, 3 );
		pY.init_deriv( TILE_SIZE+2, CV_8UC1, CV_16SC1, 0, 1, 3 );

		gradient = (float *) cvAlloc( roi.height * roi.width * sizeof( float ));
		memset((void*)gradient, 0, roi.height*roi.width*sizeof(float));
		if( !gradient )
			return CV_OUTOFMEM_ERR;
		map = (uchar *) cvAlloc( map_width * map_height );
		if( !map )
		{
			cvFree( &gradient );
			return CV_OUTOFMEM_ERR;
		}
		/* clear map - no gradient computed */
		memset( (void *) map, 0, map_width * map_height );
	}
	E = (float *) cvAlloc( neighbors * sizeof( float ));

	//------------------------- Original Image Parameters ----------------
	float _oalpha=*oalpha, _obeta=*obeta, _ogamma=*ogamma, _oteta=*oteta, _ozeta=*ozeta, _oomega=*oomega;
	CvMat _osrc = cvMat( roi.height, roi.width, CV_8UC1, osrc );
	int roisize=roi.width*roi.width;
#define INIT_ENERGY_TERM(X)	\
	float *X     = (float *) cvAlloc( neighbors * sizeof( float )); \
	float *o##X  = (float *) cvAlloc( n * sizeof( float )); \
	float *os##X = (float *) cvAlloc( n * sizeof( float )); \
	memset(X, 0, neighbors * sizeof(float)); \
	memset(o##X, 0, n * sizeof(float)); \
	memset(os##X, 0, n * sizeof(float));
INIT_ENERGY_TERM(Econt)
INIT_ENERGY_TERM(Ecurv)
INIT_ENERGY_TERM(Eimg)
INIT_ENERGY_TERM(Eint)
INIT_ENERGY_TERM(Earc)
INIT_ENERGY_TERM(Edux)
INIT_ENERGY_TERM(Eduy)
	//------------------------ //End Original Image Parameters
	CvMat *_srcp;
	unsigned char *srcp;
	CvPoint *ppt;
	IplImage *pdux, *pduy;
	for (int isoriginit=0; isoriginit<2; isoriginit++){
		if (!isoriginit){
			ppt=opt;
			_srcp=&_osrc;
			srcp=osrc;
			pdux = odux;
			pduy = oduy;
		}
		else{
			ppt=pt;
			_srcp=&_src;
			srcp=src;
			converged=0;
			iteration=0;
			if( scheme == _CV_SNAKE_GRAD )
				memset( (void *) map, 0, map_width * map_height );
			pdux = dux;
			pduy = duy;
		}


		while( !converged )
		{
			float ave_d = 0;
			int moved = 0;

			converged = 0;
			iteration++;
			/* compute average distance */
			for( i = 1; i < n; i++ )
			{
				int diffx = ppt[i - 1].x - ppt[i].x;
				int diffy = ppt[i - 1].y - ppt[i].y;

				ave_d += cvSqrt( (float) (diffx * diffx + diffy * diffy) );
			}
			ave_d += cvSqrt( (float) ((ppt[0].x - ppt[n - 1].x) *
				(ppt[0].x - ppt[n - 1].x) +
				(ppt[0].y - ppt[n - 1].y) * (ppt[0].y - ppt[n - 1].y)));

			ave_d *= invn;
			/* average distance computed */
			for( i = 0; i < n; i++ )
			{
				float Emin = _CV_SNAKE_BIG;
				float maxEcont = 0, minEcont = _CV_SNAKE_BIG;
				float maxEcurv = 0, minEcurv = _CV_SNAKE_BIG;
				float maxEimg  = 0, minEimg  = _CV_SNAKE_BIG;
				float maxEint  = 0, minEint  = _CV_SNAKE_BIG;
				float maxEarc  = 0, minEarc  = _CV_SNAKE_BIG;
				float maxEdux  = 0, minEdux  = _CV_SNAKE_BIG;
				float maxEduy  = 0, minEduy  = _CV_SNAKE_BIG;

				int offsetx = 0;
				int offsety = 0;
				float tmp, energy;
				int diffx, diffy;

				// compute bounds
				int left = MIN( ppt[i].x, win.width >> 1 );
				int right = MIN( roi.width - 1 - ppt[i].x, win.width >> 1 );
				int upper = MIN( ppt[i].y, win.height >> 1 );
				int bottom = MIN( roi.height - 1 - ppt[i].y, win.height >> 1 );

				// Calculate Econt
				if (!(alpha==0 || oalpha==0)){
					for( j = -upper; j <= bottom; j++ )
					{
						for( k = -left; k <= right; k++ )
						{
							if( i == 0 )
							{
								diffx = ppt[n - 1].x - (ppt[i].x + k);
								diffy = ppt[n - 1].y - (ppt[i].y + j);
							}
							else
							{
								diffx = ppt[i - 1].x - (ppt[i].x + k);
								diffy = ppt[i - 1].y - (ppt[i].y + j);
							}
							Econt[(j + centery) * win.width + k + centerx] = energy =
								(float) fabs( ave_d -
								cvSqrt( (float) (diffx * diffx + diffy * diffy) ));

							maxEcont = MAX( maxEcont, energy );
							minEcont = MIN( minEcont, energy );
						}
					}
					if(isoriginit){
						tmp = maxEcont - minEcont;
						tmp = (tmp == 0) ? 0 : (1 / tmp);
						for( k = 0; k < neighbors; k++ )
							Econt[k] = (Econt[k] - minEcont) * tmp;
						osEcont[i] = (oEcont[i] - minEcont)*tmp;
					}
				}
				//  Calculate Ecurv
				if (!(beta==0 || obeta==0)) {
					for( j = -upper; j <= bottom; j++ )
					{
						for( k = -left; k <= right; k++ )
						{
							int tx, ty;
							if( i == 0 )
							{
								tx = ppt[n - 1].x - 2 * (ppt[i].x + k) + ppt[i + 1].x;
								ty = ppt[n - 1].y - 2 * (ppt[i].y + j) + ppt[i + 1].y;
							}
							else if( i == n - 1 )
							{
								tx = ppt[i - 1].x - 2 * (ppt[i].x + k) + ppt[0].x;
								ty = ppt[i - 1].y - 2 * (ppt[i].y + j) + ppt[0].y;
							}
							else
							{
								tx = ppt[i - 1].x - 2 * (ppt[i].x + k) + ppt[i + 1].x;
								ty = ppt[i - 1].y - 2 * (ppt[i].y + j) + ppt[i + 1].y;
							}
							Ecurv[(j + centery) * win.width + k + centerx] = energy =
								(float) (tx * tx + ty * ty);
							maxEcurv = MAX( maxEcurv, energy );
							minEcurv = MIN( minEcurv, energy );
						}
					}
					if(isoriginit){
						tmp = maxEcurv - minEcurv;
						tmp = (tmp == 0) ? 0 : (1 / tmp);
						for( k = 0; k < neighbors; k++ )
							Ecurv[k] = (Ecurv[k] - minEcurv) * tmp;
						osEcurv[i] = (oEcurv[i] - minEcurv)*tmp;
					}
				}
				// Calculate Eimg
				if (!(gamma==0 || ogamma==0)) {
					for( j = -upper; j <= bottom; j++ )
					{
						for( k = -left; k <= right; k++ )
						{
							if( scheme == _CV_SNAKE_GRAD )
							{
								// look at map and check status 
								int x = (ppt[i].x + k)/WTILE_SIZE;
								int y = (ppt[i].y + j)/WTILE_SIZE;

								if( map[y * map_width + x] == 0 )
								{
									int l, m;

									// evaluate block location
									int upshift = y ? 1 : 0;
									int leftshift = x ? 1 : 0;
									int bottomshift = MIN( 1, roi.height - (y + 1)*WTILE_SIZE );
									int rightshift = MIN( 1, roi.width - (x + 1)*WTILE_SIZE );
									CvRect g_roi = { x*WTILE_SIZE - leftshift, y*WTILE_SIZE - upshift,
										leftshift + WTILE_SIZE + rightshift, upshift + WTILE_SIZE + bottomshift };
									CvMat _src1;
									cvGetSubArr( _srcp, &_src1, g_roi );

									pX.process( &_src1, &_dx );
									pY.process( &_src1, &_dy );

									for( l = 0; l < WTILE_SIZE + bottomshift; l++ )
									{
										for( m = 0; m < WTILE_SIZE + rightshift; m++ )
										{
											gradient[(y*WTILE_SIZE + l) * roi.width + x*WTILE_SIZE + m] =
												(float) (dx[(l + upshift) * TILE_SIZE + m + leftshift] *
												dx[(l + upshift) * TILE_SIZE + m + leftshift] +
												dy[(l + upshift) * TILE_SIZE + m + leftshift] *
												dy[(l + upshift) * TILE_SIZE + m + leftshift]);
										}
									}
									map[y * map_width + x] = 1;
								}
								Eimg[(j + centery) * win.width + k + centerx] = energy =
									gradient[(ppt[i].y + j) * roi.width + ppt[i].x + k];


							}
							else
								Eimg[(j + centery) * win.width + k + centerx] = energy =
									srcp[(ppt[i].y + j) * srcStep + ppt[i].x + k];
							maxEimg = MAX( maxEimg, energy );
							minEimg = MIN( minEimg, energy );
						}
					}
					if(isoriginit){
						tmp = (maxEimg - minEimg);
						tmp = (tmp == 0) ? 0 : (1 / tmp);
						for( k = 0; k < neighbors; k++ )
							Eimg[k] = (minEimg - Eimg[k]) * tmp;
						osEimg[i] = (minEimg - oEimg[i])*tmp;
					}
				}
				//  Calculate Eint
				if (oteta!=0) {
					for( j = -upper; j <= bottom; j++ )
					{
						for( k = -left; k <= right; k++ )
						{
							Eint[(j + centery) * win.width + k + centerx] = energy =
								srcp[(ppt[i].y + j) * srcStep + ppt[i].x + k];
							maxEint = MAX( maxEint, energy );
							minEint = MIN( minEint, energy );
						}
					}
					if (isoriginit){
						tmp = maxEint - minEint;
						tmp = (tmp == 0) ? 0 : (1 / tmp);
						for( k = 0; k < neighbors; k++ )
							Eint[k] = (Eint[k] - minEint) * tmp;
						osEint[i] = (oEint[i] - minEint)*tmp;
					}
				}
				//  Calculate Earc
				if (ozeta!=0) {
					for( j = -upper; j <= bottom; j++ )
					{
						for( k = -left; k <= right; k++ )
						{
							int diff2x,diff2y;

							if( i == 0 )
							{
								diffx = opt[n - 1].x - (ppt[i].x + k);
								diffy = opt[n - 1].y - (ppt[i].y + j);
							}
							else
							{
								diffx = opt[i - 1].x - (ppt[i].x + k);
								diffy = opt[i - 1].y - (ppt[i].y + j);
							}
							if( i == n-1 )
							{
								diff2x = opt[0].x - (ppt[i].x + k);
								diff2y = opt[0].y - (ppt[i].y + j);
							}
							else
							{
								diff2x = opt[i + 1].x - (ppt[i].x + k);
								diff2y = opt[i + 1].y - (ppt[i].y + j);
							}
							Earc[(j + centery) * win.width + k + centerx] = energy =
								cvSqrt( (float) (diffx * diffx + diffy * diffy) ) + cvSqrt( (float) (diff2x * diff2x + diff2y * diff2y) );

							maxEarc = MAX( maxEarc, energy );
							minEarc = MIN( minEarc, energy );
						}
					}
					if (isoriginit){
						tmp = maxEarc - minEarc;
						tmp = (tmp == 0) ? 0 : (1 / tmp);
						for( k = 0; k < neighbors; k++ )
							Earc[k] = (Earc[k] - minEarc) * tmp;
						osEarc[i] = (oEarc[i] - minEarc)*tmp;
					}
				}
				//  Calculate Edu-x/y gradients
				if (oomega!=0) {
					for( j = -upper; j <= bottom; j++ )
					{
						for( k = -left; k <= right; k++ )
						{
							float energyy;
							Edux[(j + centery) * win.width + k + centerx] = energy = (float)pdux->imageData[(ppt[i].y + j) * pdux->widthStep + ppt[i].x + k];
							Eduy[(j + centery) * win.width + k + centerx] = energyy = (float)pduy->imageData[(ppt[i].y + j) * pduy->widthStep + ppt[i].x + k];
							maxEdux = MAX( maxEdux, energy );
							minEdux = MIN( minEdux, energy );
							maxEduy = MAX( maxEduy, energyy );
							minEduy = MIN( minEduy, energyy );
						}
					}
					if (isoriginit){
						tmp = maxEdux - minEdux;
						tmp = (tmp == 0) ? 0 : (1 / tmp);
						for( k = 0; k < neighbors; k++ )
							Edux[k] = (Edux[k] - minEdux) * tmp;
						osEdux[i] = (oEdux[i] - minEdux)*tmp;
						tmp = maxEduy - minEduy;
						tmp = (tmp == 0) ? 0 : (1 / tmp);
						for( k = 0; k < neighbors; k++ )
							Eduy[k] = (Eduy[k] - minEduy) * tmp;
						osEduy[i] = (oEduy[i] - minEduy)*tmp;
					}
				}
				//---------------------- //end E calculations.

				int loci=centery*win.width+centerx;
				if (!isoriginit){
					//Initialize Original image parameters
					oEcont[i] = Econt[loci];
					oEcurv[i] = Ecurv[loci];
					oEimg[i] = Eimg[loci];
					oEint[i] = Eint[loci];
					if (oEarc_static){
						if (oEarc_static_ready)
							oEarc[i] = oEarc_static[i];
						else
							oEarc[i] = oEarc_static[i] = Earc[loci];
					}
					else
						oEarc[i] = Earc[loci];
					oEdux[i] = Edux[loci];
					oEduy[i] = Eduy[loci];
				}
				else{
					/* locate coefficients */
					if( coeffUsage != CV_VALUE)
					{
						_alpha = alpha[i];
						_beta = beta[i];
						_gamma = gamma[i];
						_oalpha = oalpha[i];
						_obeta = obeta[i];
						_ogamma = ogamma[i];
						_oteta = oteta[i];
						_ozeta = ozeta[i];
						_oomega = oomega[i];
					}

					/* Find Minimize point in the neighbors */
					for( k = 0; k < neighbors; k++ )
					{
						E[k] = _alpha * Econt[k] + _beta * Ecurv[k] + _gamma * Eimg[k]
						+ _oalpha*fabs(Econt[k]-osEcont[i])
						+ _obeta*fabs(Ecurv[k]-osEcurv[i])
						+ _ogamma*fabs(Eimg[k]-osEimg[i])
						+ _oteta*fabs(Eint[k]-osEint[i])
						+ _ozeta*fabs(Earc[k]-osEarc[i])
						+ _oomega*(fabs(Edux[k]-osEdux[i])+fabs(Eduy[k]-osEduy[i]))
						;
					}
//					Emin = _CV_SNAKE_BIG;
					Emin = E[loci];
					for( j = -upper; j <= bottom; j++ )
					{
						for( k = -left; k <= right; k++ )
						{

							if( E[(j + centery) * win.width + k + centerx] < Emin )// || (E[(j + centery) * win.width + k + centerx] == Emin && rand()%2))
							{
								Emin = E[(j + centery) * win.width + k + centerx];
								offsetx = k;
								offsety = j;
							}
						}
					}

					if( offsetx || offsety )
					{
						ppt[i].x += offsetx;
						ppt[i].y += offsety;
						moved++;
					}
				}//originit
				/*
				//Debugging: display gradient image
				float maxgrad=0;
				float mingrad=_CV_SNAKE_BIG;
				for(j=0; j<roi.width; j++){
					for(k=0; k<roi.height; k++){
						float grad=gradient[k*roi.width+j];
						if(grad<mingrad)
							mingrad=grad;
						if(grad>maxgrad)
							maxgrad=grad;
					}
				}
				IplImage *gray = cvCreateImage( cvSize(roi.width, roi.height), IPL_DEPTH_8U, 1 );
				tmp = (maxEimg - minEimg);
				tmp = (tmp == 0) ? 0 : (1 / tmp);
				for(j=0; j<roi.width; j++){
					for(k=0; k<roi.height; k++){
						float grad=gradient[k*roi.width+j];
						cvSetReal2D(gray,k,j,((grad-mingrad)*tmp*255));
					}
				}
				cvNamedWindow("tmp");
				cvShowImage("tmp",gray);
				cvReleaseImage(&gray);
				cvWaitKey(100);
				*/

			}//for n
			converged = (moved == 0);
			if( (criteria.type & CV_TERMCRIT_ITER) && (iteration >= criteria.max_iter) )
				converged = 1;
			if( (criteria.type & CV_TERMCRIT_EPS) && (moved <= criteria.epsilon) )
				converged = 1;
		}//while !converged
	}//for isoriginit
	cvFree( &E );
	cvFree( &Econt );
	cvFree( &oEcont );
	cvFree( &osEcont );
	cvFree( &Ecurv );
	cvFree( &oEcurv );
	cvFree( &osEcurv );
	cvFree( &Eimg );
	cvFree( &oEimg );
	cvFree( &osEimg );
	cvFree( &Eint );
	cvFree( &oEint );
	cvFree( &osEint );
	cvFree( &Earc );
	cvFree( &oEarc );
	cvFree( &osEarc );
	cvFree( &Edux );
	cvFree( &oEdux );
	cvFree( &osEdux );
	cvFree( &Eduy );
	cvFree( &oEduy );
	cvFree( &osEduy );


	if( scheme == _CV_SNAKE_GRAD )
	{
		cvFree( &gradient );
		cvFree( &map );
	}
	if(iterations) *iterations = iteration;
	return CV_OK;
}