| /*M/////////////////////////////////////////////////////////////////////////////////////// |
| // |
| // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. |
| // |
| // By downloading, copying, installing or using the software you agree to this license. |
| // If you do not agree to this license, do not download, install, |
| // copy or use the software. |
| // |
| // |
| // Intel License Agreement |
| // For Open Source Computer Vision Library |
| // |
| // Copyright (C) 2000, Intel Corporation, all rights reserved. |
| // Third party copyrights are property of their respective owners. |
| // |
| // Redistribution and use in source and binary forms, with or without modification, |
| // are permitted provided that the following conditions are met: |
| // |
| // * Redistribution's of source code must retain the above copyright notice, |
| // this list of conditions and the following disclaimer. |
| // |
| // * Redistribution's in binary form must reproduce the above copyright notice, |
| // this list of conditions and the following disclaimer in the documentation |
| // and/or other materials provided with the distribution. |
| // |
| // * The name of Intel Corporation may not be used to endorse or promote products |
| // derived from this software without specific prior written permission. |
| // |
| // This software is provided by the copyright holders and contributors "as is" and |
| // any express or implied warranties, including, but not limited to, the implied |
| // warranties of merchantability and fitness for a particular purpose are disclaimed. |
| // In no event shall the Intel Corporation or contributors be liable for any direct, |
| // indirect, incidental, special, exemplary, or consequential damages |
| // (including, but not limited to, procurement of substitute goods or services; |
| // loss of use, data, or profits; or business interruption) however caused |
| // and on any theory of liability, whether in contract, strict liability, |
| // or tort (including negligence or otherwise) arising in any way out of |
| // the use of this software, even if advised of the possibility of such damage. |
| // |
| //M*/ |
| #include "_cv.h" |
| |
| #define _CV_SNAKE_BIG 2.e+38f |
| #define _CV_SNAKE_IMAGE 1 |
| #define _CV_SNAKE_GRAD 2 |
| |
| |
| /*F/////////////////////////////////////////////////////////////////////////////////////// |
| // Name: icvSnake8uC1R |
| // Purpose: |
| // Context: |
| // Parameters: |
| // src - source image, |
| // srcStep - its step in bytes, |
| // roi - size of ROI, |
| // pt - pointer to snake points array |
| // n - size of points array, |
| // alpha - pointer to coefficient of continuity energy, |
| // beta - pointer to coefficient of curvature energy, |
| // gamma - pointer to coefficient of image energy, |
| // coeffUsage - if CV_VALUE - alpha, beta, gamma point to single value |
| // if CV_MATAY - point to arrays |
| // criteria - termination criteria. |
| // scheme - image energy scheme |
| // if _CV_SNAKE_IMAGE - image intensity is energy |
| // if _CV_SNAKE_GRAD - magnitude of gradient is energy |
| // Returns: |
| //F*/ |
| |
| 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; |
| } |
| |
| |
| CV_IMPL void |
| cvSnakeImage( const IplImage* src, CvPoint* points, |
| int length, float *alpha, |
| float *beta, float *gamma, |
| int coeffUsage, CvSize win, |
| CvTermCriteria criteria, int calcGradient ) |
| { |
| |
| CV_FUNCNAME( "cvSnakeImage" ); |
| |
| __BEGIN__; |
| |
| uchar *data; |
| CvSize size; |
| int step; |
| |
| if( src->nChannels != 1 ) |
| CV_ERROR( CV_BadNumChannels, "input image has more than one channel" ); |
| |
| if( src->depth != IPL_DEPTH_8U ) |
| CV_ERROR( CV_BadDepth, cvUnsupportedFormat ); |
| |
| cvGetRawData( src, &data, &step, &size ); |
| |
| IPPI_CALL( icvSnake8uC1R( data, step, size, points, length, |
| alpha, beta, gamma, coeffUsage, win, criteria, |
| calcGradient ? _CV_SNAKE_GRAD : _CV_SNAKE_IMAGE )); |
| __END__; |
| } |
| |
| /* end of file */ |