Home | History | Annotate | Download | only in src
      1 /*M///////////////////////////////////////////////////////////////////////////////////////
      2 //
      3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      4 //
      5 //  By downloading, copying, installing or using the software you agree to this license.
      6 //  If you do not agree to this license, do not download, install,
      7 //  copy or use the software.
      8 //
      9 //
     10 //                        Intel License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
     14 // Third party copyrights are property of their respective owners.
     15 //
     16 // Redistribution and use in source and binary forms, with or without modification,
     17 // are permitted provided that the following conditions are met:
     18 //
     19 //   * Redistribution's of source code must retain the above copyright notice,
     20 //     this list of conditions and the following disclaimer.
     21 //
     22 //   * Redistribution's in binary form must reproduce the above copyright notice,
     23 //     this list of conditions and the following disclaimer in the documentation
     24 //     and/or other materials provided with the distribution.
     25 //
     26 //   * The name of Intel Corporation may not be used to endorse or promote products
     27 //     derived from this software without specific prior written permission.
     28 //
     29 // This software is provided by the copyright holders and contributors "as is" and
     30 // any express or implied warranties, including, but not limited to, the implied
     31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     32 // In no event shall the Intel Corporation or contributors be liable for any direct,
     33 // indirect, incidental, special, exemplary, or consequential damages
     34 // (including, but not limited to, procurement of substitute goods or services;
     35 // loss of use, data, or profits; or business interruption) however caused
     36 // and on any theory of liability, whether in contract, strict liability,
     37 // or tort (including negligence or otherwise) arising in any way out of
     38 // the use of this software, even if advised of the possibility of such damage.
     39 //
     40 //M*/
     41 #include "_cv.h"
     42 
     43 #define _CV_SNAKE_BIG 2.e+38f
     44 #define _CV_SNAKE_IMAGE 1
     45 #define _CV_SNAKE_GRAD  2
     46 
     47 
     48 /*F///////////////////////////////////////////////////////////////////////////////////////
     49 //    Name:      icvSnake8uC1R
     50 //    Purpose:
     51 //    Context:
     52 //    Parameters:
     53 //               src - source image,
     54 //               srcStep - its step in bytes,
     55 //               roi - size of ROI,
     56 //               pt - pointer to snake points array
     57 //               n - size of points array,
     58 //               alpha - pointer to coefficient of continuity energy,
     59 //               beta - pointer to coefficient of curvature energy,
     60 //               gamma - pointer to coefficient of image energy,
     61 //               coeffUsage - if CV_VALUE - alpha, beta, gamma point to single value
     62 //                            if CV_MATAY - point to arrays
     63 //               criteria - termination criteria.
     64 //               scheme - image energy scheme
     65 //                         if _CV_SNAKE_IMAGE - image intensity is energy
     66 //                         if _CV_SNAKE_GRAD  - magnitude of gradient is energy
     67 //    Returns:
     68 //F*/
     69 
     70 static CvStatus
     71 icvSnake8uC1R( unsigned char *src,
     72                int srcStep,
     73                CvSize roi,
     74                CvPoint * pt,
     75                int n,
     76                float *alpha,
     77                float *beta,
     78                float *gamma,
     79                int coeffUsage, CvSize win, CvTermCriteria criteria, int scheme )
     80 {
     81     int i, j, k;
     82     int neighbors = win.height * win.width;
     83 
     84     int centerx = win.width >> 1;
     85     int centery = win.height >> 1;
     86 
     87     float invn;
     88     int iteration = 0;
     89     int converged = 0;
     90 
     91 
     92     float *Econt;
     93     float *Ecurv;
     94     float *Eimg;
     95     float *E;
     96 
     97     float _alpha, _beta, _gamma;
     98 
     99     /*#ifdef GRAD_SNAKE */
    100     float *gradient = NULL;
    101     uchar *map = NULL;
    102     int map_width = ((roi.width - 1) >> 3) + 1;
    103     int map_height = ((roi.height - 1) >> 3) + 1;
    104     CvSepFilter pX, pY;
    105     #define WTILE_SIZE 8
    106     #define TILE_SIZE (WTILE_SIZE + 2)
    107     short dx[TILE_SIZE*TILE_SIZE], dy[TILE_SIZE*TILE_SIZE];
    108     CvMat _dx = cvMat( TILE_SIZE, TILE_SIZE, CV_16SC1, dx );
    109     CvMat _dy = cvMat( TILE_SIZE, TILE_SIZE, CV_16SC1, dy );
    110     CvMat _src = cvMat( roi.height, roi.width, CV_8UC1, src );
    111 
    112     /* inner buffer of convolution process */
    113     //char ConvBuffer[400];
    114 
    115     /*#endif */
    116 
    117 
    118     /* check bad arguments */
    119     if( src == NULL )
    120         return CV_NULLPTR_ERR;
    121     if( (roi.height <= 0) || (roi.width <= 0) )
    122         return CV_BADSIZE_ERR;
    123     if( srcStep < roi.width )
    124         return CV_BADSIZE_ERR;
    125     if( pt == NULL )
    126         return CV_NULLPTR_ERR;
    127     if( n < 3 )
    128         return CV_BADSIZE_ERR;
    129     if( alpha == NULL )
    130         return CV_NULLPTR_ERR;
    131     if( beta == NULL )
    132         return CV_NULLPTR_ERR;
    133     if( gamma == NULL )
    134         return CV_NULLPTR_ERR;
    135     if( coeffUsage != CV_VALUE && coeffUsage != CV_ARRAY )
    136         return CV_BADFLAG_ERR;
    137     if( (win.height <= 0) || (!(win.height & 1)))
    138         return CV_BADSIZE_ERR;
    139     if( (win.width <= 0) || (!(win.width & 1)))
    140         return CV_BADSIZE_ERR;
    141 
    142     invn = 1 / ((float) n);
    143 
    144     if( scheme == _CV_SNAKE_GRAD )
    145     {
    146         pX.init_deriv( TILE_SIZE+2, CV_8UC1, CV_16SC1, 1, 0, 3 );
    147         pY.init_deriv( TILE_SIZE+2, CV_8UC1, CV_16SC1, 0, 1, 3 );
    148 
    149         gradient = (float *) cvAlloc( roi.height * roi.width * sizeof( float ));
    150 
    151         if( !gradient )
    152             return CV_OUTOFMEM_ERR;
    153         map = (uchar *) cvAlloc( map_width * map_height );
    154         if( !map )
    155         {
    156             cvFree( &gradient );
    157             return CV_OUTOFMEM_ERR;
    158         }
    159         /* clear map - no gradient computed */
    160         memset( (void *) map, 0, map_width * map_height );
    161     }
    162     Econt = (float *) cvAlloc( neighbors * sizeof( float ));
    163     Ecurv = (float *) cvAlloc( neighbors * sizeof( float ));
    164     Eimg = (float *) cvAlloc( neighbors * sizeof( float ));
    165     E = (float *) cvAlloc( neighbors * sizeof( float ));
    166 
    167     while( !converged )
    168     {
    169         float ave_d = 0;
    170         int moved = 0;
    171 
    172         converged = 0;
    173         iteration++;
    174         /* compute average distance */
    175         for( i = 1; i < n; i++ )
    176         {
    177             int diffx = pt[i - 1].x - pt[i].x;
    178             int diffy = pt[i - 1].y - pt[i].y;
    179 
    180             ave_d += cvSqrt( (float) (diffx * diffx + diffy * diffy) );
    181         }
    182         ave_d += cvSqrt( (float) ((pt[0].x - pt[n - 1].x) *
    183                                   (pt[0].x - pt[n - 1].x) +
    184                                   (pt[0].y - pt[n - 1].y) * (pt[0].y - pt[n - 1].y)));
    185 
    186         ave_d *= invn;
    187         /* average distance computed */
    188         for( i = 0; i < n; i++ )
    189         {
    190             /* Calculate Econt */
    191             float maxEcont = 0;
    192             float maxEcurv = 0;
    193             float maxEimg = 0;
    194             float minEcont = _CV_SNAKE_BIG;
    195             float minEcurv = _CV_SNAKE_BIG;
    196             float minEimg = _CV_SNAKE_BIG;
    197             float Emin = _CV_SNAKE_BIG;
    198 
    199             int offsetx = 0;
    200             int offsety = 0;
    201             float tmp;
    202 
    203             /* compute bounds */
    204             int left = MIN( pt[i].x, win.width >> 1 );
    205             int right = MIN( roi.width - 1 - pt[i].x, win.width >> 1 );
    206             int upper = MIN( pt[i].y, win.height >> 1 );
    207             int bottom = MIN( roi.height - 1 - pt[i].y, win.height >> 1 );
    208 
    209             maxEcont = 0;
    210             minEcont = _CV_SNAKE_BIG;
    211             for( j = -upper; j <= bottom; j++ )
    212             {
    213                 for( k = -left; k <= right; k++ )
    214                 {
    215                     int diffx, diffy;
    216                     float energy;
    217 
    218                     if( i == 0 )
    219                     {
    220                         diffx = pt[n - 1].x - (pt[i].x + k);
    221                         diffy = pt[n - 1].y - (pt[i].y + j);
    222                     }
    223                     else
    224                     {
    225                         diffx = pt[i - 1].x - (pt[i].x + k);
    226                         diffy = pt[i - 1].y - (pt[i].y + j);
    227                     }
    228                     Econt[(j + centery) * win.width + k + centerx] = energy =
    229                         (float) fabs( ave_d -
    230                                       cvSqrt( (float) (diffx * diffx + diffy * diffy) ));
    231 
    232                     maxEcont = MAX( maxEcont, energy );
    233                     minEcont = MIN( minEcont, energy );
    234                 }
    235             }
    236             tmp = maxEcont - minEcont;
    237             tmp = (tmp == 0) ? 0 : (1 / tmp);
    238             for( k = 0; k < neighbors; k++ )
    239             {
    240                 Econt[k] = (Econt[k] - minEcont) * tmp;
    241             }
    242 
    243             /*  Calculate Ecurv */
    244             maxEcurv = 0;
    245             minEcurv = _CV_SNAKE_BIG;
    246             for( j = -upper; j <= bottom; j++ )
    247             {
    248                 for( k = -left; k <= right; k++ )
    249                 {
    250                     int tx, ty;
    251                     float energy;
    252 
    253                     if( i == 0 )
    254                     {
    255                         tx = pt[n - 1].x - 2 * (pt[i].x + k) + pt[i + 1].x;
    256                         ty = pt[n - 1].y - 2 * (pt[i].y + j) + pt[i + 1].y;
    257                     }
    258                     else if( i == n - 1 )
    259                     {
    260                         tx = pt[i - 1].x - 2 * (pt[i].x + k) + pt[0].x;
    261                         ty = pt[i - 1].y - 2 * (pt[i].y + j) + pt[0].y;
    262                     }
    263                     else
    264                     {
    265                         tx = pt[i - 1].x - 2 * (pt[i].x + k) + pt[i + 1].x;
    266                         ty = pt[i - 1].y - 2 * (pt[i].y + j) + pt[i + 1].y;
    267                     }
    268                     Ecurv[(j + centery) * win.width + k + centerx] = energy =
    269                         (float) (tx * tx + ty * ty);
    270                     maxEcurv = MAX( maxEcurv, energy );
    271                     minEcurv = MIN( minEcurv, energy );
    272                 }
    273             }
    274             tmp = maxEcurv - minEcurv;
    275             tmp = (tmp == 0) ? 0 : (1 / tmp);
    276             for( k = 0; k < neighbors; k++ )
    277             {
    278                 Ecurv[k] = (Ecurv[k] - minEcurv) * tmp;
    279             }
    280 
    281             /* Calculate Eimg */
    282             for( j = -upper; j <= bottom; j++ )
    283             {
    284                 for( k = -left; k <= right; k++ )
    285                 {
    286                     float energy;
    287 
    288                     if( scheme == _CV_SNAKE_GRAD )
    289                     {
    290                         /* look at map and check status */
    291                         int x = (pt[i].x + k)/WTILE_SIZE;
    292                         int y = (pt[i].y + j)/WTILE_SIZE;
    293 
    294                         if( map[y * map_width + x] == 0 )
    295                         {
    296                             int l, m;
    297 
    298                             /* evaluate block location */
    299                             int upshift = y ? 1 : 0;
    300                             int leftshift = x ? 1 : 0;
    301                             int bottomshift = MIN( 1, roi.height - (y + 1)*WTILE_SIZE );
    302                             int rightshift = MIN( 1, roi.width - (x + 1)*WTILE_SIZE );
    303                             CvRect g_roi = { x*WTILE_SIZE - leftshift, y*WTILE_SIZE - upshift,
    304                                 leftshift + WTILE_SIZE + rightshift, upshift + WTILE_SIZE + bottomshift };
    305                             CvMat _src1;
    306                             cvGetSubArr( &_src, &_src1, g_roi );
    307 
    308                             pX.process( &_src1, &_dx );
    309                             pY.process( &_src1, &_dy );
    310 
    311                             for( l = 0; l < WTILE_SIZE + bottomshift; l++ )
    312                             {
    313                                 for( m = 0; m < WTILE_SIZE + rightshift; m++ )
    314                                 {
    315                                     gradient[(y*WTILE_SIZE + l) * roi.width + x*WTILE_SIZE + m] =
    316                                         (float) (dx[(l + upshift) * TILE_SIZE + m + leftshift] *
    317                                                  dx[(l + upshift) * TILE_SIZE + m + leftshift] +
    318                                                  dy[(l + upshift) * TILE_SIZE + m + leftshift] *
    319                                                  dy[(l + upshift) * TILE_SIZE + m + leftshift]);
    320                                 }
    321                             }
    322                             map[y * map_width + x] = 1;
    323                         }
    324                         Eimg[(j + centery) * win.width + k + centerx] = energy =
    325                             gradient[(pt[i].y + j) * roi.width + pt[i].x + k];
    326                     }
    327                     else
    328                     {
    329                         Eimg[(j + centery) * win.width + k + centerx] = energy =
    330                             src[(pt[i].y + j) * srcStep + pt[i].x + k];
    331                     }
    332 
    333                     maxEimg = MAX( maxEimg, energy );
    334                     minEimg = MIN( minEimg, energy );
    335                 }
    336             }
    337 
    338             tmp = (maxEimg - minEimg);
    339             tmp = (tmp == 0) ? 0 : (1 / tmp);
    340 
    341             for( k = 0; k < neighbors; k++ )
    342             {
    343                 Eimg[k] = (minEimg - Eimg[k]) * tmp;
    344             }
    345 
    346             /* locate coefficients */
    347             if( coeffUsage == CV_VALUE)
    348             {
    349                 _alpha = *alpha;
    350                 _beta = *beta;
    351                 _gamma = *gamma;
    352             }
    353             else
    354             {
    355                 _alpha = alpha[i];
    356                 _beta = beta[i];
    357                 _gamma = gamma[i];
    358             }
    359 
    360             /* Find Minimize point in the neighbors */
    361             for( k = 0; k < neighbors; k++ )
    362             {
    363                 E[k] = _alpha * Econt[k] + _beta * Ecurv[k] + _gamma * Eimg[k];
    364             }
    365             Emin = _CV_SNAKE_BIG;
    366             for( j = -upper; j <= bottom; j++ )
    367             {
    368                 for( k = -left; k <= right; k++ )
    369                 {
    370 
    371                     if( E[(j + centery) * win.width + k + centerx] < Emin )
    372                     {
    373                         Emin = E[(j + centery) * win.width + k + centerx];
    374                         offsetx = k;
    375                         offsety = j;
    376                     }
    377                 }
    378             }
    379 
    380             if( offsetx || offsety )
    381             {
    382                 pt[i].x += offsetx;
    383                 pt[i].y += offsety;
    384                 moved++;
    385             }
    386         }
    387         converged = (moved == 0);
    388         if( (criteria.type & CV_TERMCRIT_ITER) && (iteration >= criteria.max_iter) )
    389             converged = 1;
    390         if( (criteria.type & CV_TERMCRIT_EPS) && (moved <= criteria.epsilon) )
    391             converged = 1;
    392     }
    393 
    394     cvFree( &Econt );
    395     cvFree( &Ecurv );
    396     cvFree( &Eimg );
    397     cvFree( &E );
    398 
    399     if( scheme == _CV_SNAKE_GRAD )
    400     {
    401         cvFree( &gradient );
    402         cvFree( &map );
    403     }
    404     return CV_OK;
    405 }
    406 
    407 
    408 CV_IMPL void
    409 cvSnakeImage( const IplImage* src, CvPoint* points,
    410               int length, float *alpha,
    411               float *beta, float *gamma,
    412               int coeffUsage, CvSize win,
    413               CvTermCriteria criteria, int calcGradient )
    414 {
    415 
    416     CV_FUNCNAME( "cvSnakeImage" );
    417 
    418     __BEGIN__;
    419 
    420     uchar *data;
    421     CvSize size;
    422     int step;
    423 
    424     if( src->nChannels != 1 )
    425         CV_ERROR( CV_BadNumChannels, "input image has more than one channel" );
    426 
    427     if( src->depth != IPL_DEPTH_8U )
    428         CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
    429 
    430     cvGetRawData( src, &data, &step, &size );
    431 
    432     IPPI_CALL( icvSnake8uC1R( data, step, size, points, length,
    433                               alpha, beta, gamma, coeffUsage, win, criteria,
    434                               calcGradient ? _CV_SNAKE_GRAD : _CV_SNAKE_IMAGE ));
    435     __END__;
    436 }
    437 
    438 /* end of file */
    439