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 ) \
376IPCVAPI_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 )    \
411IPCVAPI_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 ) \
435static 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 )\
471static 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 )         \
495IPCVAPI_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)\
530IPCVAPI_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 )     \
554static 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 )  \
590static 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)\
614ICV_DEF_MEAN_SDV_BLOCK_FUNC_2D( flavor, 1, arrtype, sumtype, sqsumtype, \
615                            worktype, sqworktype, block_size, sqr_macro)\
616ICV_DEF_MEAN_SDV_BLOCK_FUNC_2D( flavor, 2, arrtype, sumtype, sqsumtype, \
617                            worktype, sqworktype, block_size, sqr_macro)\
618ICV_DEF_MEAN_SDV_BLOCK_FUNC_2D( flavor, 3, arrtype, sumtype, sqsumtype, \
619                            worktype, sqworktype, block_size, sqr_macro)\
620ICV_DEF_MEAN_SDV_BLOCK_FUNC_2D( flavor, 4, arrtype, sumtype, sqsumtype, \
621                            worktype, sqworktype, block_size, sqr_macro)\
622ICV_DEF_MEAN_SDV_BLOCK_FUNC_2D_COI( flavor, arrtype, sumtype, sqsumtype,\
623                            worktype, sqworktype, block_size, sqr_macro)\
624                                                                        \
625ICV_DEF_MEAN_SDV_MASK_BLOCK_FUNC_2D( flavor, 1, arrtype, sumtype,       \
626            sqsumtype, worktype, sqworktype, block_size, sqr_macro )    \
627ICV_DEF_MEAN_SDV_MASK_BLOCK_FUNC_2D( flavor, 2, arrtype, sumtype,       \
628            sqsumtype, worktype, sqworktype, block_size, sqr_macro )    \
629ICV_DEF_MEAN_SDV_MASK_BLOCK_FUNC_2D( flavor, 3, arrtype, sumtype,       \
630            sqsumtype, worktype, sqworktype, block_size, sqr_macro )    \
631ICV_DEF_MEAN_SDV_MASK_BLOCK_FUNC_2D( flavor, 4, arrtype, sumtype,       \
632            sqsumtype, worktype, sqworktype, block_size, sqr_macro )    \
633ICV_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 )   \
637ICV_DEF_MEAN_SDV_FUNC_2D( flavor, 1, arrtype, sumtype, sqsumtype, worktype )    \
638ICV_DEF_MEAN_SDV_FUNC_2D( flavor, 2, arrtype, sumtype, sqsumtype, worktype )    \
639ICV_DEF_MEAN_SDV_FUNC_2D( flavor, 3, arrtype, sumtype, sqsumtype, worktype )    \
640ICV_DEF_MEAN_SDV_FUNC_2D( flavor, 4, arrtype, sumtype, sqsumtype, worktype )    \
641ICV_DEF_MEAN_SDV_FUNC_2D_COI( flavor, arrtype, sumtype, sqsumtype, worktype )   \
642                                                                                \
643ICV_DEF_MEAN_SDV_MASK_FUNC_2D(flavor, 1, arrtype, sumtype, sqsumtype, worktype) \
644ICV_DEF_MEAN_SDV_MASK_FUNC_2D(flavor, 2, arrtype, sumtype, sqsumtype, worktype) \
645ICV_DEF_MEAN_SDV_MASK_FUNC_2D(flavor, 3, arrtype, sumtype, sqsumtype, worktype) \
646ICV_DEF_MEAN_SDV_MASK_FUNC_2D(flavor, 4, arrtype, sumtype, sqsumtype, worktype) \
647ICV_DEF_MEAN_SDV_MASK_FUNC_2D_COI( flavor, arrtype, sumtype, sqsumtype, worktype )
648
649
650ICV_DEF_MEAN_SDV_BLOCK_ALL( 8u, uchar, int64, int64, unsigned, unsigned, 1 << 16, CV_SQR_8U )
651ICV_DEF_MEAN_SDV_BLOCK_ALL( 16u, ushort, int64, int64, unsigned, int64, 1 << 16, CV_SQR )
652ICV_DEF_MEAN_SDV_BLOCK_ALL( 16s, short, int64, int64, int, int64, 1 << 16, CV_SQR )
653
654ICV_DEF_MEAN_SDV_ALL( 32s, int, double, double, double )
655ICV_DEF_MEAN_SDV_ALL( 32f, float, double, double, double )
656ICV_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
670CV_DEF_INIT_BIG_FUNC_TAB_2D( Mean_StdDev, R )
671CV_DEF_INIT_FUNC_TAB_2D( Mean_StdDev, CnCR )
672CV_DEF_INIT_BIG_FUNC_TAB_2D( Mean_StdDev, MR )
673CV_DEF_INIT_FUNC_TAB_2D( Mean_StdDev, CnCMR )
674
675CV_IMPL  void
676cvAvgSdv( 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