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 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