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 
     42 #include "_cxcore.h"
     43 
     44 /****************************************************************************************\
     45 *                             Mean and StdDev calculation                                *
     46 \****************************************************************************************/
     47 
     48 #define ICV_MEAN_SDV_COI_CASE( worktype, sqsumtype, \
     49                                sqr_macro, len, cn ) \
     50     for( ; x <= (len) - 4*(cn); x += 4*(cn))\
     51     {                                       \
     52         worktype t0 = src[x];               \
     53         worktype t1 = src[x + (cn)];        \
     54                                             \
     55         s0  += t0 + t1;                     \
     56         sq0 += (sqsumtype)(sqr_macro(t0)) + \
     57                (sqsumtype)(sqr_macro(t1));  \
     58                                             \
     59         t0 = src[x + 2*(cn)];               \
     60         t1 = src[x + 3*(cn)];               \
     61                                             \
     62         s0  += t0 + t1;                     \
     63         sq0 += (sqsumtype)(sqr_macro(t0)) + \
     64                (sqsumtype)(sqr_macro(t1));  \
     65     }                                       \
     66                                             \
     67     for( ; x < (len); x += (cn) )           \
     68     {                                       \
     69         worktype t0 = src[x];               \
     70                                             \
     71         s0 += t0;                           \
     72         sq0 += (sqsumtype)(sqr_macro(t0));  \
     73     }
     74 
     75 
     76 #define ICV_MEAN_SDV_CASE_C1( worktype, sqsumtype, sqr_macro, len ) \
     77     ICV_MEAN_SDV_COI_CASE( worktype, sqsumtype, sqr_macro, len, 1 )
     78 
     79 
     80 #define ICV_MEAN_SDV_CASE_C2( worktype, sqsumtype, \
     81                               sqr_macro, len ) \
     82     for( ; x < (len); x += 2 )              \
     83     {                                       \
     84         worktype t0 = (src)[x];             \
     85         worktype t1 = (src)[x + 1];         \
     86                                             \
     87         s0 += t0;                           \
     88         sq0 += (sqsumtype)(sqr_macro(t0));  \
     89         s1 += t1;                           \
     90         sq1 += (sqsumtype)(sqr_macro(t1));  \
     91     }
     92 
     93 
     94 #define ICV_MEAN_SDV_CASE_C3( worktype, sqsumtype, \
     95                               sqr_macro, len ) \
     96     for( ; x < (len); x += 3 )              \
     97     {                                       \
     98         worktype t0 = (src)[x];             \
     99         worktype t1 = (src)[x + 1];         \
    100         worktype t2 = (src)[x + 2];         \
    101                                             \
    102         s0 += t0;                           \
    103         sq0 += (sqsumtype)(sqr_macro(t0));  \
    104         s1 += t1;                           \
    105         sq1 += (sqsumtype)(sqr_macro(t1));  \
    106         s2 += t2;                           \
    107         sq2 += (sqsumtype)(sqr_macro(t2));  \
    108     }
    109 
    110 
    111 #define ICV_MEAN_SDV_CASE_C4( worktype, sqsumtype, \
    112                               sqr_macro, len ) \
    113     for( ; x < (len); x += 4 )              \
    114     {                                       \
    115         worktype t0 = (src)[x];             \
    116         worktype t1 = (src)[x + 1];         \
    117                                             \
    118         s0 += t0;                           \
    119         sq0 += (sqsumtype)(sqr_macro(t0));  \
    120         s1 += t1;                           \
    121         sq1 += (sqsumtype)(sqr_macro(t1));  \
    122                                             \
    123         t0 = (src)[x + 2];                  \
    124         t1 = (src)[x + 3];                  \
    125                                             \
    126         s2 += t0;                           \
    127         sq2 += (sqsumtype)(sqr_macro(t0));  \
    128         s3 += t1;                           \
    129         sq3 += (sqsumtype)(sqr_macro(t1));  \
    130     }
    131 
    132 
    133 #define ICV_MEAN_SDV_MASK_COI_CASE( worktype, sqsumtype, \
    134                                     sqr_macro, len, cn ) \
    135     for( ; x <= (len) - 4; x += 4 )             \
    136     {                                           \
    137         worktype t0;                            \
    138         if( mask[x] )                           \
    139         {                                       \
    140             t0 = src[x*(cn)]; pix++;            \
    141             s0 += t0;                           \
    142             sq0 += sqsumtype(sqr_macro(t0));    \
    143         }                                       \
    144                                                 \
    145         if( mask[x+1] )                         \
    146         {                                       \
    147             t0 = src[(x+1)*(cn)]; pix++;        \
    148             s0 += t0;                           \
    149             sq0 += sqsumtype(sqr_macro(t0));    \
    150         }                                       \
    151                                                 \
    152         if( mask[x+2] )                         \
    153         {                                       \
    154             t0 = src[(x+2)*(cn)]; pix++;        \
    155             s0 += t0;                           \
    156             sq0 += sqsumtype(sqr_macro(t0));    \
    157         }                                       \
    158                                                 \
    159         if( mask[x+3] )                         \
    160         {                                       \
    161             t0 = src[(x+3)*(cn)]; pix++;        \
    162             s0 += t0;                           \
    163             sq0 += sqsumtype(sqr_macro(t0));    \
    164         }                                       \
    165     }                                           \
    166                                                 \
    167     for( ; x < (len); x++ )                     \
    168     {                                           \
    169         if( mask[x] )                           \
    170         {                                       \
    171             worktype t0 = src[x*(cn)]; pix++;   \
    172             s0 += t0;                           \
    173             sq0 += sqsumtype(sqr_macro(t0));    \
    174         }                                       \
    175     }
    176 
    177 
    178 #define ICV_MEAN_SDV_MASK_CASE_C1( worktype, sqsumtype, sqr_macro, len )    \
    179     ICV_MEAN_SDV_MASK_COI_CASE( worktype, sqsumtype, sqr_macro, len, 1 )
    180 
    181 
    182 #define ICV_MEAN_SDV_MASK_CASE_C2( worktype, sqsumtype,\
    183                                    sqr_macro, len )    \
    184     for( ; x < (len); x++ )                     \
    185     {                                           \
    186         if( mask[x] )                           \
    187         {                                       \
    188             worktype t0 = src[x*2];             \
    189             worktype t1 = src[x*2+1];           \
    190             pix++;                              \
    191             s0 += t0;                           \
    192             sq0 += sqsumtype(sqr_macro(t0));    \
    193             s1 += t1;                           \
    194             sq1 += sqsumtype(sqr_macro(t1));    \
    195         }                                       \
    196     }
    197 
    198 
    199 #define ICV_MEAN_SDV_MASK_CASE_C3( worktype, sqsumtype,\
    200                                    sqr_macro, len )    \
    201     for( ; x < (len); x++ )                     \
    202     {                                           \
    203         if( mask[x] )                           \
    204         {                                       \
    205             worktype t0 = src[x*3];             \
    206             worktype t1 = src[x*3+1];           \
    207             worktype t2 = src[x*3+2];           \
    208             pix++;                              \
    209             s0 += t0;                           \
    210             sq0 += sqsumtype(sqr_macro(t0));    \
    211             s1 += t1;                           \
    212             sq1 += sqsumtype(sqr_macro(t1));    \
    213             s2 += t2;                           \
    214             sq2 += sqsumtype(sqr_macro(t2));    \
    215         }                                       \
    216     }
    217 
    218 
    219 #define ICV_MEAN_SDV_MASK_CASE_C4( worktype, sqsumtype,\
    220                                    sqr_macro, len )    \
    221     for( ; x < (len); x++ )                     \
    222     {                                           \
    223         if( mask[x] )                           \
    224         {                                       \
    225             worktype t0 = src[x*4];             \
    226             worktype t1 = src[x*4+1];           \
    227             pix++;                              \
    228             s0 += t0;                           \
    229             sq0 += sqsumtype(sqr_macro(t0));    \
    230             s1 += t1;                           \
    231             sq1 += sqsumtype(sqr_macro(t1));    \
    232             t0 = src[x*4+2];                    \
    233             t1 = src[x*4+3];                    \
    234             s2 += t0;                           \
    235             sq2 += sqsumtype(sqr_macro(t0));    \
    236             s3 += t1;                           \
    237             sq3 += sqsumtype(sqr_macro(t1));    \
    238         }                                       \
    239     }
    240 
    241 
    242 ////////////////////////////////////// entry macros //////////////////////////////////////
    243 
    244 #define ICV_MEAN_SDV_ENTRY_COMMON()                 \
    245     int pix;                                        \
    246     double scale, tmp;                              \
    247     step /= sizeof(src[0])
    248 
    249 #define ICV_MEAN_SDV_ENTRY_C1( sumtype, sqsumtype ) \
    250     sumtype s0 = 0;                                 \
    251     sqsumtype sq0 = 0;                              \
    252     ICV_MEAN_SDV_ENTRY_COMMON()
    253 
    254 #define ICV_MEAN_SDV_ENTRY_C2( sumtype, sqsumtype ) \
    255     sumtype s0 = 0, s1 = 0;                         \
    256     sqsumtype sq0 = 0, sq1 = 0;                     \
    257     ICV_MEAN_SDV_ENTRY_COMMON()
    258 
    259 #define ICV_MEAN_SDV_ENTRY_C3( sumtype, sqsumtype ) \
    260     sumtype s0 = 0, s1 = 0, s2 = 0;                 \
    261     sqsumtype sq0 = 0, sq1 = 0, sq2 = 0;            \
    262     ICV_MEAN_SDV_ENTRY_COMMON()
    263 
    264 #define ICV_MEAN_SDV_ENTRY_C4( sumtype, sqsumtype ) \
    265     sumtype s0 = 0, s1 = 0, s2 = 0, s3 = 0;         \
    266     sqsumtype sq0 = 0, sq1 = 0, sq2 = 0, sq3 = 0;   \
    267     ICV_MEAN_SDV_ENTRY_COMMON()
    268 
    269 
    270 #define ICV_MEAN_SDV_ENTRY_BLOCK_COMMON( block_size )   \
    271     int remaining = block_size;                         \
    272     ICV_MEAN_SDV_ENTRY_COMMON()
    273 
    274 #define ICV_MEAN_SDV_ENTRY_BLOCK_C1( sumtype, sqsumtype,        \
    275                         worktype, sqworktype, block_size )      \
    276     sumtype sum0 = 0;                                           \
    277     sqsumtype sqsum0 = 0;                                       \
    278     worktype s0 = 0;                                            \
    279     sqworktype sq0 = 0;                                         \
    280     ICV_MEAN_SDV_ENTRY_BLOCK_COMMON( block_size )
    281 
    282 #define ICV_MEAN_SDV_ENTRY_BLOCK_C2( sumtype, sqsumtype,        \
    283                         worktype, sqworktype, block_size )      \
    284     sumtype sum0 = 0, sum1 = 0;                                 \
    285     sqsumtype sqsum0 = 0, sqsum1 = 0;                           \
    286     worktype s0 = 0, s1 = 0;                                    \
    287     sqworktype sq0 = 0, sq1 = 0;                                \
    288     ICV_MEAN_SDV_ENTRY_BLOCK_COMMON( block_size )
    289 
    290 #define ICV_MEAN_SDV_ENTRY_BLOCK_C3( sumtype, sqsumtype,        \
    291                         worktype, sqworktype, block_size )      \
    292     sumtype sum0 = 0, sum1 = 0, sum2 = 0;                       \
    293     sqsumtype sqsum0 = 0, sqsum1 = 0, sqsum2 = 0;               \
    294     worktype s0 = 0, s1 = 0, s2 = 0;                            \
    295     sqworktype sq0 = 0, sq1 = 0, sq2 = 0;                       \
    296     ICV_MEAN_SDV_ENTRY_BLOCK_COMMON( block_size )
    297 
    298 #define ICV_MEAN_SDV_ENTRY_BLOCK_C4( sumtype, sqsumtype,        \
    299                         worktype, sqworktype, block_size )      \
    300     sumtype sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0;             \
    301     sqsumtype sqsum0 = 0, sqsum1 = 0, sqsum2 = 0, sqsum3 = 0;   \
    302     worktype s0 = 0, s1 = 0, s2 = 0, s3 = 0;                    \
    303     sqworktype sq0 = 0, sq1 = 0, sq2 = 0, sq3 = 0;              \
    304     ICV_MEAN_SDV_ENTRY_BLOCK_COMMON( block_size )
    305 
    306 
    307 /////////////////////////////////////// exit macros //////////////////////////////////////
    308 
    309 #define ICV_MEAN_SDV_EXIT_COMMON()              \
    310     scale = pix ? 1./pix : 0
    311 
    312 #define ICV_MEAN_SDV_EXIT_CN( total, sqtotal, idx ) \
    313     ICV_MEAN_SDV_EXIT_COMMON();                 \
    314     mean[idx] = tmp = scale*(double)total##idx; \
    315     tmp = scale*(double)sqtotal##idx - tmp*tmp; \
    316     sdv[idx] = sqrt(MAX(tmp,0.))
    317 
    318 #define ICV_MEAN_SDV_EXIT_C1( total, sqtotal )  \
    319     ICV_MEAN_SDV_EXIT_COMMON();                 \
    320     ICV_MEAN_SDV_EXIT_CN( total, sqtotal, 0 )
    321 
    322 #define ICV_MEAN_SDV_EXIT_C2( total, sqtotal )  \
    323     ICV_MEAN_SDV_EXIT_COMMON();                 \
    324     ICV_MEAN_SDV_EXIT_CN( total, sqtotal, 0 );  \
    325     ICV_MEAN_SDV_EXIT_CN( total, sqtotal, 1 )
    326 
    327 #define ICV_MEAN_SDV_EXIT_C3( total, sqtotal )  \
    328     ICV_MEAN_SDV_EXIT_COMMON();                 \
    329     ICV_MEAN_SDV_EXIT_CN( total, sqtotal, 0 );  \
    330     ICV_MEAN_SDV_EXIT_CN( total, sqtotal, 1 );  \
    331     ICV_MEAN_SDV_EXIT_CN( total, sqtotal, 2 )
    332 
    333 #define ICV_MEAN_SDV_EXIT_C4( total, sqtotal )  \
    334     ICV_MEAN_SDV_EXIT_COMMON();                 \
    335     ICV_MEAN_SDV_EXIT_CN( total, sqtotal, 0 );  \
    336     ICV_MEAN_SDV_EXIT_CN( total, sqtotal, 1 );  \
    337     ICV_MEAN_SDV_EXIT_CN( total, sqtotal, 2 );  \
    338     ICV_MEAN_SDV_EXIT_CN( total, sqtotal, 3 )
    339 
    340 ////////////////////////////////////// update macros /////////////////////////////////////
    341 
    342 #define ICV_MEAN_SDV_UPDATE_COMMON( block_size )\
    343     remaining = block_size
    344 
    345 #define ICV_MEAN_SDV_UPDATE_C1( block_size )    \
    346     ICV_MEAN_SDV_UPDATE_COMMON( block_size );   \
    347     sum0 += s0; sqsum0 += sq0;                  \
    348     s0 = 0; sq0 = 0
    349 
    350 #define ICV_MEAN_SDV_UPDATE_C2( block_size )    \
    351     ICV_MEAN_SDV_UPDATE_COMMON( block_size );   \
    352     sum0 += s0; sqsum0 += sq0;                  \
    353     sum1 += s1; sqsum1 += sq1;                  \
    354     s0 = s1 = 0; sq0 = sq1 = 0
    355 
    356 #define ICV_MEAN_SDV_UPDATE_C3( block_size )    \
    357     ICV_MEAN_SDV_UPDATE_COMMON( block_size );   \
    358     sum0 += s0; sqsum0 += sq0;                  \
    359     sum1 += s1; sqsum1 += sq1;                  \
    360     sum2 += s2; sqsum2 += sq2;                  \
    361     s0 = s1 = s2 = 0; sq0 = sq1 = sq2 = 0
    362 
    363 #define ICV_MEAN_SDV_UPDATE_C4( block_size )    \
    364     ICV_MEAN_SDV_UPDATE_COMMON( block_size );   \
    365     sum0 += s0; sqsum0 += sq0;                  \
    366     sum1 += s1; sqsum1 += sq1;                  \
    367     sum2 += s2; sqsum2 += sq2;                  \
    368     sum3 += s3; sqsum3 += sq3;                  \
    369     s0 = s1 = s2 = s3 = 0; sq0 = sq1 = sq2 = sq3 = 0
    370 
    371 
    372 
    373 #define ICV_DEF_MEAN_SDV_BLOCK_FUNC_2D( flavor, cn, arrtype,        \
    374                                 sumtype, sqsumtype, worktype,       \
    375                                 sqworktype, block_size, sqr_macro ) \
    376 IPCVAPI_IMPL( CvStatus, icvMean_StdDev_##flavor##_C##cn##R,         \
    377                         ( const arrtype* src, int step,             \
    378                           CvSize size, double* mean, double* sdv ), \
    379                           (src, step, size, mean, sdv) )            \
    380 {                                                                   \
    381     ICV_MEAN_SDV_ENTRY_BLOCK_C##cn( sumtype, sqsumtype,             \
    382                 worktype, sqworktype, (block_size)*(cn) );          \
    383     pix = size.width * size.height;                                 \
    384     size.width *= (cn);                                             \
    385                                                                     \
    386     for( ; size.height--; src += step )                             \
    387     {                                                               \
    388         int x = 0;                                                  \
    389         while( x < size.width )                                     \
    390         {                                                           \
    391             int limit = MIN( remaining, size.width - x );           \
    392             remaining -= limit;                                     \
    393             limit += x;                                             \
    394             ICV_MEAN_SDV_CASE_C##cn( worktype, sqworktype,          \
    395                                      sqr_macro, limit );            \
    396             if( remaining == 0 )                                    \
    397             {                                                       \
    398                 ICV_MEAN_SDV_UPDATE_C##cn( (block_size)*(cn) );     \
    399             }                                                       \
    400         }                                                           \
    401     }                                                               \
    402                                                                     \
    403     ICV_MEAN_SDV_UPDATE_C##cn(0);                                   \
    404     ICV_MEAN_SDV_EXIT_C##cn( sum, sqsum );                          \
    405     return CV_OK;                                                   \
    406 }
    407 
    408 
    409 #define ICV_DEF_MEAN_SDV_FUNC_2D( flavor, cn, arrtype,              \
    410                                   sumtype, sqsumtype, worktype )    \
    411 IPCVAPI_IMPL( CvStatus, icvMean_StdDev_##flavor##_C##cn##R,         \
    412                         ( const arrtype* src, int step,             \
    413                           CvSize size, double* mean, double* sdv ), \
    414                           (src, step, size, mean, sdv) )            \
    415 {                                                                   \
    416     ICV_MEAN_SDV_ENTRY_C##cn( sumtype, sqsumtype );                 \
    417     pix = size.width * size.height;                                 \
    418     size.width *= (cn);                                             \
    419                                                                     \
    420     for( ; size.height--; src += step )                             \
    421     {                                                               \
    422         int x = 0;                                                  \
    423         ICV_MEAN_SDV_CASE_C##cn( worktype, sqsumtype,               \
    424                                  CV_SQR, size.width );              \
    425     }                                                               \
    426                                                                     \
    427     ICV_MEAN_SDV_EXIT_C##cn( s, sq );                               \
    428     return CV_OK;                                                   \
    429 }
    430 
    431 
    432 #define ICV_DEF_MEAN_SDV_BLOCK_FUNC_2D_COI( flavor, arrtype,        \
    433                                 sumtype, sqsumtype, worktype,       \
    434                                 sqworktype, block_size, sqr_macro ) \
    435 static CvStatus CV_STDCALL icvMean_StdDev_##flavor##_CnCR           \
    436                         ( const arrtype* src, int step,             \
    437                           CvSize size, int cn, int coi,             \
    438                           double* mean, double* sdv )               \
    439 {                                                                   \
    440     ICV_MEAN_SDV_ENTRY_BLOCK_C1( sumtype, sqsumtype,                \
    441                 worktype, sqworktype, (block_size)*(cn) );          \
    442     pix = size.width * size.height;                                 \
    443     size.width *= (cn);                                             \
    444     src += coi - 1;                                                 \
    445                                                                     \
    446     for( ; size.height--; src += step )                             \
    447     {                                                               \
    448         int x = 0;                                                  \
    449         while( x < size.width )                                     \
    450         {                                                           \
    451             int limit = MIN( remaining, size.width - x );           \
    452             remaining -= limit;                                     \
    453             limit += x;                                             \
    454             ICV_MEAN_SDV_COI_CASE( worktype, sqworktype,            \
    455                                    sqr_macro, limit, cn);           \
    456             if( remaining == 0 )                                    \
    457             {                                                       \
    458                 ICV_MEAN_SDV_UPDATE_C1( (block_size)*(cn) );        \
    459             }                                                       \
    460         }                                                           \
    461     }                                                               \
    462                                                                     \
    463     ICV_MEAN_SDV_UPDATE_C1(0);                                      \
    464     ICV_MEAN_SDV_EXIT_C1( sum, sqsum );                             \
    465     return CV_OK;                                                   \
    466 }
    467 
    468 
    469 #define ICV_DEF_MEAN_SDV_FUNC_2D_COI( flavor, arrtype,              \
    470                                       sumtype, sqsumtype, worktype )\
    471 static CvStatus CV_STDCALL icvMean_StdDev_##flavor##_CnCR           \
    472                         ( const arrtype* src, int step, CvSize size,\
    473                         int cn, int coi, double* mean, double* sdv )\
    474 {                                                                   \
    475     ICV_MEAN_SDV_ENTRY_C1( sumtype, sqsumtype );                    \
    476     pix = size.width * size.height;                                 \
    477     size.width *= (cn);                                             \
    478     src += coi - 1;                                                 \
    479                                                                     \
    480     for( ; size.height--; src += step )                             \
    481     {                                                               \
    482         int x = 0;                                                  \
    483         ICV_MEAN_SDV_COI_CASE( worktype, sqsumtype,                 \
    484                                CV_SQR, size.width, cn );            \
    485     }                                                               \
    486                                                                     \
    487     ICV_MEAN_SDV_EXIT_C1( s, sq );                                  \
    488     return CV_OK;                                                   \
    489 }
    490 
    491 
    492 #define ICV_DEF_MEAN_SDV_MASK_BLOCK_FUNC_2D( flavor, cn,            \
    493                         arrtype, sumtype, sqsumtype, worktype,      \
    494                         sqworktype, block_size, sqr_macro )         \
    495 IPCVAPI_IMPL( CvStatus, icvMean_StdDev_##flavor##_C##cn##MR,        \
    496                         ( const arrtype* src, int step,             \
    497                           const uchar* mask, int maskstep,          \
    498                           CvSize size, double* mean, double* sdv ), \
    499                        (src, step, mask, maskstep, size, mean, sdv))\
    500 {                                                                   \
    501     ICV_MEAN_SDV_ENTRY_BLOCK_C##cn( sumtype, sqsumtype,             \
    502                     worktype, sqworktype, block_size );             \
    503     pix = 0;                                                        \
    504                                                                     \
    505     for( ; size.height--; src += step, mask += maskstep )           \
    506     {                                                               \
    507         int x = 0;                                                  \
    508         while( x < size.width )                                     \
    509         {                                                           \
    510             int limit = MIN( remaining, size.width - x );           \
    511             remaining -= limit;                                     \
    512             limit += x;                                             \
    513             ICV_MEAN_SDV_MASK_CASE_C##cn( worktype, sqworktype,     \
    514                                           sqr_macro, limit );       \
    515             if( remaining == 0 )                                    \
    516             {                                                       \
    517                 ICV_MEAN_SDV_UPDATE_C##cn( block_size );            \
    518             }                                                       \
    519         }                                                           \
    520     }                                                               \
    521                                                                     \
    522     ICV_MEAN_SDV_UPDATE_C##cn(0);                                   \
    523     ICV_MEAN_SDV_EXIT_C##cn( sum, sqsum );                          \
    524     return CV_OK;                                                   \
    525 }
    526 
    527 
    528 #define ICV_DEF_MEAN_SDV_MASK_FUNC_2D( flavor, cn, arrtype,         \
    529                                        sumtype, sqsumtype, worktype)\
    530 IPCVAPI_IMPL( CvStatus, icvMean_StdDev_##flavor##_C##cn##MR,        \
    531                         ( const arrtype* src, int step,             \
    532                           const uchar* mask, int maskstep,          \
    533                           CvSize size, double* mean, double* sdv ), \
    534                        (src, step, mask, maskstep, size, mean, sdv))\
    535 {                                                                   \
    536     ICV_MEAN_SDV_ENTRY_C##cn( sumtype, sqsumtype );                 \
    537     pix = 0;                                                        \
    538                                                                     \
    539     for( ; size.height--; src += step, mask += maskstep )           \
    540     {                                                               \
    541         int x = 0;                                                  \
    542         ICV_MEAN_SDV_MASK_CASE_C##cn( worktype, sqsumtype,          \
    543                                       CV_SQR, size.width );         \
    544     }                                                               \
    545                                                                     \
    546     ICV_MEAN_SDV_EXIT_C##cn( s, sq );                               \
    547     return CV_OK;                                                   \
    548 }
    549 
    550 
    551 #define ICV_DEF_MEAN_SDV_MASK_BLOCK_FUNC_2D_COI( flavor,            \
    552                             arrtype, sumtype, sqsumtype, worktype,  \
    553                             sqworktype, block_size, sqr_macro )     \
    554 static CvStatus CV_STDCALL icvMean_StdDev_##flavor##_CnCMR          \
    555                         ( const arrtype* src, int step,             \
    556                           const uchar* mask, int maskstep,          \
    557                           CvSize size, int cn, int coi,             \
    558                           double* mean, double* sdv )               \
    559 {                                                                   \
    560     ICV_MEAN_SDV_ENTRY_BLOCK_C1( sumtype, sqsumtype,                \
    561                     worktype, sqworktype, block_size );             \
    562     pix = 0;                                                        \
    563     src += coi - 1;                                                 \
    564                                                                     \
    565     for( ; size.height--; src += step, mask += maskstep )           \
    566     {                                                               \
    567         int x = 0;                                                  \
    568         while( x < size.width )                                     \
    569         {                                                           \
    570             int limit = MIN( remaining, size.width - x );           \
    571             remaining -= limit;                                     \
    572             limit += x;                                             \
    573             ICV_MEAN_SDV_MASK_COI_CASE( worktype, sqworktype,       \
    574                                         sqr_macro, limit, cn );     \
    575             if( remaining == 0 )                                    \
    576             {                                                       \
    577                 ICV_MEAN_SDV_UPDATE_C1( block_size );               \
    578             }                                                       \
    579         }                                                           \
    580     }                                                               \
    581                                                                     \
    582     ICV_MEAN_SDV_UPDATE_C1(0);                                      \
    583     ICV_MEAN_SDV_EXIT_C1( sum, sqsum );                             \
    584     return CV_OK;                                                   \
    585 }
    586 
    587 
    588 #define ICV_DEF_MEAN_SDV_MASK_FUNC_2D_COI( flavor, arrtype,         \
    589                                     sumtype, sqsumtype, worktype )  \
    590 static CvStatus CV_STDCALL icvMean_StdDev_##flavor##_CnCMR          \
    591                         ( const arrtype* src, int step,             \
    592                           const uchar* mask, int maskstep,          \
    593                           CvSize size, int cn, int coi,             \
    594                           double* mean, double* sdv )               \
    595 {                                                                   \
    596     ICV_MEAN_SDV_ENTRY_C1( sumtype, sqsumtype );                    \
    597     pix = 0;                                                        \
    598     src += coi - 1;                                                 \
    599                                                                     \
    600     for( ; size.height--; src += step, mask += maskstep )           \
    601     {                                                               \
    602         int x = 0;                                                  \
    603         ICV_MEAN_SDV_MASK_COI_CASE( worktype, sqsumtype,            \
    604                                     CV_SQR, size.width, cn );       \
    605     }                                                               \
    606                                                                     \
    607     ICV_MEAN_SDV_EXIT_C1( s, sq );                                  \
    608     return CV_OK;                                                   \
    609 }
    610 
    611 
    612 #define ICV_DEF_MEAN_SDV_BLOCK_ALL( flavor, arrtype, sumtype, sqsumtype,\
    613                             worktype, sqworktype, block_size, sqr_macro)\
    614 ICV_DEF_MEAN_SDV_BLOCK_FUNC_2D( flavor, 1, arrtype, sumtype, sqsumtype, \
    615                             worktype, sqworktype, block_size, sqr_macro)\
    616 ICV_DEF_MEAN_SDV_BLOCK_FUNC_2D( flavor, 2, arrtype, sumtype, sqsumtype, \
    617                             worktype, sqworktype, block_size, sqr_macro)\
    618 ICV_DEF_MEAN_SDV_BLOCK_FUNC_2D( flavor, 3, arrtype, sumtype, sqsumtype, \
    619                             worktype, sqworktype, block_size, sqr_macro)\
    620 ICV_DEF_MEAN_SDV_BLOCK_FUNC_2D( flavor, 4, arrtype, sumtype, sqsumtype, \
    621                             worktype, sqworktype, block_size, sqr_macro)\
    622 ICV_DEF_MEAN_SDV_BLOCK_FUNC_2D_COI( flavor, arrtype, sumtype, sqsumtype,\
    623                             worktype, sqworktype, block_size, sqr_macro)\
    624                                                                         \
    625 ICV_DEF_MEAN_SDV_MASK_BLOCK_FUNC_2D( flavor, 1, arrtype, sumtype,       \
    626             sqsumtype, worktype, sqworktype, block_size, sqr_macro )    \
    627 ICV_DEF_MEAN_SDV_MASK_BLOCK_FUNC_2D( flavor, 2, arrtype, sumtype,       \
    628             sqsumtype, worktype, sqworktype, block_size, sqr_macro )    \
    629 ICV_DEF_MEAN_SDV_MASK_BLOCK_FUNC_2D( flavor, 3, arrtype, sumtype,       \
    630             sqsumtype, worktype, sqworktype, block_size, sqr_macro )    \
    631 ICV_DEF_MEAN_SDV_MASK_BLOCK_FUNC_2D( flavor, 4, arrtype, sumtype,       \
    632             sqsumtype, worktype, sqworktype, block_size, sqr_macro )    \
    633 ICV_DEF_MEAN_SDV_MASK_BLOCK_FUNC_2D_COI( flavor, arrtype, sumtype,      \
    634             sqsumtype, worktype, sqworktype, block_size, sqr_macro )
    635 
    636 #define ICV_DEF_MEAN_SDV_ALL( flavor, arrtype, sumtype, sqsumtype, worktype )   \
    637 ICV_DEF_MEAN_SDV_FUNC_2D( flavor, 1, arrtype, sumtype, sqsumtype, worktype )    \
    638 ICV_DEF_MEAN_SDV_FUNC_2D( flavor, 2, arrtype, sumtype, sqsumtype, worktype )    \
    639 ICV_DEF_MEAN_SDV_FUNC_2D( flavor, 3, arrtype, sumtype, sqsumtype, worktype )    \
    640 ICV_DEF_MEAN_SDV_FUNC_2D( flavor, 4, arrtype, sumtype, sqsumtype, worktype )    \
    641 ICV_DEF_MEAN_SDV_FUNC_2D_COI( flavor, arrtype, sumtype, sqsumtype, worktype )   \
    642                                                                                 \
    643 ICV_DEF_MEAN_SDV_MASK_FUNC_2D(flavor, 1, arrtype, sumtype, sqsumtype, worktype) \
    644 ICV_DEF_MEAN_SDV_MASK_FUNC_2D(flavor, 2, arrtype, sumtype, sqsumtype, worktype) \
    645 ICV_DEF_MEAN_SDV_MASK_FUNC_2D(flavor, 3, arrtype, sumtype, sqsumtype, worktype) \
    646 ICV_DEF_MEAN_SDV_MASK_FUNC_2D(flavor, 4, arrtype, sumtype, sqsumtype, worktype) \
    647 ICV_DEF_MEAN_SDV_MASK_FUNC_2D_COI( flavor, arrtype, sumtype, sqsumtype, worktype )
    648 
    649 
    650 ICV_DEF_MEAN_SDV_BLOCK_ALL( 8u, uchar, int64, int64, unsigned, unsigned, 1 << 16, CV_SQR_8U )
    651 ICV_DEF_MEAN_SDV_BLOCK_ALL( 16u, ushort, int64, int64, unsigned, int64, 1 << 16, CV_SQR )
    652 ICV_DEF_MEAN_SDV_BLOCK_ALL( 16s, short, int64, int64, int, int64, 1 << 16, CV_SQR )
    653 
    654 ICV_DEF_MEAN_SDV_ALL( 32s, int, double, double, double )
    655 ICV_DEF_MEAN_SDV_ALL( 32f, float, double, double, double )
    656 ICV_DEF_MEAN_SDV_ALL( 64f, double, double, double, double )
    657 
    658 #define icvMean_StdDev_8s_C1R  0
    659 #define icvMean_StdDev_8s_C2R  0
    660 #define icvMean_StdDev_8s_C3R  0
    661 #define icvMean_StdDev_8s_C4R  0
    662 #define icvMean_StdDev_8s_CnCR 0
    663 
    664 #define icvMean_StdDev_8s_C1MR  0
    665 #define icvMean_StdDev_8s_C2MR  0
    666 #define icvMean_StdDev_8s_C3MR  0
    667 #define icvMean_StdDev_8s_C4MR  0
    668 #define icvMean_StdDev_8s_CnCMR 0
    669 
    670 CV_DEF_INIT_BIG_FUNC_TAB_2D( Mean_StdDev, R )
    671 CV_DEF_INIT_FUNC_TAB_2D( Mean_StdDev, CnCR )
    672 CV_DEF_INIT_BIG_FUNC_TAB_2D( Mean_StdDev, MR )
    673 CV_DEF_INIT_FUNC_TAB_2D( Mean_StdDev, CnCMR )
    674 
    675 CV_IMPL  void
    676 cvAvgSdv( const CvArr* img, CvScalar* _mean, CvScalar* _sdv, const void* mask )
    677 {
    678     CvScalar mean = {{0,0,0,0}};
    679     CvScalar sdv = {{0,0,0,0}};
    680 
    681     static CvBigFuncTable meansdv_tab;
    682     static CvFuncTable meansdvcoi_tab;
    683     static CvBigFuncTable meansdvmask_tab;
    684     static CvFuncTable meansdvmaskcoi_tab;
    685     static int inittab = 0;
    686 
    687     CV_FUNCNAME("cvMean_StdDev");
    688 
    689     __BEGIN__;
    690 
    691     int type, coi = 0;
    692     int mat_step, mask_step = 0;
    693     CvSize size;
    694     CvMat stub, maskstub, *mat = (CvMat*)img, *matmask = (CvMat*)mask;
    695 
    696     if( !inittab )
    697     {
    698         icvInitMean_StdDevRTable( &meansdv_tab );
    699         icvInitMean_StdDevCnCRTable( &meansdvcoi_tab );
    700         icvInitMean_StdDevMRTable( &meansdvmask_tab );
    701         icvInitMean_StdDevCnCMRTable( &meansdvmaskcoi_tab );
    702         inittab = 1;
    703     }
    704 
    705     if( !CV_IS_MAT(mat) )
    706         CV_CALL( mat = cvGetMat( mat, &stub, &coi ));
    707 
    708     type = CV_MAT_TYPE( mat->type );
    709 
    710     if( CV_MAT_CN(type) > 4 && coi == 0 )
    711         CV_ERROR( CV_StsOutOfRange, "The input array must have at most 4 channels unless COI is set" );
    712 
    713     size = cvGetMatSize( mat );
    714     mat_step = mat->step;
    715 
    716     if( !mask )
    717     {
    718         if( CV_IS_MAT_CONT( mat->type ))
    719         {
    720             size.width *= size.height;
    721             size.height = 1;
    722             mat_step = CV_STUB_STEP;
    723         }
    724 
    725         if( CV_MAT_CN(type) == 1 || coi == 0 )
    726         {
    727             CvFunc2D_1A2P func = (CvFunc2D_1A2P)(meansdv_tab.fn_2d[type]);
    728 
    729             if( !func )
    730                 CV_ERROR( CV_StsBadArg, cvUnsupportedFormat );
    731 
    732             IPPI_CALL( func( mat->data.ptr, mat_step, size, mean.val, sdv.val ));
    733         }
    734         else
    735         {
    736             CvFunc2DnC_1A2P func = (CvFunc2DnC_1A2P)
    737                 (meansdvcoi_tab.fn_2d[CV_MAT_DEPTH(type)]);
    738 
    739             if( !func )
    740                 CV_ERROR( CV_StsBadArg, cvUnsupportedFormat );
    741 
    742             IPPI_CALL( func( mat->data.ptr, mat_step, size,
    743                              CV_MAT_CN(type), coi, mean.val, sdv.val ));
    744         }
    745     }
    746     else
    747     {
    748         CV_CALL( matmask = cvGetMat( matmask, &maskstub ));
    749 
    750         mask_step = matmask->step;
    751 
    752         if( !CV_IS_MASK_ARR( matmask ))
    753             CV_ERROR( CV_StsBadMask, "" );
    754 
    755         if( !CV_ARE_SIZES_EQ( mat, matmask ))
    756             CV_ERROR( CV_StsUnmatchedSizes, "" );
    757 
    758         if( CV_IS_MAT_CONT( mat->type & matmask->type ))
    759         {
    760             size.width *= size.height;
    761             size.height = 1;
    762             mat_step = mask_step = CV_STUB_STEP;
    763         }
    764 
    765         if( CV_MAT_CN(type) == 1 || coi == 0 )
    766         {
    767             CvFunc2D_2A2P func = (CvFunc2D_2A2P)(meansdvmask_tab.fn_2d[type]);
    768 
    769             if( !func )
    770                 CV_ERROR( CV_StsBadArg, cvUnsupportedFormat );
    771 
    772             IPPI_CALL( func( mat->data.ptr, mat_step, matmask->data.ptr,
    773                              mask_step, size, mean.val, sdv.val ));
    774         }
    775         else
    776         {
    777             CvFunc2DnC_2A2P func = (CvFunc2DnC_2A2P)
    778                 (meansdvmaskcoi_tab.fn_2d[CV_MAT_DEPTH(type)]);
    779 
    780             if( !func )
    781                 CV_ERROR( CV_StsBadArg, cvUnsupportedFormat );
    782 
    783             IPPI_CALL( func( mat->data.ptr, mat_step,
    784                              matmask->data.ptr, mask_step,
    785                              size, CV_MAT_CN(type), coi, mean.val, sdv.val ));
    786         }
    787     }
    788 
    789     __END__;
    790 
    791     if( _mean )
    792         *_mean = mean;
    793 
    794     if( _sdv )
    795         *_sdv = sdv;
    796 }
    797 
    798 
    799 /*  End of file  */
    800