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 typedef struct _CvRGBf 44 { float blue; 45 float green; 46 float red; 47 } 48 _CvRGBf; 49 50 typedef struct _CvRect16u 51 { 52 ushort x1, y1, x2, y2; 53 } 54 _CvRect16u; 55 56 typedef struct _CvPyramid 57 { 58 float c; 59 struct _CvPyramid *p; 60 int a; 61 _CvRect16u rect; /* ROI for the connected component */ 62 } _CvPyramid; 63 64 /* element of base layer */ 65 typedef struct _CvPyramidBase 66 { 67 float c; 68 struct _CvPyramid *p; 69 } 70 _CvPyramidBase; 71 72 typedef struct _CvPyramidC3 73 { 74 _CvRGBf c; 75 struct _CvPyramidC3 *p; 76 int a; 77 _CvRect16u rect; /* ROI for the connected component */ 78 } _CvPyramidC3; 79 80 /* element of base layer */ 81 typedef struct _CvPyramidBaseC3 82 { 83 _CvRGBf c; 84 struct _CvPyramidC3 *p; 85 } 86 _CvPyramidBaseC3; 87 88 typedef struct _CvListNode 89 { 90 struct _CvListNode* next; 91 void* data; 92 } 93 _CvListNode; 94 95 96 static CvStatus icvSegmentClusterC1( CvSeq* cmp_seq, CvSeq* res_seq, 97 double threshold, 98 _CvPyramid* first_level_end, 99 CvSize first_level_size ); 100 101 static CvStatus icvSegmentClusterC3( CvSeq* cmp_seq, CvSeq* res_seq, 102 double threshold, 103 _CvPyramidC3* first_level_end, 104 CvSize first_level_size ); 105 106 static CvStatus icvUpdatePyrLinks_8u_C1 107 (int layer, void *layer_data, CvSize size, void *parent_layer, 108 void *_writer, float threshold, int is_last_iter, void *_stub, CvWriteNodeFunction /*func*/); 109 110 static CvStatus icvUpdatePyrLinks_8u_C3 111 (int layer, void *layer_data, CvSize size, void *parent_layer, 112 void *_writer, float threshold, int is_last_iter, void *_stub, CvWriteNodeFunction /*func*/); 113 114 static void icvMaxRoi( _CvRect16u *max_rect, _CvRect16u* cur_rect ); 115 static void icvMaxRoi1( _CvRect16u *max_rect, int x, int y ); 116 117 118 #define _CV_CHECK( icvFun ) \ 119 { \ 120 if( icvFun != CV_OK ) \ 121 goto M_END; \ 122 } 123 124 125 #define _CV_MAX3( a, b, c) ((a)>(b) ? ((a)>(c) ? (a) : (c)) : ((b)>(c) ? (b) : (c))) 126 127 /*#define _CV_RGB_DIST(a, b) _CV_MAX3((float)fabs((a).red - (b).red), \ 128 (float)fabs((a).green - (b).green), \ 129 (float)fabs((a).blue - (b).blue))*/ 130 131 #define _CV_NEXT_BASE_C1(p,n) (_CvPyramid*)((char*)(p) + (n)*sizeof(_CvPyramidBase)) 132 #define _CV_NEXT_BASE_C3(p,n) (_CvPyramidC3*)((char*)(p) + (n)*sizeof(_CvPyramidBaseC3)) 133 134 135 CV_INLINE float icvRGBDist_Max( const _CvRGBf& a, const _CvRGBf& b ) 136 { 137 float tr = (float)fabs(a.red - b.red); 138 float tg = (float)fabs(a.green - b.green); 139 float tb = (float)fabs(a.blue - b.blue); 140 141 return _CV_MAX3( tr, tg, tb ); 142 } 143 144 CV_INLINE float icvRGBDist_Sum( const _CvRGBf& a, const _CvRGBf& b ) 145 { 146 float tr = (float)fabs(a.red - b.red); 147 float tg = (float)fabs(a.green - b.green); 148 float tb = (float)fabs(a.blue - b.blue); 149 150 return (tr + tg + tb); 151 } 152 153 #if 1 154 #define _CV_RGB_DIST icvRGBDist_Max 155 #define _CV_RGB_THRESH_SCALE 1 156 #else 157 #define _CV_RGB_DIST icvRGBDist_Sum 158 #define _CV_RGB_THRESH_SCALE 3 159 #endif 160 161 #define _CV_INV_TAB_SIZE 32 162 163 static const float icvInvTab[ /*_CV_INV_TAB_SIZE*/ ] = 164 { 165 1.00000000f, 0.50000000f, 0.33333333f, 0.25000000f, 0.20000000f, 0.16666667f, 166 0.14285714f, 0.12500000f, 0.11111111f, 0.10000000f, 0.09090909f, 0.08333333f, 167 0.07692308f, 0.07142857f, 0.06666667f, 0.06250000f, 0.05882353f, 0.05555556f, 168 0.05263158f, 0.05000000f, 0.04761905f, 0.04545455f, 0.04347826f, 0.04166667f, 169 0.04000000f, 0.03846154f, 0.03703704f, 0.03571429f, 0.03448276f, 0.03333333f, 170 0.03225806f, 0.03125000f 171 }; 172 173 static void 174 icvWritePyrNode( void *elem, void *writer ) 175 { 176 CV_WRITE_SEQ_ELEM( *(_CvListNode *) elem, *(CvSeqWriter *) writer ); 177 } 178 179 180 static CvStatus 181 icvPyrSegmentation8uC1R( uchar * src_image, int src_step, 182 uchar * dst_image, int dst_step, 183 CvSize roi, CvFilter filter, 184 CvSeq ** dst_comp, CvMemStorage * storage, 185 int level, int threshold1, int threshold2 ) 186 { 187 int i, j, l; 188 int step; 189 const int max_iter = 3; /* maximum number of iterations */ 190 int cur_iter = 0; /* current iteration */ 191 192 _CvPyramid *pyram[16]; /* pointers to the pyramid down up to level */ 193 194 float *pyramida = 0; 195 _CvPyramid stub; 196 197 _CvPyramid *p_cur; 198 _CvPyramidBase *p_base; 199 _CvListNode cmp_node; 200 201 CvSeq *cmp_seq = 0; 202 CvSeq *res_seq = 0; 203 CvMemStorage *temp_storage = 0; 204 CvSize size; 205 CvStatus status; 206 CvSeqWriter writer; 207 208 int buffer_size; 209 char *buffer = 0; 210 211 status = CV_OK; 212 213 /* clear pointer to resultant sequence */ 214 if( dst_comp ) 215 *dst_comp = 0; 216 217 /* check args */ 218 if( !src_image || !dst_image || !storage || !dst_comp ) 219 return CV_NULLPTR_ERR; 220 if( roi.width <= 0 || roi.height <= 0 || src_step < roi.width || dst_step < roi.width ) 221 return CV_BADSIZE_ERR; 222 if( filter != CV_GAUSSIAN_5x5 ) 223 return CV_BADRANGE_ERR; 224 if( threshold1 < 0 || threshold2 < 0 ) 225 return CV_BADRANGE_ERR; 226 if( level <= 0 ) 227 return CV_BADRANGE_ERR; 228 229 if( ((roi.width | roi.height) & ((1 << level) - 1)) != 0 ) 230 return CV_BADCOEF_ERR; 231 232 temp_storage = cvCreateChildMemStorage( storage ); 233 234 /* sequence for temporary components */ 235 cmp_seq = cvCreateSeq( 0, sizeof( CvSeq ), sizeof( _CvListNode ), temp_storage ); 236 assert( cmp_seq != 0 ); 237 238 res_seq = cvCreateSeq( CV_SEQ_CONNECTED_COMP, sizeof( CvSeq ), 239 sizeof( CvConnectedComp ), storage ); 240 assert( res_seq != 0 ); 241 242 /* calculate buffer size */ 243 buffer_size = roi.width * roi.height * (sizeof( float ) + sizeof( _CvPyramidBase )); 244 245 for( l = 1; l <= level; l++ ) 246 buffer_size += ((roi.width >> l) + 1) * ((roi.height >> l) + 1) * sizeof(_CvPyramid); 247 248 /* allocate buffer */ 249 buffer = (char *) cvAlloc( buffer_size ); 250 if( !buffer ) 251 { 252 status = CV_OUTOFMEM_ERR; 253 goto M_END; 254 } 255 256 pyramida = (float *) buffer; 257 258 /* initialization pyramid-linking properties down up to level */ 259 step = roi.width * sizeof( float ); 260 261 { 262 CvMat _src; 263 CvMat _pyramida; 264 cvInitMatHeader( &_src, roi.height, roi.width, CV_8UC1, src_image, src_step ); 265 cvInitMatHeader( &_pyramida, roi.height, roi.width, CV_32FC1, pyramida, step ); 266 cvConvert( &_src, &_pyramida ); 267 /*_CV_CHECK( icvCvtTo_32f_C1R( src_image, src_step, pyramida, step, roi, CV_8UC1 ));*/ 268 } 269 p_base = (_CvPyramidBase *) (buffer + step * roi.height); 270 pyram[0] = (_CvPyramid *) p_base; 271 272 /* fill base level of pyramid */ 273 for( i = 0; i < roi.height; i++ ) 274 { 275 for( j = 0; j < roi.width; j++, p_base++ ) 276 { 277 p_base->c = pyramida[i * roi.width + j]; 278 p_base->p = &stub; 279 } 280 } 281 282 p_cur = (_CvPyramid *) p_base; 283 size = roi; 284 285 /* calculate initial pyramid */ 286 for( l = 1; l <= level; l++ ) 287 { 288 CvSize dst_size = { size.width/2+1, size.height/2+1 }; 289 CvMat prev_level = cvMat( size.height, size.width, CV_32FC1 ); 290 CvMat next_level = cvMat( dst_size.height, dst_size.width, CV_32FC1 ); 291 292 cvSetData( &prev_level, pyramida, step ); 293 cvSetData( &next_level, pyramida, step ); 294 cvPyrDown( &prev_level, &next_level ); 295 296 //_CV_CHECK( icvPyrDown_Gauss5x5_32f_C1R( pyramida, step, pyramida, step, size, buff )); 297 //_CV_CHECK( icvPyrDownBorder_32f_CnR( pyramida, step, size, pyramida, step, dst_size, 1 )); 298 pyram[l] = p_cur; 299 300 size.width = dst_size.width - 1; 301 size.height = dst_size.height - 1; 302 303 /* fill layer #l */ 304 for( i = 0; i <= size.height; i++ ) 305 { 306 for( j = 0; j <= size.width; j++, p_cur++ ) 307 { 308 p_cur->c = pyramida[i * roi.width + j]; 309 p_cur->p = &stub; 310 p_cur->a = 0; 311 p_cur->rect.x2 = 0; 312 } 313 } 314 } 315 316 cvStartAppendToSeq( cmp_seq, &writer ); 317 318 /* do several iterations to determine son-father links */ 319 for( cur_iter = 0; cur_iter < max_iter; cur_iter++ ) 320 { 321 int is_last_iter = cur_iter == max_iter - 1; 322 323 size = roi; 324 325 /* build son-father links down up to level */ 326 for( l = 0; l < level; l++ ) 327 { 328 icvUpdatePyrLinks_8u_C1( l, pyram[l], size, pyram[l + 1], &writer, 329 (float) threshold1, is_last_iter, &stub, 330 icvWritePyrNode ); 331 332 /* clear last border row */ 333 if( l > 0 ) 334 { 335 p_cur = pyram[l] + (size.width + 1) * size.height; 336 for( j = 0; j <= size.width; j++ ) 337 p_cur[j].c = 0; 338 } 339 340 size.width >>= 1; 341 size.height >>= 1; 342 } 343 344 /* clear the old c value for the last level */ 345 p_cur = pyram[level]; 346 for( i = 0; i <= size.height; i++, p_cur += size.width + 1 ) 347 for( j = 0; j <= size.width; j++ ) 348 p_cur[j].c = 0; 349 350 size = roi; 351 step = roi.width; 352 353 /* calculate average c value for the 0 < l <=level */ 354 for( l = 0; l < level; l++, step = (step >> 1) + 1 ) 355 { 356 _CvPyramid *p_prev, *p_row_prev; 357 358 stub.c = 0; 359 360 /* calculate average c value for the next level */ 361 if( l == 0 ) 362 { 363 p_base = (_CvPyramidBase *) pyram[0]; 364 for( i = 0; i < roi.height; i++, p_base += size.width ) 365 { 366 for( j = 0; j < size.width; j += 2 ) 367 { 368 _CvPyramid *p1 = p_base[j].p; 369 _CvPyramid *p2 = p_base[j + 1].p; 370 371 p1->c += p_base[j].c; 372 p2->c += p_base[j + 1].c; 373 } 374 } 375 } 376 else 377 { 378 p_cur = pyram[l]; 379 for( i = 0; i < size.height; i++, p_cur += size.width + 1 ) 380 { 381 for( j = 0; j < size.width; j += 2 ) 382 { 383 _CvPyramid *p1 = p_cur[j].p; 384 _CvPyramid *p2 = p_cur[j + 1].p; 385 386 float t0 = (float) p_cur[j].a * p_cur[j].c; 387 float t1 = (float) p_cur[j + 1].a * p_cur[j + 1].c; 388 389 p1->c += t0; 390 p2->c += t1; 391 392 if( !is_last_iter ) 393 p_cur[j].a = p_cur[j + 1].a = 0; 394 } 395 if( !is_last_iter ) 396 p_cur[size.width].a = 0; 397 } 398 if( !is_last_iter ) 399 { 400 for( j = 0; j <= size.width; j++ ) 401 { 402 p_cur[j].a = 0; 403 } 404 } 405 } 406 407 /* assign random values of the next level null c */ 408 p_cur = pyram[l + 1]; 409 p_row_prev = p_prev = pyram[l]; 410 411 size.width >>= 1; 412 size.height >>= 1; 413 414 for( i = 0; i <= size.height; i++, p_cur += size.width + 1 ) 415 { 416 if( i < size.height || !is_last_iter ) 417 { 418 for( j = 0; j < size.width; j++ ) 419 { 420 int a = p_cur[j].a; 421 422 if( a != 0 ) 423 { 424 if( a <= _CV_INV_TAB_SIZE ) 425 { 426 p_cur[j].c *= icvInvTab[a - 1]; 427 } 428 else 429 { 430 p_cur[j].c /= a; 431 } 432 } 433 else 434 { 435 p_cur[j].c = p_prev->c; 436 } 437 438 if( l == 0 ) 439 p_prev = _CV_NEXT_BASE_C1(p_prev,2); 440 else 441 p_prev += 2; 442 } 443 444 if( p_cur[size.width].a == 0 ) 445 { 446 p_cur[size.width].c = p_prev[(l != 0) - 1].c; 447 } 448 else 449 { 450 p_cur[size.width].c /= p_cur[size.width].a; 451 if( is_last_iter ) 452 { 453 cmp_node.data = p_cur + size.width; 454 CV_WRITE_SEQ_ELEM( cmp_node, writer ); 455 } 456 } 457 } 458 else 459 { 460 for( j = 0; j <= size.width; j++ ) 461 { 462 int a = p_cur[j].a; 463 464 if( a != 0 ) 465 { 466 if( a <= _CV_INV_TAB_SIZE ) 467 { 468 p_cur[j].c *= icvInvTab[a - 1]; 469 } 470 else 471 { 472 p_cur[j].c /= a; 473 } 474 475 cmp_node.data = p_cur + j; 476 CV_WRITE_SEQ_ELEM( cmp_node, writer ); 477 } 478 else 479 { 480 p_cur[j].c = p_prev->c; 481 } 482 483 if( l == 0 ) 484 { 485 p_prev = _CV_NEXT_BASE_C1(p_prev, (j * 2 < step - 2 ? 2 : 1)); 486 } 487 else 488 { 489 p_prev++; 490 } 491 } 492 } 493 494 if( l + 1 == level && !is_last_iter ) 495 for( j = 0; j <= size.width; j++ ) 496 p_cur[j].a = 0; 497 498 if( !(i & 1) ) 499 { 500 p_prev = p_row_prev; 501 } 502 else 503 { 504 p_prev = (_CvPyramid*)((char*)p_row_prev + step * 505 (l == 0 ? sizeof(_CvPyramidBase) : sizeof(_CvPyramid))); 506 } 507 } 508 } 509 } /* end of the iteration process */ 510 511 /* construct a connected components */ 512 size.width = roi.width >> level; 513 size.height = roi.height >> level; 514 515 p_cur = pyram[level]; 516 517 for( i = 0; i < size.height; i++, p_cur += size.width + 1 ) 518 { 519 for( j = 0; j < size.width; j++ ) 520 { 521 if( p_cur[j].a != 0 ) 522 { 523 cmp_node.data = p_cur + j; 524 CV_WRITE_SEQ_ELEM( cmp_node, writer ); 525 } 526 } 527 } 528 529 cvEndWriteSeq( &writer ); 530 531 /* clusterization segmented components and construction 532 output connected components */ 533 icvSegmentClusterC1( cmp_seq, res_seq, threshold2, pyram[1], roi ); 534 535 /* convert (inplace) resultant segment values to int (top level) */ 536 537 /* propagate segment values top down */ 538 for( l = level - 1; l >= 0; l-- ) 539 { 540 p_cur = pyram[l]; 541 542 size.width <<= 1; 543 size.height <<= 1; 544 545 if( l == 0 ) 546 { 547 size.width--; 548 size.height--; 549 } 550 551 for( i = 0; i <= size.height; i++ ) 552 { 553 for( j = 0; j <= size.width; j++ ) 554 { 555 _CvPyramid *p = p_cur->p; 556 557 assert( p != 0 ); 558 if( p != &stub ) 559 p_cur->c = p->c; 560 561 if( l == 0 ) 562 { 563 Cv32suf _c; 564 /* copy the segmented values to destination image */ 565 _c.f = p_cur->c; dst_image[j] = (uchar)_c.i; 566 p_cur = _CV_NEXT_BASE_C1(p_cur, 1); 567 } 568 else 569 { 570 p_cur++; 571 } 572 } 573 if( l == 0 ) 574 dst_image += dst_step; 575 } 576 } 577 M_END: 578 579 cvFree( &buffer ); 580 cvReleaseMemStorage( &temp_storage ); 581 582 if( status == CV_OK ) 583 *dst_comp = res_seq; 584 585 return status; 586 } 587 588 589 590 /****************************************************************************************\ 591 color!!! image segmentation by pyramid-linking 592 \****************************************************************************************/ 593 static CvStatus 594 icvPyrSegmentation8uC3R( uchar * src_image, int src_step, 595 uchar * dst_image, int dst_step, 596 CvSize roi, CvFilter filter, 597 CvSeq ** dst_comp, CvMemStorage * storage, 598 int level, int threshold1, int threshold2 ) 599 { 600 int i, j, l; 601 602 int step; 603 const int max_iter = 3; /* maximum number of iterations */ 604 int cur_iter = 0; /* current iteration */ 605 606 _CvPyramidC3 *pyram[16]; /* pointers to the pyramid down up to level */ 607 608 float *pyramida = 0; 609 _CvPyramidC3 stub; 610 611 _CvPyramidC3 *p_cur; 612 _CvPyramidBaseC3 *p_base; 613 _CvListNode cmp_node; 614 615 CvSeq *cmp_seq = 0; 616 CvSeq *res_seq = 0; 617 CvMemStorage *temp_storage = 0; 618 CvSize size; 619 CvStatus status; 620 CvSeqWriter writer; 621 622 int buffer_size; 623 char *buffer = 0; 624 625 status = CV_OK; 626 627 threshold1 *= _CV_RGB_THRESH_SCALE; 628 threshold2 *= _CV_RGB_THRESH_SCALE; 629 630 /* clear pointer to resultant sequence */ 631 if( dst_comp ) 632 *dst_comp = 0; 633 634 /* check args */ 635 if( !src_image || !dst_image || !storage || !dst_comp ) 636 return CV_NULLPTR_ERR; 637 if( roi.width <= 0 || roi.height <= 0 || 638 src_step < roi.width * 3 || dst_step < roi.width * 3 ) return CV_BADSIZE_ERR; 639 if( filter != CV_GAUSSIAN_5x5 ) 640 return CV_BADRANGE_ERR; 641 if( threshold1 < 0 || threshold2 < 0 ) 642 return CV_BADRANGE_ERR; 643 if( level <= 0 ) 644 return CV_BADRANGE_ERR; 645 646 if( ((roi.width | roi.height) & ((1 << level) - 1)) != 0 ) 647 return CV_BADCOEF_ERR; 648 649 temp_storage = cvCreateChildMemStorage( storage ); 650 651 /* sequence for temporary components */ 652 cmp_seq = cvCreateSeq( 0, sizeof( CvSeq ), sizeof( _CvListNode ), temp_storage ); 653 assert( cmp_seq != 0 ); 654 655 res_seq = cvCreateSeq( CV_SEQ_CONNECTED_COMP, sizeof( CvSeq ), 656 sizeof( CvConnectedComp ), storage ); 657 assert( res_seq != 0 ); 658 659 /* calculate buffer size */ 660 buffer_size = roi.width * roi.height * (sizeof( _CvRGBf ) + sizeof( _CvPyramidBaseC3 )); 661 662 for( l = 1; l <= level; l++ ) 663 buffer_size += ((roi.width >> l) + 1) * ((roi.height >> l) + 1) * sizeof(_CvPyramidC3); 664 665 /* allocate buffer */ 666 buffer = (char *) cvAlloc( buffer_size ); 667 if( !buffer ) 668 { 669 status = CV_OUTOFMEM_ERR; 670 goto M_END; 671 } 672 673 pyramida = (float *) buffer; 674 675 /* initialization pyramid-linking properties down up to level */ 676 step = roi.width * sizeof( _CvRGBf ); 677 678 { 679 CvMat _src; 680 CvMat _pyramida; 681 cvInitMatHeader( &_src, roi.height, roi.width, CV_8UC3, src_image, src_step ); 682 cvInitMatHeader( &_pyramida, roi.height, roi.width, CV_32FC3, pyramida, step ); 683 cvConvert( &_src, &_pyramida ); 684 /*_CV_CHECK( icvCvtTo_32f_C1R( src_image, src_step, pyramida, step, 685 cvSize( roi.width * 3, roi.height ), CV_8UC1 ));*/ 686 } 687 688 p_base = (_CvPyramidBaseC3 *) (buffer + step * roi.height); 689 pyram[0] = (_CvPyramidC3 *) p_base; 690 691 /* fill base level of pyramid */ 692 for( i = 0; i < roi.height; i++ ) 693 { 694 for( j = 0; j < roi.width; j++, p_base++ ) 695 { 696 p_base->c = ((_CvRGBf *) pyramida)[i * roi.width + j]; 697 p_base->p = &stub; 698 } 699 } 700 701 p_cur = (_CvPyramidC3 *) p_base; 702 size = roi; 703 704 /* calculate initial pyramid */ 705 for( l = 1; l <= level; l++ ) 706 { 707 CvSize dst_size = { size.width/2 + 1, size.height/2 + 1 }; 708 CvMat prev_level = cvMat( size.height, size.width, CV_32FC3 ); 709 CvMat next_level = cvMat( dst_size.height, dst_size.width, CV_32FC3 ); 710 711 cvSetData( &prev_level, pyramida, step ); 712 cvSetData( &next_level, pyramida, step ); 713 cvPyrDown( &prev_level, &next_level ); 714 715 //_CV_CHECK( icvPyrDown_Gauss5x5_32f_C3R( pyramida, step, pyramida, step, size, buff )); 716 //_CV_CHECK( icvPyrDownBorder_32f_CnR( pyramida, step, size, pyramida, step, dst_size, 3 )); 717 pyram[l] = p_cur; 718 719 size.width = dst_size.width - 1; 720 size.height = dst_size.height - 1; 721 722 /* fill layer #l */ 723 for( i = 0; i <= size.height; i++ ) 724 { 725 assert( (char*)p_cur - buffer < buffer_size ); 726 for( j = 0; j <= size.width; j++, p_cur++ ) 727 { 728 p_cur->c = ((_CvRGBf *) pyramida)[i * roi.width + j]; 729 p_cur->p = &stub; 730 p_cur->a = 0; 731 p_cur->rect.x2 = 0; 732 } 733 } 734 } 735 736 cvStartAppendToSeq( cmp_seq, &writer ); 737 738 /* do several iterations to determine son-father links */ 739 for( cur_iter = 0; cur_iter < max_iter; cur_iter++ ) 740 { 741 int is_last_iter = cur_iter == max_iter - 1; 742 743 size = roi; 744 745 /* build son-father links down up to level */ 746 for( l = 0; l < level; l++ ) 747 { 748 icvUpdatePyrLinks_8u_C3( l, pyram[l], size, pyram[l + 1], &writer, 749 (float) threshold1, is_last_iter, &stub, 750 icvWritePyrNode ); 751 752 /* clear last border row */ 753 if( l > 0 ) 754 { 755 p_cur = pyram[l] + (size.width + 1) * size.height; 756 for( j = 0; j <= size.width; j++ ) 757 p_cur[j].c.blue = p_cur[j].c.green = p_cur[j].c.red = 0; 758 } 759 760 size.width >>= 1; 761 size.height >>= 1; 762 } 763 764 /* clear the old c value for the last level */ 765 p_cur = pyram[level]; 766 for( i = 0; i <= size.height; i++, p_cur += size.width + 1 ) 767 for( j = 0; j <= size.width; j++ ) 768 p_cur[j].c.blue = p_cur[j].c.green = p_cur[j].c.red = 0; 769 770 size = roi; 771 step = roi.width; 772 773 /* calculate average c value for the 0 < l <=level */ 774 for( l = 0; l < level; l++, step = (step >> 1) + 1 ) 775 { 776 _CvPyramidC3 *p_prev, *p_row_prev; 777 778 stub.c.blue = stub.c.green = stub.c.red = 0; 779 780 /* calculate average c value for the next level */ 781 if( l == 0 ) 782 { 783 p_base = (_CvPyramidBaseC3 *) pyram[0]; 784 for( i = 0; i < roi.height; i++, p_base += size.width ) 785 { 786 for( j = 0; j < size.width; j++ ) 787 { 788 _CvPyramidC3 *p = p_base[j].p; 789 790 p->c.blue += p_base[j].c.blue; 791 p->c.green += p_base[j].c.green; 792 p->c.red += p_base[j].c.red; 793 } 794 } 795 } 796 else 797 { 798 p_cur = pyram[l]; 799 for( i = 0; i < size.height; i++, p_cur += size.width + 1 ) 800 { 801 for( j = 0; j < size.width; j++ ) 802 { 803 _CvPyramidC3 *p = p_cur[j].p; 804 float a = (float) p_cur[j].a; 805 806 p->c.blue += a * p_cur[j].c.blue; 807 p->c.green += a * p_cur[j].c.green; 808 p->c.red += a * p_cur[j].c.red; 809 810 if( !is_last_iter ) 811 p_cur[j].a = 0; 812 } 813 if( !is_last_iter ) 814 p_cur[size.width].a = 0; 815 } 816 if( !is_last_iter ) 817 { 818 for( j = 0; j <= size.width; j++ ) 819 { 820 p_cur[j].a = 0; 821 } 822 } 823 } 824 825 /* assign random values of the next level null c */ 826 p_cur = pyram[l + 1]; 827 p_row_prev = p_prev = pyram[l]; 828 829 size.width >>= 1; 830 size.height >>= 1; 831 832 for( i = 0; i <= size.height; i++, p_cur += size.width + 1 ) 833 { 834 if( i < size.height || !is_last_iter ) 835 { 836 for( j = 0; j < size.width; j++ ) 837 { 838 int a = p_cur[j].a; 839 840 if( a != 0 ) 841 { 842 float inv_a; 843 844 if( a <= _CV_INV_TAB_SIZE ) 845 { 846 inv_a = icvInvTab[a - 1]; 847 } 848 else 849 { 850 inv_a = 1.f / a; 851 } 852 p_cur[j].c.blue *= inv_a; 853 p_cur[j].c.green *= inv_a; 854 p_cur[j].c.red *= inv_a; 855 } 856 else 857 { 858 p_cur[j].c = p_prev->c; 859 } 860 861 if( l == 0 ) 862 p_prev = _CV_NEXT_BASE_C3( p_prev, 2 ); 863 else 864 p_prev += 2; 865 } 866 867 if( p_cur[size.width].a == 0 ) 868 { 869 p_cur[size.width].c = p_prev[(l != 0) - 1].c; 870 } 871 else 872 { 873 p_cur[size.width].c.blue /= p_cur[size.width].a; 874 p_cur[size.width].c.green /= p_cur[size.width].a; 875 p_cur[size.width].c.red /= p_cur[size.width].a; 876 if( is_last_iter ) 877 { 878 cmp_node.data = p_cur + size.width; 879 CV_WRITE_SEQ_ELEM( cmp_node, writer ); 880 } 881 } 882 } 883 else 884 { 885 for( j = 0; j <= size.width; j++ ) 886 { 887 int a = p_cur[j].a; 888 889 if( a != 0 ) 890 { 891 float inv_a; 892 893 if( a <= _CV_INV_TAB_SIZE ) 894 { 895 inv_a = icvInvTab[a - 1]; 896 } 897 else 898 { 899 inv_a = 1.f / a; 900 } 901 p_cur[j].c.blue *= inv_a; 902 p_cur[j].c.green *= inv_a; 903 p_cur[j].c.red *= inv_a; 904 905 cmp_node.data = p_cur + j; 906 CV_WRITE_SEQ_ELEM( cmp_node, writer ); 907 } 908 else 909 { 910 p_cur[j].c = p_prev->c; 911 } 912 913 if( l == 0 ) 914 { 915 p_prev = _CV_NEXT_BASE_C3( p_prev, (j * 2 < step - 2 ? 2 : 1)); 916 } 917 else 918 { 919 p_prev++; 920 } 921 } 922 } 923 924 if( l + 1 == level && !is_last_iter ) 925 for( j = 0; j <= size.width; j++ ) 926 p_cur[j].a = 0; 927 928 if( !(i & 1) ) 929 { 930 p_prev = p_row_prev; 931 } 932 else 933 { 934 p_prev = (_CvPyramidC3*)((char*)p_row_prev + step * 935 (l == 0 ? sizeof( _CvPyramidBaseC3 ) : sizeof( _CvPyramidC3 ))); 936 } 937 } 938 } 939 } /* end of the iteration process */ 940 941 /* construct a connected components */ 942 size.width = roi.width >> level; 943 size.height = roi.height >> level; 944 945 p_cur = pyram[level]; 946 947 for( i = 0; i < size.height; i++, p_cur += size.width + 1 ) 948 { 949 for( j = 0; j < size.width; j++ ) 950 { 951 if( p_cur[j].a != 0 ) 952 { 953 cmp_node.data = p_cur + j; 954 CV_WRITE_SEQ_ELEM( cmp_node, writer ); 955 } 956 } 957 } 958 959 cvEndWriteSeq( &writer ); 960 961 /* clusterization segmented components and construction 962 output connected components */ 963 icvSegmentClusterC3( cmp_seq, res_seq, threshold2, pyram[1], roi ); 964 965 /* convert (inplace) resultant segment values to int (top level) */ 966 967 /* propagate segment values top down */ 968 for( l = level - 1; l >= 0; l-- ) 969 { 970 p_cur = pyram[l]; 971 972 size.width <<= 1; 973 size.height <<= 1; 974 975 if( l == 0 ) 976 { 977 size.width--; 978 size.height--; 979 } 980 981 for( i = 0; i <= size.height; i++ ) 982 { 983 for( j = 0; j <= size.width; j++ ) 984 { 985 _CvPyramidC3 *p = p_cur->p; 986 987 assert( p != 0 ); 988 if( p != &stub ) 989 { 990 p_cur->c = p->c; 991 } 992 993 if( l == 0 ) 994 { 995 Cv32suf _c; 996 /* copy the segmented values to destination image */ 997 _c.f = p_cur->c.blue; dst_image[j*3] = (uchar)_c.i; 998 _c.f = p_cur->c.green; dst_image[j*3+1] = (uchar)_c.i; 999 _c.f = p_cur->c.red; dst_image[j*3+2] = (uchar)_c.i; 1000 p_cur = _CV_NEXT_BASE_C3(p_cur,1); 1001 } 1002 else 1003 { 1004 p_cur++; 1005 } 1006 } 1007 if( l == 0 ) 1008 dst_image += dst_step; 1009 } 1010 } 1011 1012 M_END: 1013 1014 cvFree( &buffer ); 1015 cvReleaseMemStorage( &temp_storage ); 1016 1017 if( status == CV_OK ) 1018 *dst_comp = res_seq; 1019 1020 return status; 1021 } 1022 1023 1024 static CvStatus icvUpdatePyrLinks_8u_C1 1025 (int layer, void *layer_data, CvSize size, void *parent_layer, 1026 void *_writer, float threshold, int is_last_iter, void *_stub, CvWriteNodeFunction /*func*/) 1027 { 1028 int i, j; 1029 _CvListNode cmp_node; 1030 1031 _CvPyramid *stub = (_CvPyramid *) _stub; 1032 _CvPyramid *p_cur = (_CvPyramid *) layer_data; 1033 _CvPyramid *p_next1 = (_CvPyramid *) parent_layer; 1034 _CvPyramid *p_next3 = p_next1 + (size.width >> 1) + 1; 1035 1036 CvSeqWriter & writer = *(CvSeqWriter *) _writer; 1037 1038 for( i = 0; i < size.height; i++ ) 1039 { 1040 for( j = 0; j < size.width; j += 2 ) 1041 { 1042 float c0, c1, c2, c3, c4; 1043 _CvPyramid *p; 1044 1045 /* son-father threshold linking for the current node establish */ 1046 c0 = p_cur->c; 1047 1048 /* find pointer for the first pixel */ 1049 c1 = (float) fabs( c0 - p_next1[0].c ); 1050 c2 = (float) fabs( c0 - p_next1[1].c ); 1051 c3 = (float) fabs( c0 - p_next3[0].c ); 1052 c4 = (float) fabs( c0 - p_next3[1].c ); 1053 1054 p = p_next1; 1055 1056 if( c1 > c2 ) 1057 { 1058 p = p_next1 + 1; 1059 c1 = c2; 1060 } 1061 if( c1 > c3 ) 1062 { 1063 p = p_next3; 1064 c1 = c3; 1065 } 1066 if( c1 > c4 ) 1067 { 1068 p = p_next3 + 1; 1069 c1 = c4; 1070 } 1071 1072 if( c1 <= threshold ) 1073 { 1074 p_cur->p = p; 1075 1076 if( layer == 0 ) 1077 { 1078 p->a++; 1079 p_cur = (_CvPyramid*)((char*)p_cur + sizeof(_CvPyramidBase)); 1080 if( is_last_iter ) 1081 icvMaxRoi1( &(p->rect), j, i ); 1082 } 1083 else 1084 { 1085 int a = p_cur->a; 1086 1087 p->a += a; 1088 p_cur->c = 0; 1089 p_cur++; 1090 if( is_last_iter && a != 0 ) 1091 icvMaxRoi( &(p->rect), &(p_cur[-1].rect) ); 1092 } 1093 } 1094 else 1095 { 1096 p_cur->p = stub; 1097 if( is_last_iter ) 1098 { 1099 cmp_node.data = p_cur; 1100 CV_WRITE_SEQ_ELEM( cmp_node, writer ); 1101 } 1102 if( layer == 0 ) 1103 { 1104 p_cur = _CV_NEXT_BASE_C1(p_cur,1); 1105 } 1106 else 1107 { 1108 p_cur->c = 0; 1109 p_cur++; 1110 } 1111 } 1112 1113 /* find pointer for the second pixel */ 1114 c0 = p_cur->c; 1115 1116 c1 = (float) fabs( c0 - p_next1[0].c ); 1117 c2 = (float) fabs( c0 - p_next1[1].c ); 1118 c3 = (float) fabs( c0 - p_next3[0].c ); 1119 c4 = (float) fabs( c0 - p_next3[1].c ); 1120 1121 p = p_next1; 1122 p_next1++; 1123 1124 if( c1 > c2 ) 1125 { 1126 p = p_next1; 1127 c1 = c2; 1128 } 1129 if( c1 > c3 ) 1130 { 1131 p = p_next3; 1132 c1 = c3; 1133 } 1134 1135 p_next3++; 1136 if( c1 > c4 ) 1137 { 1138 p = p_next3; 1139 c1 = c4; 1140 } 1141 1142 if( c1 <= threshold ) 1143 { 1144 p_cur->p = p; 1145 1146 if( layer == 0 ) 1147 { 1148 p->a++; 1149 p_cur = _CV_NEXT_BASE_C1(p_cur,1); 1150 if( is_last_iter ) 1151 icvMaxRoi1( &(p->rect), j + 1, i ); 1152 } 1153 else 1154 { 1155 int a = p_cur->a; 1156 1157 p->a += a; 1158 p_cur->c = 0; 1159 p_cur++; 1160 if( is_last_iter && a != 0 ) 1161 icvMaxRoi( &(p->rect), &(p_cur[-1].rect) ); 1162 } 1163 } 1164 else 1165 { 1166 p_cur->p = stub; 1167 if( is_last_iter ) 1168 { 1169 cmp_node.data = p_cur; 1170 CV_WRITE_SEQ_ELEM( cmp_node, writer ); 1171 } 1172 if( layer == 0 ) 1173 { 1174 p_cur = _CV_NEXT_BASE_C1(p_cur,1); 1175 } 1176 else 1177 { 1178 p_cur->c = 0; 1179 p_cur++; 1180 } 1181 } 1182 } 1183 1184 /* clear c's */ 1185 if( layer > 0 ) 1186 { 1187 p_cur->c = 0; 1188 p_cur++; 1189 } 1190 1191 if( !(i & 1) ) 1192 { 1193 p_next1 -= size.width >> 1; 1194 p_next3 -= size.width >> 1; 1195 } 1196 else 1197 { 1198 p_next1++; 1199 p_next3++; 1200 } 1201 } 1202 1203 return CV_OK; 1204 } 1205 1206 1207 static CvStatus icvUpdatePyrLinks_8u_C3 1208 (int layer, void *layer_data, CvSize size, void *parent_layer, 1209 void *_writer, float threshold, int is_last_iter, void *_stub, CvWriteNodeFunction /*func*/) 1210 { 1211 int i, j; 1212 _CvListNode cmp_node; 1213 1214 _CvPyramidC3 *stub = (_CvPyramidC3 *) _stub; 1215 _CvPyramidC3 *p_cur = (_CvPyramidC3 *) layer_data; 1216 _CvPyramidC3 *p_next1 = (_CvPyramidC3 *) parent_layer; 1217 _CvPyramidC3 *p_next3 = p_next1 + (size.width >> 1) + 1; 1218 1219 CvSeqWriter & writer = *(CvSeqWriter *) _writer; 1220 1221 for( i = 0; i < size.height; i++ ) 1222 { 1223 for( j = 0; j < size.width; j += 2 ) 1224 { 1225 float c1, c2, c3, c4; 1226 _CvPyramidC3 *p; 1227 1228 /* find pointer for the first pixel */ 1229 c1 = _CV_RGB_DIST( p_cur->c, p_next1[0].c ); 1230 c2 = _CV_RGB_DIST( p_cur->c, p_next1[1].c ); 1231 c3 = _CV_RGB_DIST( p_cur->c, p_next3[0].c ); 1232 c4 = _CV_RGB_DIST( p_cur->c, p_next3[1].c ); 1233 1234 p = p_next1; 1235 1236 if( c1 > c2 ) 1237 { 1238 p = p_next1 + 1; 1239 c1 = c2; 1240 } 1241 if( c1 > c3 ) 1242 { 1243 p = p_next3; 1244 c1 = c3; 1245 } 1246 if( c1 > c4 ) 1247 { 1248 p = p_next3 + 1; 1249 c1 = c4; 1250 } 1251 1252 if( c1 < threshold ) 1253 { 1254 p_cur->p = p; 1255 1256 if( layer == 0 ) 1257 { 1258 p->a++; 1259 p_cur = _CV_NEXT_BASE_C3(p_cur,1); 1260 if( is_last_iter ) 1261 icvMaxRoi1( &(p->rect), j, i ); 1262 } 1263 else 1264 { 1265 int a = p_cur->a; 1266 1267 p->a += a; 1268 p_cur->c.blue = p_cur->c.green = p_cur->c.red = 0; 1269 p_cur++; 1270 if( is_last_iter && a != 0 ) 1271 icvMaxRoi( &(p->rect), &(p_cur[-1].rect) ); 1272 } 1273 } 1274 else 1275 { 1276 p_cur->p = stub; 1277 if( is_last_iter /* && ( == 0 || p_cur->a != 0) */ ) 1278 { 1279 cmp_node.data = p_cur; 1280 CV_WRITE_SEQ_ELEM( cmp_node, writer ); 1281 } 1282 1283 if( layer == 0 ) 1284 { 1285 p_cur = _CV_NEXT_BASE_C3(p_cur,1); 1286 } 1287 else 1288 { 1289 p_cur->c.blue = p_cur->c.green = p_cur->c.red = 0; 1290 p_cur++; 1291 } 1292 } 1293 1294 /* find pointer for the second pixel */ 1295 c1 = _CV_RGB_DIST( p_cur->c, p_next1[0].c ); 1296 c2 = _CV_RGB_DIST( p_cur->c, p_next1[1].c ); 1297 c3 = _CV_RGB_DIST( p_cur->c, p_next3[0].c ); 1298 c4 = _CV_RGB_DIST( p_cur->c, p_next3[1].c ); 1299 1300 p = p_next1; 1301 p_next1++; 1302 1303 if( c1 > c2 ) 1304 { 1305 p = p_next1; 1306 c1 = c2; 1307 } 1308 if( c1 > c3 ) 1309 { 1310 p = p_next3; 1311 c1 = c3; 1312 } 1313 1314 p_next3++; 1315 if( c1 > c4 ) 1316 { 1317 p = p_next3; 1318 c1 = c4; 1319 } 1320 1321 if( c1 < threshold ) 1322 { 1323 p_cur->p = p; 1324 1325 if( layer == 0 ) 1326 { 1327 p->a++; 1328 p_cur = _CV_NEXT_BASE_C3(p_cur,1); 1329 if( is_last_iter ) 1330 icvMaxRoi1( &(p->rect), j + 1, i ); 1331 } 1332 else 1333 { 1334 int a = p_cur->a; 1335 1336 p->a += a; 1337 p_cur->c.blue = p_cur->c.green = p_cur->c.red = 0; 1338 p_cur++; 1339 if( is_last_iter && a != 0 ) 1340 icvMaxRoi( &(p->rect), &(p_cur[-1].rect) ); 1341 } 1342 } 1343 else 1344 { 1345 p_cur->p = stub; 1346 if( is_last_iter /* && ( == 0 || p_cur->a != 0) */ ) 1347 { 1348 cmp_node.data = p_cur; 1349 CV_WRITE_SEQ_ELEM( cmp_node, writer ); 1350 } 1351 if( layer == 0 ) 1352 { 1353 p_cur = _CV_NEXT_BASE_C3(p_cur,1); 1354 } 1355 else 1356 { 1357 p_cur->c.blue = p_cur->c.green = p_cur->c.red = 0; 1358 p_cur++; 1359 } 1360 } 1361 } 1362 1363 /* clear c's */ 1364 if( layer > 0 ) 1365 { 1366 p_cur->c.blue = p_cur->c.green = p_cur->c.red = 0; 1367 p_cur++; 1368 } 1369 1370 if( !(i & 1) ) 1371 { 1372 p_next1 -= size.width >> 1; 1373 p_next3 -= size.width >> 1; 1374 } 1375 else 1376 { 1377 p_next1++; 1378 p_next3++; 1379 } 1380 } 1381 1382 return CV_OK; 1383 } 1384 1385 1386 1387 /****************************************************************************************\ 1388 1389 clusterization segmented components 1390 1391 \****************************************************************************************/ 1392 static void 1393 icvExpandBaseLevelC1( _CvPyramid * base_p, _CvPyramid * p, _CvPyramidBase * start, int width ) 1394 { 1395 int x = (int)((_CvPyramidBase *) base_p - start); 1396 int y = x / width; 1397 1398 x -= y * width; 1399 p->a = 1; 1400 p->rect.x1 = (ushort) x; 1401 p->rect.y1 = (ushort) y; 1402 p->rect.x2 = (ushort) (x + 1); 1403 p->rect.y2 = (ushort) (y + 1); 1404 p->c = base_p->c; 1405 } 1406 1407 CvStatus 1408 icvSegmentClusterC1( CvSeq * cmp_seq, CvSeq * res_seq, 1409 double threshold, _CvPyramid * first_level_end, CvSize first_level_size ) 1410 { 1411 const double eps = 1.; 1412 CvSeqWriter writer; 1413 CvSeqReader reader; 1414 _CvPyramid temp_cmp; 1415 _CvPyramidBase *first_level_start = (_CvPyramidBase *) first_level_end - 1416 first_level_size.width * first_level_size.height; 1417 int c, i, count = cmp_seq->total; 1418 1419 cvStartReadSeq( cmp_seq, &reader, 0 ); 1420 cvStartAppendToSeq( res_seq, &writer ); 1421 1422 if( threshold < eps ) 1423 { 1424 /* if threshold is too small then simply copy all 1425 the components to the output sequence */ 1426 for( i = 0; i < count; i++ ) 1427 { 1428 CvConnectedComp comp; 1429 _CvPyramid *cmp = (_CvPyramid *) (((_CvListNode *) reader.ptr)->data); 1430 Cv32suf _c; 1431 1432 if( cmp < first_level_end ) 1433 { 1434 icvExpandBaseLevelC1( cmp, &temp_cmp, first_level_start, 1435 first_level_size.width ); 1436 cmp = &temp_cmp; 1437 } 1438 1439 _c.i = cvRound( cmp->c ); 1440 cmp->c = _c.f; 1441 comp.value = cvRealScalar(_c.i); 1442 comp.area = cmp->a; 1443 comp.rect.x = cmp->rect.x1; 1444 comp.rect.y = cmp->rect.y1; 1445 comp.rect.width = cmp->rect.x2 - cmp->rect.x1; 1446 comp.rect.height = cmp->rect.y2 - cmp->rect.y1; 1447 comp.contour = 0; 1448 1449 CV_WRITE_SEQ_ELEM( comp, writer ); 1450 CV_NEXT_SEQ_ELEM( sizeof( _CvListNode ), reader ); 1451 } 1452 } 1453 else 1454 { 1455 _CvListNode stub_node; 1456 _CvListNode *prev = &stub_node; 1457 1458 stub_node.next = 0; 1459 1460 for( i = 0; i < count; i++ ) 1461 { 1462 _CvListNode *node = (_CvListNode *) reader.ptr; 1463 1464 prev->next = node; 1465 prev = node; 1466 CV_NEXT_SEQ_ELEM( sizeof( _CvListNode ), reader ); 1467 } 1468 prev->next = 0; 1469 prev = stub_node.next; 1470 1471 while( prev ) 1472 { 1473 _CvListNode *node = prev->next; 1474 _CvListNode *acc = prev; 1475 _CvPyramid *cmp = (_CvPyramid *) (acc->data); 1476 CvConnectedComp comp; 1477 float c0 = cmp->c; 1478 1479 if( cmp < first_level_end ) 1480 { 1481 icvExpandBaseLevelC1( cmp, &temp_cmp, first_level_start, 1482 first_level_size.width ); 1483 } 1484 else 1485 { 1486 temp_cmp = *cmp; 1487 temp_cmp.c *= temp_cmp.a; 1488 } 1489 1490 acc->next = 0; 1491 stub_node.next = 0; 1492 prev = &stub_node; 1493 1494 while( node ) 1495 { 1496 cmp = (_CvPyramid *) (node->data); 1497 if( fabs( c0 - cmp->c ) < threshold ) 1498 { 1499 _CvPyramid temp; 1500 1501 /* exclude from global list and add to list of joint component */ 1502 prev->next = node->next; 1503 node->next = acc; 1504 acc = node; 1505 1506 if( cmp < first_level_end ) 1507 { 1508 icvExpandBaseLevelC1( cmp, &temp, first_level_start, 1509 first_level_size.width ); 1510 cmp = &temp; 1511 } 1512 1513 temp_cmp.a += cmp->a; 1514 temp_cmp.c += cmp->c * cmp->a; 1515 icvMaxRoi( &(temp_cmp.rect), &(cmp->rect) ); 1516 } 1517 else 1518 { 1519 if( prev == &stub_node ) 1520 { 1521 stub_node.next = node; 1522 } 1523 prev = node; 1524 } 1525 node = prev->next; 1526 } 1527 1528 if( temp_cmp.a != 0 ) 1529 { 1530 c = cvRound( temp_cmp.c / temp_cmp.a ); 1531 } 1532 else 1533 { 1534 c = cvRound( c0 ); 1535 } 1536 node = acc; 1537 1538 while( node ) 1539 { 1540 Cv32suf _c; 1541 cmp = (_CvPyramid *) (node->data); 1542 _c.i = c; cmp->c = _c.f; 1543 node = node->next; 1544 } 1545 1546 comp.value = cvRealScalar(c); 1547 comp.area = temp_cmp.a; 1548 comp.rect.x = temp_cmp.rect.x1; 1549 comp.rect.y = temp_cmp.rect.y1; 1550 comp.rect.width = temp_cmp.rect.x2 - temp_cmp.rect.x1; 1551 comp.rect.height = temp_cmp.rect.y2 - temp_cmp.rect.y1; 1552 comp.contour = 0; 1553 1554 CV_WRITE_SEQ_ELEM( comp, writer ); 1555 prev = stub_node.next; 1556 } 1557 } 1558 1559 cvEndWriteSeq( &writer ); 1560 return CV_OK; 1561 } 1562 1563 /****************************************************************************************\ 1564 1565 clusterization segmented components 1566 1567 \****************************************************************************************/ 1568 static void 1569 icvExpandBaseLevelC3( _CvPyramidC3 * base_p, _CvPyramidC3 * p, 1570 _CvPyramidBaseC3 * start, int width ) 1571 { 1572 int x = (int)((_CvPyramidBaseC3 *) base_p - start); 1573 int y = x / width; 1574 1575 x -= y * width; 1576 p->a = 1; 1577 p->rect.x1 = (ushort) x; 1578 p->rect.y1 = (ushort) y; 1579 p->rect.x2 = (ushort) (x + 1); 1580 p->rect.y2 = (ushort) (y + 1); 1581 p->c = base_p->c; 1582 } 1583 1584 CvStatus 1585 icvSegmentClusterC3( CvSeq * cmp_seq, CvSeq * res_seq, 1586 double threshold, 1587 _CvPyramidC3 * first_level_end, CvSize first_level_size ) 1588 { 1589 const double eps = 1.; 1590 CvSeqWriter writer; 1591 CvSeqReader reader; 1592 _CvPyramidC3 temp_cmp; 1593 _CvPyramidBaseC3 *first_level_start = (_CvPyramidBaseC3 *) first_level_end - 1594 first_level_size.width * first_level_size.height; 1595 int i, count = cmp_seq->total; 1596 int c_blue, c_green, c_red; 1597 1598 cvStartReadSeq( cmp_seq, &reader, 0 ); 1599 cvStartAppendToSeq( res_seq, &writer ); 1600 1601 if( threshold < eps ) 1602 { 1603 /* if threshold is too small then simply copy all 1604 the components to the output sequence */ 1605 for( i = 0; i < count; i++ ) 1606 { 1607 CvConnectedComp comp; 1608 _CvPyramidC3 *cmp = (_CvPyramidC3 *) (((_CvListNode *) reader.ptr)->data); 1609 Cv32suf _c; 1610 1611 if( cmp < first_level_end ) 1612 { 1613 icvExpandBaseLevelC3( cmp, &temp_cmp, first_level_start, 1614 first_level_size.width ); 1615 cmp = &temp_cmp; 1616 } 1617 1618 c_blue = cvRound( cmp->c.blue ); 1619 c_green = cvRound( cmp->c.green ); 1620 c_red = cvRound( cmp->c.red ); 1621 _c.i = c_blue; cmp->c.blue = _c.f; 1622 _c.i = c_green; cmp->c.green = _c.f; 1623 _c.i = c_red; cmp->c.red = _c.f; 1624 comp.value = cvScalar( c_blue, c_green, c_red ); 1625 comp.area = cmp->a; 1626 comp.rect.x = cmp->rect.x1; 1627 comp.rect.y = cmp->rect.y1; 1628 comp.rect.width = cmp->rect.x2 - cmp->rect.x1; 1629 comp.rect.height = cmp->rect.y2 - cmp->rect.y1; 1630 comp.contour = 0; 1631 1632 CV_WRITE_SEQ_ELEM( comp, writer ); 1633 CV_NEXT_SEQ_ELEM( sizeof( _CvListNode ), reader ); 1634 } 1635 } 1636 else 1637 { 1638 _CvListNode stub_node; 1639 _CvListNode *prev = &stub_node; 1640 1641 stub_node.next = 0; 1642 1643 for( i = 0; i < count; i++ ) 1644 { 1645 _CvListNode *node = (_CvListNode *) reader.ptr; 1646 1647 prev->next = node; 1648 prev = node; 1649 CV_NEXT_SEQ_ELEM( sizeof( _CvListNode ), reader ); 1650 } 1651 prev->next = 0; 1652 prev = stub_node.next; 1653 1654 while( prev ) 1655 { 1656 _CvListNode *node = prev->next; 1657 _CvListNode *acc = prev; 1658 _CvPyramidC3 *cmp = (_CvPyramidC3 *) (acc->data); 1659 CvConnectedComp comp; 1660 _CvRGBf c0 = cmp->c; 1661 1662 if( cmp < first_level_end ) 1663 { 1664 icvExpandBaseLevelC3( cmp, &temp_cmp, first_level_start, 1665 first_level_size.width ); 1666 } 1667 else 1668 { 1669 temp_cmp = *cmp; 1670 temp_cmp.c.blue *= temp_cmp.a; 1671 temp_cmp.c.green *= temp_cmp.a; 1672 temp_cmp.c.red *= temp_cmp.a; 1673 } 1674 1675 acc->next = 0; 1676 stub_node.next = 0; 1677 prev = &stub_node; 1678 1679 while( node ) 1680 { 1681 cmp = (_CvPyramidC3 *) (node->data); 1682 if( _CV_RGB_DIST( c0, cmp->c ) < threshold ) 1683 { 1684 _CvPyramidC3 temp; 1685 1686 /* exclude from global list and add to list of joint component */ 1687 prev->next = node->next; 1688 node->next = acc; 1689 acc = node; 1690 1691 if( cmp < first_level_end ) 1692 { 1693 icvExpandBaseLevelC3( cmp, &temp, first_level_start, 1694 first_level_size.width ); 1695 cmp = &temp; 1696 } 1697 1698 temp_cmp.a += cmp->a; 1699 temp_cmp.c.blue += cmp->c.blue * cmp->a; 1700 temp_cmp.c.green += cmp->c.green * cmp->a; 1701 temp_cmp.c.red += cmp->c.red * cmp->a; 1702 icvMaxRoi( &(temp_cmp.rect), &(cmp->rect) ); 1703 } 1704 else 1705 { 1706 if( prev == &stub_node ) 1707 { 1708 stub_node.next = node; 1709 } 1710 prev = node; 1711 } 1712 node = prev->next; 1713 } 1714 1715 if( temp_cmp.a != 0 ) 1716 { 1717 c_blue = cvRound( temp_cmp.c.blue / temp_cmp.a ); 1718 c_green = cvRound( temp_cmp.c.green / temp_cmp.a ); 1719 c_red = cvRound( temp_cmp.c.red / temp_cmp.a ); 1720 } 1721 else 1722 { 1723 c_blue = cvRound( c0.blue ); 1724 c_green = cvRound( c0.green ); 1725 c_red = cvRound( c0.red ); 1726 } 1727 node = acc; 1728 1729 while( node ) 1730 { 1731 Cv32suf _c; 1732 cmp = (_CvPyramidC3 *) (node->data); 1733 _c.i = c_blue; cmp->c.blue = _c.f; 1734 _c.i = c_green; cmp->c.green = _c.f; 1735 _c.i = c_red; cmp->c.red = _c.f; 1736 node = node->next; 1737 } 1738 1739 comp.value = cvScalar( c_blue, c_green, c_red ); 1740 comp.area = temp_cmp.a; 1741 comp.rect.x = temp_cmp.rect.x1; 1742 comp.rect.y = temp_cmp.rect.y1; 1743 comp.rect.width = temp_cmp.rect.x2 - temp_cmp.rect.x1; 1744 comp.rect.height = temp_cmp.rect.y2 - temp_cmp.rect.y1; 1745 comp.contour = 0; 1746 1747 CV_WRITE_SEQ_ELEM( comp, writer ); 1748 prev = stub_node.next; 1749 } 1750 } 1751 1752 cvEndWriteSeq( &writer ); 1753 return CV_OK; 1754 } 1755 1756 /****************************************************************************************\ 1757 1758 definition of the maximum roi size 1759 1760 \****************************************************************************************/ 1761 void 1762 icvMaxRoi( _CvRect16u * max_rect, _CvRect16u * cur_rect ) 1763 { 1764 if( max_rect->x2 == 0 ) 1765 *max_rect = *cur_rect; 1766 else 1767 { 1768 if( max_rect->x1 > cur_rect->x1 ) 1769 max_rect->x1 = cur_rect->x1; 1770 if( max_rect->y1 > cur_rect->y1 ) 1771 max_rect->y1 = cur_rect->y1; 1772 1773 if( max_rect->x2 < cur_rect->x2 ) 1774 max_rect->x2 = cur_rect->x2; 1775 if( max_rect->y2 < cur_rect->y2 ) 1776 max_rect->y2 = cur_rect->y2; 1777 } 1778 } 1779 1780 void 1781 icvMaxRoi1( _CvRect16u * max_rect, int x, int y ) 1782 { 1783 if( max_rect->x2 == 0 ) 1784 { 1785 max_rect->x1 = (ushort) x; 1786 max_rect->y1 = (ushort) y; 1787 1788 ++x; 1789 ++y; 1790 1791 max_rect->x2 = (ushort) x; 1792 max_rect->y2 = (ushort) y; 1793 } 1794 else 1795 { 1796 if( max_rect->x1 > x ) 1797 max_rect->x1 = (ushort) x; 1798 if( max_rect->y1 > y ) 1799 max_rect->y1 = (ushort) y; 1800 1801 ++x; 1802 ++y; 1803 1804 if( max_rect->x2 < x ) 1805 max_rect->x2 = (ushort) x; 1806 if( max_rect->y2 < y ) 1807 max_rect->y2 = (ushort) y; 1808 } 1809 } 1810 1811 1812 /*F/////////////////////////////////////////////////////////////////////////////////////// 1813 // Name: cvPyrSegmentation 1814 // Purpose: 1815 // segments an image using pyramid-linking technique 1816 // Context: 1817 // Parameters: 1818 // src - source image 1819 // dst - destination image 1820 // comp - pointer to returned connected component sequence 1821 // storage - where the sequence is stored 1822 // level - maximal pyramid level 1823 // threshold1 - first threshold, affecting on detalization level when pyramid 1824 // is built. 1825 // threshold2 - second threshold - affects on final components merging. 1826 // Returns: 1827 // Notes: 1828 // Source and destination image must be equal types and channels 1829 //F*/ 1830 CV_IMPL void 1831 cvPyrSegmentation( IplImage * src, 1832 IplImage * dst, 1833 CvMemStorage * storage, 1834 CvSeq ** comp, int level, double threshold1, double threshold2 ) 1835 { 1836 CvSize src_size, dst_size; 1837 uchar *src_data = 0; 1838 uchar *dst_data = 0; 1839 int src_step = 0, dst_step = 0; 1840 int thresh1 = cvRound( threshold1 ); 1841 int thresh2 = cvRound( threshold2 ); 1842 1843 CV_FUNCNAME( "cvPyrSegmentation" ); 1844 1845 __BEGIN__; 1846 1847 if( src->depth != IPL_DEPTH_8U ) 1848 CV_ERROR( CV_BadDepth, cvUnsupportedFormat ); 1849 1850 if( src->depth != dst->depth || src->nChannels != dst->nChannels ) 1851 CV_ERROR( CV_StsBadArg, "src and dst have different formats" ); 1852 1853 cvGetRawData( src, &src_data, &src_step, &src_size ); 1854 cvGetRawData( dst, &dst_data, &dst_step, &dst_size ); 1855 1856 if( src_size.width != dst_size.width || 1857 src_size.height != dst_size.height ) 1858 CV_ERROR( CV_StsBadArg, "src and dst have different ROIs" ); 1859 1860 switch (src->nChannels) 1861 { 1862 case 1: 1863 IPPI_CALL( icvPyrSegmentation8uC1R( src_data, src_step, 1864 dst_data, dst_step, 1865 src_size, 1866 CV_GAUSSIAN_5x5, 1867 comp, storage, level, thresh1, thresh2 )); 1868 break; 1869 case 3: 1870 IPPI_CALL( icvPyrSegmentation8uC3R( src_data, src_step, 1871 dst_data, dst_step, 1872 src_size, 1873 CV_GAUSSIAN_5x5, 1874 comp, storage, level, thresh1, thresh2 )); 1875 break; 1876 default: 1877 CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat ); 1878 } 1879 __END__; 1880 } 1881 1882 1883 /* End of file. */ 1884