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#include <float.h> 44 45/****************************************************************************************\ 46* Mean value over the region * 47\****************************************************************************************/ 48 49#define ICV_MEAN_CASE_C1( len ) \ 50 for( ; x <= (len) - 2; x += 2 ) \ 51 { \ 52 if( mask[x] ) \ 53 s0 += src[x], pix++; \ 54 if( mask[x+1] ) \ 55 s0 += src[x+1], pix++; \ 56 } \ 57 \ 58 for( ; x < (len); x++ ) \ 59 if( mask[x] ) \ 60 s0 += src[x], pix++ 61 62 63#define ICV_MEAN_CASE_C2( len ) \ 64 for( ; x < (len); x++ ) \ 65 if( mask[x] ) \ 66 { \ 67 s0 += src[x*2]; \ 68 s1 += src[x*2+1]; \ 69 pix++; \ 70 } 71 72 73#define ICV_MEAN_CASE_C3( len ) \ 74 for( ; x < (len); x++ ) \ 75 if( mask[x] ) \ 76 { \ 77 s0 += src[x*3]; \ 78 s1 += src[x*3+1]; \ 79 s2 += src[x*3+2]; \ 80 pix++; \ 81 } 82 83 84#define ICV_MEAN_CASE_C4( len ) \ 85 for( ; x < (len); x++ ) \ 86 if( mask[x] ) \ 87 { \ 88 s0 += src[x*4]; \ 89 s1 += src[x*4+1]; \ 90 s2 += src[x*4+2]; \ 91 s3 += src[x*4+3]; \ 92 pix++; \ 93 } 94 95 96#define ICV_MEAN_COI_CASE( len, cn ) \ 97 for( ; x <= (len) - 2; x += 2 ) \ 98 { \ 99 if( mask[x] ) \ 100 s0 += src[x*(cn)], pix++; \ 101 if( mask[x+1] ) \ 102 s0+=src[(x+1)*(cn)], pix++; \ 103 } \ 104 \ 105 for( ; x < (len); x++ ) \ 106 if( mask[x] ) \ 107 s0 += src[x*(cn)], pix++; 108 109 110////////////////////////////////////// entry macros ////////////////////////////////////// 111 112#define ICV_MEAN_ENTRY_COMMON() \ 113 int pix = 0; \ 114 step /= sizeof(src[0]) 115 116#define ICV_MEAN_ENTRY_C1( sumtype ) \ 117 sumtype s0 = 0; \ 118 ICV_MEAN_ENTRY_COMMON() 119 120#define ICV_MEAN_ENTRY_C2( sumtype ) \ 121 sumtype s0 = 0, s1 = 0; \ 122 ICV_MEAN_ENTRY_COMMON() 123 124#define ICV_MEAN_ENTRY_C3( sumtype ) \ 125 sumtype s0 = 0, s1 = 0, s2 = 0; \ 126 ICV_MEAN_ENTRY_COMMON() 127 128#define ICV_MEAN_ENTRY_C4( sumtype ) \ 129 sumtype s0 = 0, s1 = 0, s2 = 0, s3 = 0; \ 130 ICV_MEAN_ENTRY_COMMON() 131 132 133#define ICV_MEAN_ENTRY_BLOCK_COMMON( block_size ) \ 134 int remaining = block_size; \ 135 ICV_MEAN_ENTRY_COMMON() 136 137#define ICV_MEAN_ENTRY_BLOCK_C1( sumtype, worktype, block_size )\ 138 sumtype sum0 = 0; \ 139 worktype s0 = 0; \ 140 ICV_MEAN_ENTRY_BLOCK_COMMON( block_size ) 141 142#define ICV_MEAN_ENTRY_BLOCK_C2( sumtype, worktype, block_size )\ 143 sumtype sum0 = 0, sum1 = 0; \ 144 worktype s0 = 0, s1 = 0; \ 145 ICV_MEAN_ENTRY_BLOCK_COMMON( block_size ) 146 147#define ICV_MEAN_ENTRY_BLOCK_C3( sumtype, worktype, block_size )\ 148 sumtype sum0 = 0, sum1 = 0, sum2 = 0; \ 149 worktype s0 = 0, s1 = 0, s2 = 0; \ 150 ICV_MEAN_ENTRY_BLOCK_COMMON( block_size ) 151 152#define ICV_MEAN_ENTRY_BLOCK_C4( sumtype, worktype, block_size )\ 153 sumtype sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0; \ 154 worktype s0 = 0, s1 = 0, s2 = 0, s3 = 0; \ 155 ICV_MEAN_ENTRY_BLOCK_COMMON( block_size ) 156 157 158/////////////////////////////////////// exit macros ////////////////////////////////////// 159 160#define ICV_MEAN_EXIT_COMMON() \ 161 double scale = pix ? 1./pix : 0 162 163#define ICV_MEAN_EXIT_C1( tmp ) \ 164 ICV_MEAN_EXIT_COMMON(); \ 165 mean[0] = scale*(double)tmp##0 166 167#define ICV_MEAN_EXIT_C2( tmp ) \ 168 ICV_MEAN_EXIT_COMMON(); \ 169 double t0 = scale*(double)tmp##0; \ 170 double t1 = scale*(double)tmp##1; \ 171 mean[0] = t0; \ 172 mean[1] = t1 173 174#define ICV_MEAN_EXIT_C3( tmp ) \ 175 ICV_MEAN_EXIT_COMMON(); \ 176 double t0 = scale*(double)tmp##0; \ 177 double t1 = scale*(double)tmp##1; \ 178 double t2 = scale*(double)tmp##2; \ 179 mean[0] = t0; \ 180 mean[1] = t1; \ 181 mean[2] = t2 182 183#define ICV_MEAN_EXIT_C4( tmp ) \ 184 ICV_MEAN_EXIT_COMMON(); \ 185 double t0 = scale*(double)tmp##0; \ 186 double t1 = scale*(double)tmp##1; \ 187 mean[0] = t0; \ 188 mean[1] = t1; \ 189 t0 = scale*(double)tmp##2; \ 190 t1 = scale*(double)tmp##3; \ 191 mean[2] = t0; \ 192 mean[3] = t1 193 194#define ICV_MEAN_EXIT_BLOCK_C1() \ 195 sum0 += s0; \ 196 ICV_MEAN_EXIT_C1( sum ) 197 198#define ICV_MEAN_EXIT_BLOCK_C2() \ 199 sum0 += s0; sum1 += s1; \ 200 ICV_MEAN_EXIT_C2( sum ) 201 202#define ICV_MEAN_EXIT_BLOCK_C3() \ 203 sum0 += s0; sum1 += s1; \ 204 sum2 += s2; \ 205 ICV_MEAN_EXIT_C3( sum ) 206 207#define ICV_MEAN_EXIT_BLOCK_C4() \ 208 sum0 += s0; sum1 += s1; \ 209 sum2 += s2; sum3 += s3; \ 210 ICV_MEAN_EXIT_C4( sum ) 211 212////////////////////////////////////// update macros ///////////////////////////////////// 213 214#define ICV_MEAN_UPDATE_COMMON( block_size )\ 215 remaining = block_size 216 217#define ICV_MEAN_UPDATE_C1( block_size ) \ 218 ICV_MEAN_UPDATE_COMMON( block_size ); \ 219 sum0 += s0; \ 220 s0 = 0 221 222#define ICV_MEAN_UPDATE_C2( block_size ) \ 223 ICV_MEAN_UPDATE_COMMON( block_size ); \ 224 sum0 += s0; sum1 += s1; \ 225 s0 = s1 = 0 226 227#define ICV_MEAN_UPDATE_C3( block_size ) \ 228 ICV_MEAN_UPDATE_COMMON( block_size ); \ 229 sum0 += s0; sum1 += s1; sum2 += s2; \ 230 s0 = s1 = s2 = 0 231 232#define ICV_MEAN_UPDATE_C4( block_size ) \ 233 ICV_MEAN_UPDATE_COMMON( block_size ); \ 234 sum0 += s0; sum1 += s1; \ 235 sum2 += s2; sum3 += s3; \ 236 s0 = s1 = s2 = s3 = 0 237 238 239#define ICV_IMPL_MEAN_BLOCK_FUNC_2D( flavor, cn, \ 240 arrtype, sumtype, worktype, block_size ) \ 241IPCVAPI_IMPL( CvStatus, icvMean_##flavor##_C##cn##MR, \ 242 ( const arrtype* src, int step, \ 243 const uchar* mask, int maskstep, \ 244 CvSize size, double* mean ), \ 245 (src, step, mask, maskstep, size, mean)) \ 246{ \ 247 ICV_MEAN_ENTRY_BLOCK_C##cn( sumtype, worktype, block_size );\ 248 \ 249 for( ; size.height--; src += step, mask += maskstep ) \ 250 { \ 251 int x = 0; \ 252 while( x < size.width ) \ 253 { \ 254 int limit = MIN( remaining, size.width - x ); \ 255 remaining -= limit; \ 256 limit += x; \ 257 ICV_MEAN_CASE_C##cn( limit ); \ 258 if( remaining == 0 ) \ 259 { \ 260 ICV_MEAN_UPDATE_C##cn( block_size ); \ 261 } \ 262 } \ 263 } \ 264 \ 265 { ICV_MEAN_EXIT_BLOCK_C##cn(); } \ 266 return CV_OK; \ 267} 268 269 270#define ICV_IMPL_MEAN_FUNC_2D( flavor, cn, \ 271 arrtype, sumtype, worktype ) \ 272IPCVAPI_IMPL( CvStatus, icvMean_##flavor##_C##cn##MR, \ 273 ( const arrtype* src, int step, \ 274 const uchar* mask, int maskstep, \ 275 CvSize size, double* mean), \ 276 (src, step, mask, maskstep, size, mean)) \ 277{ \ 278 ICV_MEAN_ENTRY_C##cn( sumtype ); \ 279 \ 280 for( ; size.height--; src += step, mask += maskstep ) \ 281 { \ 282 int x = 0; \ 283 ICV_MEAN_CASE_C##cn( size.width ); \ 284 } \ 285 \ 286 { ICV_MEAN_EXIT_C##cn( s ); } \ 287 return CV_OK; \ 288} 289 290 291#define ICV_IMPL_MEAN_BLOCK_FUNC_2D_COI( flavor, \ 292 arrtype, sumtype, worktype, block_size ) \ 293static CvStatus CV_STDCALL \ 294icvMean_##flavor##_CnCMR( const arrtype* src, int step, \ 295 const uchar* mask, int maskstep, \ 296 CvSize size, int cn, \ 297 int coi, double* mean ) \ 298{ \ 299 ICV_MEAN_ENTRY_BLOCK_C1( sumtype, worktype, block_size ); \ 300 src += coi - 1; \ 301 \ 302 for( ; size.height--; src += step, mask += maskstep ) \ 303 { \ 304 int x = 0; \ 305 while( x < size.width ) \ 306 { \ 307 int limit = MIN( remaining, size.width - x ); \ 308 remaining -= limit; \ 309 limit += x; \ 310 ICV_MEAN_COI_CASE( limit, cn ); \ 311 if( remaining == 0 ) \ 312 { \ 313 ICV_MEAN_UPDATE_C1( block_size ); \ 314 } \ 315 } \ 316 } \ 317 \ 318 { ICV_MEAN_EXIT_BLOCK_C1(); } \ 319 return CV_OK; \ 320} 321 322 323#define ICV_IMPL_MEAN_FUNC_2D_COI( flavor, \ 324 arrtype, sumtype, worktype ) \ 325static CvStatus CV_STDCALL \ 326icvMean_##flavor##_CnCMR( const arrtype* src, int step, \ 327 const uchar* mask, int maskstep, \ 328 CvSize size, int cn, \ 329 int coi, double* mean ) \ 330{ \ 331 ICV_MEAN_ENTRY_C1( sumtype ); \ 332 src += coi - 1; \ 333 \ 334 for( ; size.height--; src += step, mask += maskstep ) \ 335 { \ 336 int x = 0; \ 337 ICV_MEAN_COI_CASE( size.width, cn ); \ 338 } \ 339 \ 340 { ICV_MEAN_EXIT_C1( s ); } \ 341 return CV_OK; \ 342} 343 344 345#define ICV_IMPL_MEAN_BLOCK_ALL( flavor, arrtype, sumtype, \ 346 worktype, block_size ) \ 347 ICV_IMPL_MEAN_BLOCK_FUNC_2D( flavor, 1, arrtype, sumtype, \ 348 worktype, block_size ) \ 349 ICV_IMPL_MEAN_BLOCK_FUNC_2D( flavor, 2, arrtype, sumtype, \ 350 worktype, block_size ) \ 351 ICV_IMPL_MEAN_BLOCK_FUNC_2D( flavor, 3, arrtype, sumtype, \ 352 worktype, block_size ) \ 353 ICV_IMPL_MEAN_BLOCK_FUNC_2D( flavor, 4, arrtype, sumtype, \ 354 worktype, block_size ) \ 355 ICV_IMPL_MEAN_BLOCK_FUNC_2D_COI( flavor, arrtype, sumtype, \ 356 worktype, block_size ) 357 358#define ICV_IMPL_MEAN_ALL( flavor, arrtype, sumtype, worktype ) \ 359 ICV_IMPL_MEAN_FUNC_2D( flavor, 1, arrtype, sumtype, worktype ) \ 360 ICV_IMPL_MEAN_FUNC_2D( flavor, 2, arrtype, sumtype, worktype ) \ 361 ICV_IMPL_MEAN_FUNC_2D( flavor, 3, arrtype, sumtype, worktype ) \ 362 ICV_IMPL_MEAN_FUNC_2D( flavor, 4, arrtype, sumtype, worktype ) \ 363 ICV_IMPL_MEAN_FUNC_2D_COI( flavor, arrtype, sumtype, worktype ) 364 365ICV_IMPL_MEAN_BLOCK_ALL( 8u, uchar, int64, unsigned, 1 << 24 ) 366ICV_IMPL_MEAN_BLOCK_ALL( 16u, ushort, int64, unsigned, 1 << 16 ) 367ICV_IMPL_MEAN_BLOCK_ALL( 16s, short, int64, int, 1 << 16 ) 368ICV_IMPL_MEAN_ALL( 32s, int, double, double ) 369ICV_IMPL_MEAN_ALL( 32f, float, double, double ) 370ICV_IMPL_MEAN_ALL( 64f, double, double, double ) 371 372#define icvMean_8s_C1MR 0 373#define icvMean_8s_C2MR 0 374#define icvMean_8s_C3MR 0 375#define icvMean_8s_C4MR 0 376#define icvMean_8s_CnCMR 0 377 378CV_DEF_INIT_BIG_FUNC_TAB_2D( Mean, MR ) 379CV_DEF_INIT_FUNC_TAB_2D( Mean, CnCMR ) 380 381CV_IMPL CvScalar 382cvAvg( const void* img, const void* maskarr ) 383{ 384 CvScalar mean = {{0,0,0,0}}; 385 386 static CvBigFuncTable mean_tab; 387 static CvFuncTable meancoi_tab; 388 static int inittab = 0; 389 390 CV_FUNCNAME("cvAvg"); 391 392 __BEGIN__; 393 394 CvSize size; 395 double scale; 396 397 if( !maskarr ) 398 { 399 CV_CALL( mean = cvSum(img)); 400 size = cvGetSize( img ); 401 size.width *= size.height; 402 scale = size.width ? 1./size.width : 0; 403 404 mean.val[0] *= scale; 405 mean.val[1] *= scale; 406 mean.val[2] *= scale; 407 mean.val[3] *= scale; 408 } 409 else 410 { 411 int type, coi = 0; 412 int mat_step, mask_step; 413 414 CvMat stub, maskstub, *mat = (CvMat*)img, *mask = (CvMat*)maskarr; 415 416 if( !inittab ) 417 { 418 icvInitMeanMRTable( &mean_tab ); 419 icvInitMeanCnCMRTable( &meancoi_tab ); 420 inittab = 1; 421 } 422 423 if( !CV_IS_MAT(mat) ) 424 CV_CALL( mat = cvGetMat( mat, &stub, &coi )); 425 426 if( !CV_IS_MAT(mask) ) 427 CV_CALL( mask = cvGetMat( mask, &maskstub )); 428 429 if( !CV_IS_MASK_ARR(mask) ) 430 CV_ERROR( CV_StsBadMask, "" ); 431 432 if( !CV_ARE_SIZES_EQ( mat, mask ) ) 433 CV_ERROR( CV_StsUnmatchedSizes, "" ); 434 435 type = CV_MAT_TYPE( mat->type ); 436 size = cvGetMatSize( mat ); 437 438 mat_step = mat->step; 439 mask_step = mask->step; 440 441 if( CV_IS_MAT_CONT( mat->type & mask->type )) 442 { 443 size.width *= size.height; 444 size.height = 1; 445 mat_step = mask_step = CV_STUB_STEP; 446 } 447 448 if( CV_MAT_CN(type) == 1 || coi == 0 ) 449 { 450 CvFunc2D_2A1P func; 451 452 if( CV_MAT_CN(type) > 4 ) 453 CV_ERROR( CV_StsOutOfRange, "The input array must have at most 4 channels unless COI is set" ); 454 455 func = (CvFunc2D_2A1P)(mean_tab.fn_2d[type]); 456 457 if( !func ) 458 CV_ERROR( CV_StsBadArg, cvUnsupportedFormat ); 459 460 IPPI_CALL( func( mat->data.ptr, mat_step, mask->data.ptr, 461 mask_step, size, mean.val )); 462 } 463 else 464 { 465 CvFunc2DnC_2A1P func = (CvFunc2DnC_2A1P)( 466 meancoi_tab.fn_2d[CV_MAT_DEPTH(type)]); 467 468 if( !func ) 469 CV_ERROR( CV_StsBadArg, cvUnsupportedFormat ); 470 471 IPPI_CALL( func( mat->data.ptr, mat_step, mask->data.ptr, 472 mask_step, size, CV_MAT_CN(type), coi, mean.val )); 473 } 474 } 475 476 __END__; 477 478 return mean; 479} 480 481/* End of file */ 482