Move the sources to trunk
[opencv] / cxcore / src / cxmeansdv.cpp
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  */