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