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 * N o r m * 46 \****************************************************************************************/ 47 48 #define ICV_NORM_CASE( _op_, \ 49 _update_op_, worktype, len ) \ 50 \ 51 for( ; x <= (len) - 4; x += 4 ) \ 52 { \ 53 worktype t0 = (src)[x]; \ 54 worktype t1 = (src)[x+1]; \ 55 t0 = _op_(t0); \ 56 t1 = _op_(t1); \ 57 norm = _update_op_( norm, t0 ); \ 58 norm = _update_op_( norm, t1 ); \ 59 \ 60 t0 = (src)[x+2]; \ 61 t1 = (src)[x+3]; \ 62 t0 = _op_(t0); \ 63 t1 = _op_(t1); \ 64 norm = _update_op_( norm, t0 ); \ 65 norm = _update_op_( norm, t1 ); \ 66 } \ 67 \ 68 for( ; x < (len); x++ ) \ 69 { \ 70 worktype t0 = (src)[x]; \ 71 t0 = (worktype)_op_(t0); \ 72 norm = _update_op_( norm, t0 ); \ 73 } 74 75 76 #define ICV_NORM_COI_CASE( _op_, \ 77 _update_op_, worktype, len, cn ) \ 78 \ 79 for( ; x < (len); x++ ) \ 80 { \ 81 worktype t0 = (src)[x*(cn)]; \ 82 t0 = (worktype)_op_(t0); \ 83 norm = _update_op_( norm, t0 ); \ 84 } 85 86 87 #define ICV_NORM_DIFF_CASE( _op_, \ 88 _update_op_, worktype, len ) \ 89 \ 90 for( ; x <= (len) - 4; x += 4 ) \ 91 { \ 92 worktype t0 = (src1)[x] - (src2)[x];\ 93 worktype t1 = (src1)[x+1]-(src2)[x+1];\ 94 \ 95 t0 = _op_(t0); \ 96 t1 = _op_(t1); \ 97 \ 98 norm = _update_op_( norm, t0 ); \ 99 norm = _update_op_( norm, t1 ); \ 100 \ 101 t0 = (src1)[x+2] - (src2)[x+2]; \ 102 t1 = (src1)[x+3] - (src2)[x+3]; \ 103 \ 104 t0 = _op_(t0); \ 105 t1 = _op_(t1); \ 106 \ 107 norm = _update_op_( norm, t0 ); \ 108 norm = _update_op_( norm, t1 ); \ 109 } \ 110 \ 111 for( ; x < (len); x++ ) \ 112 { \ 113 worktype t0 = (src1)[x] - (src2)[x];\ 114 t0 = (worktype)_op_(t0); \ 115 norm = _update_op_( norm, t0 ); \ 116 } 117 118 119 #define ICV_NORM_DIFF_COI_CASE( _op_, _update_op_, worktype, len, cn ) \ 120 for( ; x < (len); x++ ) \ 121 { \ 122 worktype t0 = (src1)[x*(cn)] - (src2)[x*(cn)]; \ 123 t0 = (worktype)_op_(t0); \ 124 norm = _update_op_( norm, t0 ); \ 125 } 126 127 128 /* 129 The algorithm and its multiple variations below 130 below accumulates the norm by blocks of size "block_size". 131 Each block may span across multiple lines and it is 132 not necessary aligned by row boundaries. Within a block 133 the norm is accumulated to intermediate light-weight 134 type (worktype). It really makes sense for 8u, 16s, 16u types 135 and L1 & L2 norms, where worktype==int and normtype==int64. 136 In other cases a simpler algorithm is used 137 */ 138 #define ICV_DEF_NORM_NOHINT_BLOCK_FUNC_2D( name, _op_, _update_op_, \ 139 post_func, arrtype, normtype, worktype, block_size ) \ 140 IPCVAPI_IMPL( CvStatus, name, ( const arrtype* src, int step, \ 141 CvSize size, double* _norm ), (src, step, size, _norm) ) \ 142 { \ 143 int remaining = block_size; \ 144 normtype total_norm = 0; \ 145 worktype norm = 0; \ 146 step /= sizeof(src[0]); \ 147 \ 148 for( ; size.height--; src += step ) \ 149 { \ 150 int x = 0; \ 151 while( x < size.width ) \ 152 { \ 153 int limit = MIN( remaining, size.width - x ); \ 154 remaining -= limit; \ 155 limit += x; \ 156 ICV_NORM_CASE( _op_, _update_op_, worktype, limit );\ 157 if( remaining == 0 ) \ 158 { \ 159 remaining = block_size; \ 160 total_norm += (normtype)norm; \ 161 norm = 0; \ 162 } \ 163 } \ 164 } \ 165 \ 166 total_norm += (normtype)norm; \ 167 *_norm = post_func((double)total_norm); \ 168 return CV_OK; \ 169 } 170 171 172 #define ICV_DEF_NORM_NOHINT_FUNC_2D( name, _op_, _update_op_, \ 173 post_func, arrtype, normtype, worktype, block_size ) \ 174 IPCVAPI_IMPL( CvStatus, name, ( const arrtype* src, int step, \ 175 CvSize size, double* _norm ), (src, step, size, _norm) ) \ 176 { \ 177 normtype norm = 0; \ 178 step /= sizeof(src[0]); \ 179 \ 180 for( ; size.height--; src += step ) \ 181 { \ 182 int x = 0; \ 183 ICV_NORM_CASE(_op_, _update_op_, worktype, size.width); \ 184 } \ 185 \ 186 *_norm = post_func((double)norm); \ 187 return CV_OK; \ 188 } 189 190 191 /* 192 In IPP only 32f flavors of norm functions are with hint. 193 For float worktype==normtype==double, thus the block algorithm, 194 described above, is not necessary. 195 */ 196 #define ICV_DEF_NORM_HINT_FUNC_2D( name, _op_, _update_op_, \ 197 post_func, arrtype, normtype, worktype, block_size ) \ 198 IPCVAPI_IMPL( CvStatus, name, ( const arrtype* src, int step, \ 199 CvSize size, double* _norm, CvHintAlgorithm /*hint*/ ), \ 200 (src, step, size, _norm, cvAlgHintAccurate) ) \ 201 { \ 202 normtype norm = 0; \ 203 step /= sizeof(src[0]); \ 204 \ 205 for( ; size.height--; src += step ) \ 206 { \ 207 int x = 0; \ 208 ICV_NORM_CASE(_op_, _update_op_, worktype, size.width); \ 209 } \ 210 \ 211 *_norm = post_func((double)norm); \ 212 return CV_OK; \ 213 } 214 215 216 #define ICV_DEF_NORM_NOHINT_BLOCK_FUNC_2D_COI( name, _op_, \ 217 _update_op_, post_func, arrtype, \ 218 normtype, worktype, block_size ) \ 219 static CvStatus CV_STDCALL name( const arrtype* src, int step, \ 220 CvSize size, int cn, int coi, double* _norm ) \ 221 { \ 222 int remaining = block_size; \ 223 normtype total_norm = 0; \ 224 worktype norm = 0; \ 225 step /= sizeof(src[0]); \ 226 src += coi - 1; \ 227 \ 228 for( ; size.height--; src += step ) \ 229 { \ 230 int x = 0; \ 231 while( x < size.width ) \ 232 { \ 233 int limit = MIN( remaining, size.width - x ); \ 234 remaining -= limit; \ 235 limit += x; \ 236 ICV_NORM_COI_CASE( _op_, _update_op_, \ 237 worktype, limit, cn ); \ 238 if( remaining == 0 ) \ 239 { \ 240 remaining = block_size; \ 241 total_norm += (normtype)norm; \ 242 norm = 0; \ 243 } \ 244 } \ 245 } \ 246 \ 247 total_norm += (normtype)norm; \ 248 *_norm = post_func((double)total_norm); \ 249 return CV_OK; \ 250 } 251 252 253 #define ICV_DEF_NORM_NOHINT_FUNC_2D_COI( name, _op_, \ 254 _update_op_, post_func, \ 255 arrtype, normtype, worktype, block_size ) \ 256 static CvStatus CV_STDCALL name( const arrtype* src, int step, \ 257 CvSize size, int cn, int coi, double* _norm ) \ 258 { \ 259 normtype norm = 0; \ 260 step /= sizeof(src[0]); \ 261 src += coi - 1; \ 262 \ 263 for( ; size.height--; src += step ) \ 264 { \ 265 int x = 0; \ 266 ICV_NORM_COI_CASE( _op_, _update_op_, \ 267 worktype, size.width, cn ); \ 268 } \ 269 \ 270 *_norm = post_func((double)norm); \ 271 return CV_OK; \ 272 } 273 274 275 #define ICV_DEF_NORM_DIFF_NOHINT_BLOCK_FUNC_2D( name, _op_, \ 276 _update_op_, post_func, arrtype, \ 277 normtype, worktype, block_size ) \ 278 IPCVAPI_IMPL( CvStatus, name,( const arrtype* src1, int step1, \ 279 const arrtype* src2, int step2, CvSize size, double* _norm),\ 280 (src1, step1, src2, step2, size, _norm)) \ 281 { \ 282 int remaining = block_size; \ 283 normtype total_norm = 0; \ 284 worktype norm = 0; \ 285 step1 /= sizeof(src1[0]); \ 286 step2 /= sizeof(src2[0]); \ 287 \ 288 for( ; size.height--; src1 += step1, src2 += step2 ) \ 289 { \ 290 int x = 0; \ 291 while( x < size.width ) \ 292 { \ 293 int limit = MIN( remaining, size.width - x ); \ 294 remaining -= limit; \ 295 limit += x; \ 296 ICV_NORM_DIFF_CASE( _op_, _update_op_, \ 297 worktype, limit ); \ 298 if( remaining == 0 ) \ 299 { \ 300 remaining = block_size; \ 301 total_norm += (normtype)norm; \ 302 norm = 0; \ 303 } \ 304 } \ 305 } \ 306 \ 307 total_norm += (normtype)norm; \ 308 *_norm = post_func((double)total_norm); \ 309 return CV_OK; \ 310 } 311 312 313 #define ICV_DEF_NORM_DIFF_NOHINT_FUNC_2D( name, _op_, \ 314 _update_op_, post_func, \ 315 arrtype, normtype, worktype, block_size ) \ 316 IPCVAPI_IMPL( CvStatus, name,( const arrtype* src1, int step1, \ 317 const arrtype* src2, int step2, CvSize size, double* _norm),\ 318 ( src1, step1, src2, step2, size, _norm )) \ 319 { \ 320 normtype norm = 0; \ 321 step1 /= sizeof(src1[0]); \ 322 step2 /= sizeof(src2[0]); \ 323 \ 324 for( ; size.height--; src1 += step1, src2 += step2 ) \ 325 { \ 326 int x = 0; \ 327 ICV_NORM_DIFF_CASE( _op_, _update_op_, \ 328 worktype, size.width ); \ 329 } \ 330 \ 331 *_norm = post_func((double)norm); \ 332 return CV_OK; \ 333 } 334 335 336 #define ICV_DEF_NORM_DIFF_HINT_FUNC_2D( name, _op_, \ 337 _update_op_, post_func, \ 338 arrtype, normtype, worktype, block_size ) \ 339 IPCVAPI_IMPL( CvStatus, name,( const arrtype* src1, int step1, \ 340 const arrtype* src2, int step2, CvSize size, double* _norm, \ 341 CvHintAlgorithm /*hint*/ ), \ 342 (src1, step1, src2, step2, size, _norm, cvAlgHintAccurate ))\ 343 { \ 344 normtype norm = 0; \ 345 step1 /= sizeof(src1[0]); \ 346 step2 /= sizeof(src2[0]); \ 347 \ 348 for( ; size.height--; src1 += step1, src2 += step2 ) \ 349 { \ 350 int x = 0; \ 351 ICV_NORM_DIFF_CASE( _op_, _update_op_, \ 352 worktype, size.width ); \ 353 } \ 354 \ 355 *_norm = post_func((double)norm); \ 356 return CV_OK; \ 357 } 358 359 360 #define ICV_DEF_NORM_DIFF_NOHINT_BLOCK_FUNC_2D_COI( name, _op_,\ 361 _update_op_, post_func, arrtype, \ 362 normtype, worktype, block_size ) \ 363 static CvStatus CV_STDCALL name( const arrtype* src1, int step1,\ 364 const arrtype* src2, int step2, CvSize size, \ 365 int cn, int coi, double* _norm ) \ 366 { \ 367 int remaining = block_size; \ 368 normtype total_norm = 0; \ 369 worktype norm = 0; \ 370 step1 /= sizeof(src1[0]); \ 371 step2 /= sizeof(src2[0]); \ 372 src1 += coi - 1; \ 373 src2 += coi - 1; \ 374 \ 375 for( ; size.height--; src1 += step1, src2 += step2 ) \ 376 { \ 377 int x = 0; \ 378 while( x < size.width ) \ 379 { \ 380 int limit = MIN( remaining, size.width - x ); \ 381 remaining -= limit; \ 382 limit += x; \ 383 ICV_NORM_DIFF_COI_CASE( _op_, _update_op_, \ 384 worktype, limit, cn ); \ 385 if( remaining == 0 ) \ 386 { \ 387 remaining = block_size; \ 388 total_norm += (normtype)norm; \ 389 norm = 0; \ 390 } \ 391 } \ 392 } \ 393 \ 394 total_norm += (normtype)norm; \ 395 *_norm = post_func((double)total_norm); \ 396 return CV_OK; \ 397 } 398 399 400 #define ICV_DEF_NORM_DIFF_NOHINT_FUNC_2D_COI( name, _op_, \ 401 _update_op_, post_func, \ 402 arrtype, normtype, worktype, block_size ) \ 403 static CvStatus CV_STDCALL name( const arrtype* src1, int step1,\ 404 const arrtype* src2, int step2, CvSize size, \ 405 int cn, int coi, double* _norm ) \ 406 { \ 407 normtype norm = 0; \ 408 step1 /= sizeof(src1[0]); \ 409 step2 /= sizeof(src2[0]); \ 410 src1 += coi - 1; \ 411 src2 += coi - 1; \ 412 \ 413 for( ; size.height--; src1 += step1, src2 += step2 ) \ 414 { \ 415 int x = 0; \ 416 ICV_NORM_DIFF_COI_CASE( _op_, _update_op_, \ 417 worktype, size.width, cn ); \ 418 } \ 419 \ 420 *_norm = post_func((double)norm); \ 421 return CV_OK; \ 422 } 423 424 425 /****************************************************************************************\ 426 * N o r m with M A S K * 427 \****************************************************************************************/ 428 429 #define ICV_NORM_MASK_CASE( _op_, \ 430 _update_op_, worktype, len ) \ 431 { \ 432 for( ; x <= (len) - 2; x += 2 ) \ 433 { \ 434 worktype t0; \ 435 if( mask[x] ) \ 436 { \ 437 t0 = (src)[x]; \ 438 t0 = _op_(t0); \ 439 norm = _update_op_( norm, t0 ); \ 440 } \ 441 if( mask[x+1] ) \ 442 { \ 443 t0 = (src)[x+1]; \ 444 t0 = _op_(t0); \ 445 norm = _update_op_( norm, t0 ); \ 446 } \ 447 } \ 448 \ 449 for( ; x < (len); x++ ) \ 450 if( mask[x] ) \ 451 { \ 452 worktype t0 = (src)[x]; \ 453 t0 = _op_(t0); \ 454 norm = _update_op_( norm, t0 ); \ 455 } \ 456 } 457 458 459 #define ICV_NORM_DIFF_MASK_CASE( _op_, _update_op_, worktype, len ) \ 460 { \ 461 for( ; x <= (len) - 2; x += 2 ) \ 462 { \ 463 worktype t0; \ 464 if( mask[x] ) \ 465 { \ 466 t0 = (src1)[x] - (src2)[x]; \ 467 t0 = _op_(t0); \ 468 norm = _update_op_( norm, t0 ); \ 469 } \ 470 if( mask[x+1] ) \ 471 { \ 472 t0 = (src1)[x+1] - (src2)[x+1]; \ 473 t0 = _op_(t0); \ 474 norm = _update_op_( norm, t0 ); \ 475 } \ 476 } \ 477 \ 478 for( ; x < (len); x++ ) \ 479 if( mask[x] ) \ 480 { \ 481 worktype t0 = (src1)[x] - (src2)[x];\ 482 t0 = _op_(t0); \ 483 norm = _update_op_( norm, t0 ); \ 484 } \ 485 } 486 487 488 #define ICV_NORM_MASK_COI_CASE( _op_, _update_op_, worktype, len, cn ) \ 489 { \ 490 for( ; x < (len); x++ ) \ 491 if( mask[x] ) \ 492 { \ 493 worktype t0 = (src)[x*(cn)]; \ 494 t0 = _op_(t0); \ 495 norm = _update_op_( norm, t0 ); \ 496 } \ 497 } 498 499 500 #define ICV_NORM_DIFF_MASK_COI_CASE( _op_, _update_op_, worktype, len, cn )\ 501 { \ 502 for( ; x < (len); x++ ) \ 503 if( mask[x] ) \ 504 { \ 505 worktype t0 = (src1)[x*(cn)] - (src2)[x*(cn)]; \ 506 t0 = _op_(t0); \ 507 norm = _update_op_( norm, t0 ); \ 508 } \ 509 } 510 511 512 #define ICV_DEF_NORM_MASK_NOHINT_BLOCK_FUNC_2D( name, _op_, \ 513 _update_op_, post_func, arrtype, \ 514 normtype, worktype, block_size ) \ 515 IPCVAPI_IMPL( CvStatus, name, ( const arrtype* src, int step, \ 516 const uchar* mask, int maskstep, CvSize size, double* _norm ),\ 517 (src, step, mask, maskstep, size, _norm) ) \ 518 { \ 519 int remaining = block_size; \ 520 normtype total_norm = 0; \ 521 worktype norm = 0; \ 522 step /= sizeof(src[0]); \ 523 \ 524 for( ; size.height--; src += step, mask += maskstep ) \ 525 { \ 526 int x = 0; \ 527 while( x < size.width ) \ 528 { \ 529 int limit = MIN( remaining, size.width - x ); \ 530 remaining -= limit; \ 531 limit += x; \ 532 ICV_NORM_MASK_CASE( _op_, _update_op_, \ 533 worktype, limit ); \ 534 if( remaining == 0 ) \ 535 { \ 536 remaining = block_size; \ 537 total_norm += (normtype)norm; \ 538 norm = 0; \ 539 } \ 540 } \ 541 } \ 542 \ 543 total_norm += (normtype)norm; \ 544 *_norm = post_func((double)total_norm); \ 545 return CV_OK; \ 546 } 547 548 549 #define ICV_DEF_NORM_MASK_NOHINT_FUNC_2D( name, _op_, _update_op_,\ 550 post_func, arrtype, normtype, worktype, block_size ) \ 551 IPCVAPI_IMPL( CvStatus, name, ( const arrtype* src, int step, \ 552 const uchar* mask, int maskstep, CvSize size, double* _norm ),\ 553 (src, step, mask, maskstep, size, _norm) ) \ 554 { \ 555 normtype norm = 0; \ 556 step /= sizeof(src[0]); \ 557 \ 558 for( ; size.height--; src += step, mask += maskstep ) \ 559 { \ 560 int x = 0; \ 561 ICV_NORM_MASK_CASE( _op_, _update_op_, \ 562 worktype, size.width ); \ 563 } \ 564 \ 565 *_norm = post_func((double)norm); \ 566 return CV_OK; \ 567 } 568 569 570 #define ICV_DEF_NORM_MASK_NOHINT_BLOCK_FUNC_2D_COI( name, _op_,\ 571 _update_op_, post_func, arrtype, \ 572 normtype, worktype, block_size ) \ 573 static CvStatus CV_STDCALL name( const arrtype* src, int step, \ 574 const uchar* mask, int maskstep, CvSize size, \ 575 int cn, int coi, double* _norm ) \ 576 { \ 577 int remaining = block_size; \ 578 normtype total_norm = 0; \ 579 worktype norm = 0; \ 580 step /= sizeof(src[0]); \ 581 src += coi - 1; \ 582 \ 583 for( ; size.height--; src += step, mask += maskstep ) \ 584 { \ 585 int x = 0; \ 586 while( x < size.width ) \ 587 { \ 588 int limit = MIN( remaining, size.width - x ); \ 589 remaining -= limit; \ 590 limit += x; \ 591 ICV_NORM_MASK_COI_CASE( _op_, _update_op_, \ 592 worktype, limit, cn ); \ 593 if( remaining == 0 ) \ 594 { \ 595 remaining = block_size; \ 596 total_norm += (normtype)norm; \ 597 norm = 0; \ 598 } \ 599 } \ 600 } \ 601 \ 602 total_norm += (normtype)norm; \ 603 *_norm = post_func((double)total_norm); \ 604 return CV_OK; \ 605 } 606 607 608 #define ICV_DEF_NORM_MASK_NOHINT_FUNC_2D_COI( name, _op_, \ 609 _update_op_, post_func, \ 610 arrtype, normtype, worktype, block_size ) \ 611 static CvStatus CV_STDCALL name( const arrtype* src, int step, \ 612 const uchar* mask, int maskstep, CvSize size, \ 613 int cn, int coi, double* _norm ) \ 614 { \ 615 normtype norm = 0; \ 616 step /= sizeof(src[0]); \ 617 src += coi - 1; \ 618 \ 619 for( ; size.height--; src += step, mask += maskstep ) \ 620 { \ 621 int x = 0; \ 622 ICV_NORM_MASK_COI_CASE( _op_, _update_op_, \ 623 worktype, size.width, cn ); \ 624 } \ 625 \ 626 *_norm = post_func((double)norm); \ 627 return CV_OK; \ 628 } 629 630 631 632 #define ICV_DEF_NORM_DIFF_MASK_NOHINT_BLOCK_FUNC_2D( name, \ 633 _op_, _update_op_, post_func, arrtype, \ 634 normtype, worktype, block_size ) \ 635 IPCVAPI_IMPL( CvStatus, name,( const arrtype* src1, int step1, \ 636 const arrtype* src2, int step2, const uchar* mask, \ 637 int maskstep, CvSize size, double* _norm ), \ 638 (src1, step1, src2, step2, mask, maskstep, size, _norm )) \ 639 { \ 640 int remaining = block_size; \ 641 normtype total_norm = 0; \ 642 worktype norm = 0; \ 643 step1 /= sizeof(src1[0]); \ 644 step2 /= sizeof(src2[0]); \ 645 \ 646 for( ; size.height--; src1 += step1, src2 += step2, \ 647 mask += maskstep ) \ 648 { \ 649 int x = 0; \ 650 while( x < size.width ) \ 651 { \ 652 int limit = MIN( remaining, size.width - x ); \ 653 remaining -= limit; \ 654 limit += x; \ 655 ICV_NORM_DIFF_MASK_CASE( _op_, _update_op_, \ 656 worktype, limit ); \ 657 if( remaining == 0 ) \ 658 { \ 659 remaining = block_size; \ 660 total_norm += (normtype)norm; \ 661 norm = 0; \ 662 } \ 663 } \ 664 } \ 665 \ 666 total_norm += (normtype)norm; \ 667 *_norm = post_func((double)total_norm); \ 668 return CV_OK; \ 669 } 670 671 672 #define ICV_DEF_NORM_DIFF_MASK_NOHINT_FUNC_2D( name, _op_, \ 673 _update_op_, post_func, \ 674 arrtype, normtype, worktype, block_size ) \ 675 IPCVAPI_IMPL( CvStatus, name,( const arrtype* src1, int step1, \ 676 const arrtype* src2, int step2, const uchar* mask, \ 677 int maskstep, CvSize size, double* _norm ), \ 678 (src1, step1, src2, step2, mask, maskstep, size, _norm )) \ 679 { \ 680 normtype norm = 0; \ 681 step1 /= sizeof(src1[0]); \ 682 step2 /= sizeof(src2[0]); \ 683 \ 684 for( ; size.height--; src1 += step1, src2 += step2, \ 685 mask += maskstep ) \ 686 { \ 687 int x = 0; \ 688 ICV_NORM_DIFF_MASK_CASE( _op_, _update_op_, \ 689 worktype, size.width ); \ 690 } \ 691 \ 692 *_norm = post_func((double)norm); \ 693 return CV_OK; \ 694 } 695 696 697 #define ICV_DEF_NORM_DIFF_MASK_NOHINT_BLOCK_FUNC_2D_COI( name, \ 698 _op_, _update_op_, post_func, arrtype, \ 699 normtype, worktype, block_size ) \ 700 static CvStatus CV_STDCALL name( const arrtype* src1, int step1,\ 701 const arrtype* src2, int step2, const uchar* mask, \ 702 int maskstep, CvSize size, int cn, int coi, double* _norm ) \ 703 { \ 704 int remaining = block_size; \ 705 normtype total_norm = 0; \ 706 worktype norm = 0; \ 707 step1 /= sizeof(src1[0]); \ 708 step2 /= sizeof(src2[0]); \ 709 src1 += coi - 1; \ 710 src2 += coi - 1; \ 711 \ 712 for( ; size.height--; src1 += step1, src2 += step2, \ 713 mask += maskstep ) \ 714 { \ 715 int x = 0; \ 716 while( x < size.width ) \ 717 { \ 718 int limit = MIN( remaining, size.width - x ); \ 719 remaining -= limit; \ 720 limit += x; \ 721 ICV_NORM_DIFF_MASK_COI_CASE( _op_, _update_op_, \ 722 worktype, limit, cn ); \ 723 if( remaining == 0 ) \ 724 { \ 725 remaining = block_size; \ 726 total_norm += (normtype)norm; \ 727 norm = 0; \ 728 } \ 729 } \ 730 } \ 731 \ 732 total_norm += (normtype)norm; \ 733 *_norm = post_func((double)total_norm); \ 734 return CV_OK; \ 735 } 736 737 738 #define ICV_DEF_NORM_DIFF_MASK_NOHINT_FUNC_2D_COI( name, _op_, \ 739 _update_op_, post_func, \ 740 arrtype, normtype, worktype, block_size ) \ 741 static CvStatus CV_STDCALL name( const arrtype* src1, int step1,\ 742 const arrtype* src2, int step2, const uchar* mask, \ 743 int maskstep, CvSize size, int cn, int coi, double* _norm ) \ 744 { \ 745 normtype norm = 0; \ 746 step1 /= sizeof(src1[0]); \ 747 step2 /= sizeof(src2[0]); \ 748 src1 += coi - 1; \ 749 src2 += coi - 1; \ 750 \ 751 for( ; size.height--; src1 += step1, src2 += step2, \ 752 mask += maskstep ) \ 753 { \ 754 int x = 0; \ 755 ICV_NORM_DIFF_MASK_COI_CASE( _op_, _update_op_, \ 756 worktype, size.width, cn );\ 757 } \ 758 \ 759 *_norm = post_func((double)norm); \ 760 return CV_OK; \ 761 } 762 763 764 //////////////////////////////////// The macros expanded ///////////////////////////////// 765 766 767 #define ICV_DEF_NORM_FUNC_ALL_C(flavor, _abs_, _abs_diff_, arrtype, worktype)\ 768 \ 769 ICV_DEF_NORM_NOHINT_FUNC_2D( icvNorm_Inf_##flavor##_C1R, \ 770 _abs_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \ 771 \ 772 ICV_DEF_NORM_NOHINT_FUNC_2D_COI( icvNorm_Inf_##flavor##_CnCR, \ 773 _abs_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \ 774 \ 775 ICV_DEF_NORM_DIFF_NOHINT_FUNC_2D( icvNormDiff_Inf_##flavor##_C1R, \ 776 _abs_diff_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \ 777 \ 778 ICV_DEF_NORM_DIFF_NOHINT_FUNC_2D_COI( icvNormDiff_Inf_##flavor##_CnCR, \ 779 _abs_diff_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \ 780 \ 781 ICV_DEF_NORM_MASK_NOHINT_FUNC_2D( icvNorm_Inf_##flavor##_C1MR, \ 782 _abs_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \ 783 \ 784 ICV_DEF_NORM_MASK_NOHINT_FUNC_2D_COI( icvNorm_Inf_##flavor##_CnCMR, \ 785 _abs_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \ 786 \ 787 ICV_DEF_NORM_DIFF_MASK_NOHINT_FUNC_2D( icvNormDiff_Inf_##flavor##_C1MR, \ 788 _abs_diff_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) \ 789 \ 790 ICV_DEF_NORM_DIFF_MASK_NOHINT_FUNC_2D_COI( icvNormDiff_Inf_##flavor##_CnCMR,\ 791 _abs_diff_, MAX, CV_NOP, arrtype, worktype, worktype, 0 ) 792 793 794 ICV_DEF_NORM_FUNC_ALL_C( 8u, CV_NOP, CV_IABS, uchar, int ) 795 ICV_DEF_NORM_FUNC_ALL_C( 16u, CV_NOP, CV_IABS, ushort, int ) 796 ICV_DEF_NORM_FUNC_ALL_C( 16s, CV_IABS, CV_IABS, short, int ) 797 // there is no protection from overflow 798 // (otherwise we had to do everything in int64's or double's) 799 ICV_DEF_NORM_FUNC_ALL_C( 32s, CV_IABS, CV_IABS, int, int ) 800 ICV_DEF_NORM_FUNC_ALL_C( 32f, fabs, fabs, float, double ) 801 ICV_DEF_NORM_FUNC_ALL_C( 64f, fabs, fabs, double, double ) 802 803 #define ICV_DEF_NORM_FUNC_ALL_L1( flavor, _abs_, _abs_diff_, hintp_func, nohint_func,\ 804 arrtype, normtype, worktype, block_size ) \ 805 \ 806 ICV_DEF_NORM_##hintp_func##_FUNC_2D( icvNorm_L1_##flavor##_C1R, \ 807 _abs_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) \ 808 \ 809 ICV_DEF_NORM_##nohint_func##_FUNC_2D_COI( icvNorm_L1_##flavor##_CnCR, \ 810 _abs_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) \ 811 \ 812 ICV_DEF_NORM_DIFF_##hintp_func##_FUNC_2D( icvNormDiff_L1_##flavor##_C1R, \ 813 _abs_diff_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) \ 814 \ 815 ICV_DEF_NORM_DIFF_##nohint_func##_FUNC_2D_COI( icvNormDiff_L1_##flavor##_CnCR, \ 816 _abs_diff_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) \ 817 \ 818 ICV_DEF_NORM_MASK_##nohint_func##_FUNC_2D( icvNorm_L1_##flavor##_C1MR, \ 819 _abs_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) \ 820 \ 821 ICV_DEF_NORM_MASK_##nohint_func##_FUNC_2D_COI( icvNorm_L1_##flavor##_CnCMR, \ 822 _abs_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) \ 823 \ 824 ICV_DEF_NORM_DIFF_MASK_##nohint_func##_FUNC_2D( icvNormDiff_L1_##flavor##_C1MR, \ 825 _abs_diff_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) \ 826 \ 827 ICV_DEF_NORM_DIFF_MASK_##nohint_func##_FUNC_2D_COI( icvNormDiff_L1_##flavor##_CnCMR,\ 828 _abs_diff_, CV_ADD, CV_NOP, arrtype, normtype, worktype, block_size ) 829 830 831 ICV_DEF_NORM_FUNC_ALL_L1( 8u, CV_NOP, CV_IABS, NOHINT_BLOCK, NOHINT_BLOCK, 832 uchar, int64, int, 1 << 23 ) 833 ICV_DEF_NORM_FUNC_ALL_L1( 16u, CV_NOP, CV_IABS, NOHINT_BLOCK, NOHINT_BLOCK, 834 ushort, int64, int, 1 << 15 ) 835 ICV_DEF_NORM_FUNC_ALL_L1( 16s, CV_IABS, CV_IABS, NOHINT_BLOCK, NOHINT_BLOCK, 836 short, int64, int, 1 << 15 ) 837 // there is no protection from overflow on abs() stage. 838 // (otherwise we had to do everything in int64's or double's) 839 ICV_DEF_NORM_FUNC_ALL_L1( 32s, fabs, fabs, NOHINT, NOHINT, 840 int, double, double, INT_MAX ) 841 ICV_DEF_NORM_FUNC_ALL_L1( 32f, fabs, fabs, HINT, NOHINT, 842 float, double, double, INT_MAX ) 843 ICV_DEF_NORM_FUNC_ALL_L1( 64f, fabs, fabs, NOHINT, NOHINT, 844 double, double, double, INT_MAX ) 845 846 847 #define ICV_DEF_NORM_FUNC_ALL_L2( flavor, hintp_func, nohint_func, arrtype, \ 848 normtype, worktype, block_size, sqr_macro ) \ 849 \ 850 ICV_DEF_NORM_##hintp_func##_FUNC_2D( icvNorm_L2_##flavor##_C1R, \ 851 sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \ 852 \ 853 ICV_DEF_NORM_##nohint_func##_FUNC_2D_COI( icvNorm_L2_##flavor##_CnCR, \ 854 sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \ 855 \ 856 ICV_DEF_NORM_DIFF_##hintp_func##_FUNC_2D( icvNormDiff_L2_##flavor##_C1R, \ 857 sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \ 858 \ 859 ICV_DEF_NORM_DIFF_##nohint_func##_FUNC_2D_COI( icvNormDiff_L2_##flavor##_CnCR, \ 860 sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \ 861 \ 862 ICV_DEF_NORM_MASK_##nohint_func##_FUNC_2D( icvNorm_L2_##flavor##_C1MR, \ 863 sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \ 864 \ 865 ICV_DEF_NORM_MASK_##nohint_func##_FUNC_2D_COI( icvNorm_L2_##flavor##_CnCMR, \ 866 sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \ 867 \ 868 ICV_DEF_NORM_DIFF_MASK_##nohint_func##_FUNC_2D( icvNormDiff_L2_##flavor##_C1MR, \ 869 sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) \ 870 \ 871 ICV_DEF_NORM_DIFF_MASK_##nohint_func##_FUNC_2D_COI( icvNormDiff_L2_##flavor##_CnCMR,\ 872 sqr_macro, CV_ADD, sqrt, arrtype, normtype, worktype, block_size ) 873 874 875 ICV_DEF_NORM_FUNC_ALL_L2( 8u, NOHINT_BLOCK, NOHINT_BLOCK, uchar, 876 int64, int, 1 << 15, CV_SQR_8U ) 877 ICV_DEF_NORM_FUNC_ALL_L2( 16u, NOHINT, NOHINT, ushort, 878 double, double, INT_MAX, CV_SQR ) 879 ICV_DEF_NORM_FUNC_ALL_L2( 16s, NOHINT, NOHINT, short, 880 double, double, INT_MAX, CV_SQR ) 881 // there is no protection from overflow on abs() stage. 882 // (otherwise we had to do everything in int64's or double's) 883 ICV_DEF_NORM_FUNC_ALL_L2( 32s, NOHINT, NOHINT, int, 884 double, double, INT_MAX, CV_SQR ) 885 ICV_DEF_NORM_FUNC_ALL_L2( 32f, HINT, NOHINT, float, 886 double, double, INT_MAX, CV_SQR ) 887 ICV_DEF_NORM_FUNC_ALL_L2( 64f, NOHINT, NOHINT, double, 888 double, double, INT_MAX, CV_SQR ) 889 890 891 #define ICV_DEF_INIT_NORM_TAB_2D( FUNCNAME, FLAG ) \ 892 static void icvInit##FUNCNAME##FLAG##Table( CvFuncTable* tab ) \ 893 { \ 894 tab->fn_2d[CV_8U] = (void*)icv##FUNCNAME##_8u_##FLAG; \ 895 tab->fn_2d[CV_8S] = 0; \ 896 tab->fn_2d[CV_16U] = (void*)icv##FUNCNAME##_16u_##FLAG; \ 897 tab->fn_2d[CV_16S] = (void*)icv##FUNCNAME##_16s_##FLAG; \ 898 tab->fn_2d[CV_32S] = (void*)icv##FUNCNAME##_32s_##FLAG; \ 899 tab->fn_2d[CV_32F] = (void*)icv##FUNCNAME##_32f_##FLAG; \ 900 tab->fn_2d[CV_64F] = (void*)icv##FUNCNAME##_64f_##FLAG; \ 901 } 902 903 ICV_DEF_INIT_NORM_TAB_2D( Norm_Inf, C1R ) 904 ICV_DEF_INIT_NORM_TAB_2D( Norm_L1, C1R ) 905 ICV_DEF_INIT_NORM_TAB_2D( Norm_L2, C1R ) 906 ICV_DEF_INIT_NORM_TAB_2D( NormDiff_Inf, C1R ) 907 ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L1, C1R ) 908 ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L2, C1R ) 909 910 ICV_DEF_INIT_NORM_TAB_2D( Norm_Inf, CnCR ) 911 ICV_DEF_INIT_NORM_TAB_2D( Norm_L1, CnCR ) 912 ICV_DEF_INIT_NORM_TAB_2D( Norm_L2, CnCR ) 913 ICV_DEF_INIT_NORM_TAB_2D( NormDiff_Inf, CnCR ) 914 ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L1, CnCR ) 915 ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L2, CnCR ) 916 917 ICV_DEF_INIT_NORM_TAB_2D( Norm_Inf, C1MR ) 918 ICV_DEF_INIT_NORM_TAB_2D( Norm_L1, C1MR ) 919 ICV_DEF_INIT_NORM_TAB_2D( Norm_L2, C1MR ) 920 ICV_DEF_INIT_NORM_TAB_2D( NormDiff_Inf, C1MR ) 921 ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L1, C1MR ) 922 ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L2, C1MR ) 923 924 ICV_DEF_INIT_NORM_TAB_2D( Norm_Inf, CnCMR ) 925 ICV_DEF_INIT_NORM_TAB_2D( Norm_L1, CnCMR ) 926 ICV_DEF_INIT_NORM_TAB_2D( Norm_L2, CnCMR ) 927 ICV_DEF_INIT_NORM_TAB_2D( NormDiff_Inf, CnCMR ) 928 ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L1, CnCMR ) 929 ICV_DEF_INIT_NORM_TAB_2D( NormDiff_L2, CnCMR ) 930 931 932 static void icvInitNormTabs( CvFuncTable* norm_tab, CvFuncTable* normmask_tab ) 933 { 934 icvInitNorm_InfC1RTable( &norm_tab[0] ); 935 icvInitNorm_L1C1RTable( &norm_tab[1] ); 936 icvInitNorm_L2C1RTable( &norm_tab[2] ); 937 icvInitNormDiff_InfC1RTable( &norm_tab[3] ); 938 icvInitNormDiff_L1C1RTable( &norm_tab[4] ); 939 icvInitNormDiff_L2C1RTable( &norm_tab[5] ); 940 941 icvInitNorm_InfCnCRTable( &norm_tab[6] ); 942 icvInitNorm_L1CnCRTable( &norm_tab[7] ); 943 icvInitNorm_L2CnCRTable( &norm_tab[8] ); 944 icvInitNormDiff_InfCnCRTable( &norm_tab[9] ); 945 icvInitNormDiff_L1CnCRTable( &norm_tab[10] ); 946 icvInitNormDiff_L2CnCRTable( &norm_tab[11] ); 947 948 icvInitNorm_InfC1MRTable( &normmask_tab[0] ); 949 icvInitNorm_L1C1MRTable( &normmask_tab[1] ); 950 icvInitNorm_L2C1MRTable( &normmask_tab[2] ); 951 icvInitNormDiff_InfC1MRTable( &normmask_tab[3] ); 952 icvInitNormDiff_L1C1MRTable( &normmask_tab[4] ); 953 icvInitNormDiff_L2C1MRTable( &normmask_tab[5] ); 954 955 icvInitNorm_InfCnCMRTable( &normmask_tab[6] ); 956 icvInitNorm_L1CnCMRTable( &normmask_tab[7] ); 957 icvInitNorm_L2CnCMRTable( &normmask_tab[8] ); 958 icvInitNormDiff_InfCnCMRTable( &normmask_tab[9] ); 959 icvInitNormDiff_L1CnCMRTable( &normmask_tab[10] ); 960 icvInitNormDiff_L2CnCMRTable( &normmask_tab[11] ); 961 } 962 963 964 CV_IMPL double 965 cvNorm( const void* imgA, const void* imgB, int normType, const void* mask ) 966 { 967 static CvFuncTable norm_tab[12]; 968 static CvFuncTable normmask_tab[12]; 969 static int inittab = 0; 970 971 double norm = 0, norm_diff = 0; 972 973 CV_FUNCNAME("cvNorm"); 974 975 __BEGIN__; 976 977 int type, depth, cn, is_relative; 978 CvSize size; 979 CvMat stub1, *mat1 = (CvMat*)imgB; 980 CvMat stub2, *mat2 = (CvMat*)imgA; 981 int mat2_flag = CV_MAT_CONT_FLAG; 982 int mat1_step, mat2_step, mask_step = 0; 983 int coi = 0, coi2 = 0; 984 985 if( !mat1 ) 986 { 987 mat1 = mat2; 988 mat2 = 0; 989 } 990 991 is_relative = mat2 && (normType & CV_RELATIVE); 992 normType &= ~CV_RELATIVE; 993 994 switch( normType ) 995 { 996 case CV_C: 997 case CV_L1: 998 case CV_L2: 999 case CV_DIFF_C: 1000 case CV_DIFF_L1: 1001 case CV_DIFF_L2: 1002 normType = (normType & 7) >> 1; 1003 break; 1004 default: 1005 CV_ERROR( CV_StsBadFlag, "" ); 1006 } 1007 1008 /* light variant */ 1009 if( CV_IS_MAT(mat1) && (!mat2 || CV_IS_MAT(mat2)) && !mask ) 1010 { 1011 if( mat2 ) 1012 { 1013 if( !CV_ARE_TYPES_EQ( mat1, mat2 )) 1014 CV_ERROR( CV_StsUnmatchedFormats, "" ); 1015 1016 if( !CV_ARE_SIZES_EQ( mat1, mat2 )) 1017 CV_ERROR( CV_StsUnmatchedSizes, "" ); 1018 1019 mat2_flag = mat2->type; 1020 } 1021 1022 size = cvGetMatSize( mat1 ); 1023 type = CV_MAT_TYPE(mat1->type); 1024 depth = CV_MAT_DEPTH(type); 1025 cn = CV_MAT_CN(type); 1026 1027 if( CV_IS_MAT_CONT( mat1->type & mat2_flag )) 1028 { 1029 size.width *= size.height; 1030 1031 if( size.width <= CV_MAX_INLINE_MAT_OP_SIZE && normType == 2 /* CV_L2 */ ) 1032 { 1033 if( depth == CV_32F ) 1034 { 1035 const float* src1data = mat1->data.fl; 1036 int size0 = size.width *= cn; 1037 1038 if( !mat2 || is_relative ) 1039 { 1040 do 1041 { 1042 double t = src1data[size.width-1]; 1043 norm += t*t; 1044 } 1045 while( --size.width ); 1046 } 1047 1048 if( mat2 ) 1049 { 1050 const float* src2data = mat2->data.fl; 1051 size.width = size0; 1052 1053 do 1054 { 1055 double t = src1data[size.width-1] - src2data[size.width-1]; 1056 norm_diff += t*t; 1057 } 1058 while( --size.width ); 1059 1060 if( is_relative ) 1061 norm = norm_diff/(norm + DBL_EPSILON); 1062 else 1063 norm = norm_diff; 1064 } 1065 norm = sqrt(norm); 1066 EXIT; 1067 } 1068 1069 if( depth == CV_64F ) 1070 { 1071 const double* src1data = mat1->data.db; 1072 int size0 = size.width *= cn; 1073 1074 if( !mat2 || is_relative ) 1075 { 1076 do 1077 { 1078 double t = src1data[size.width-1]; 1079 norm += t*t; 1080 } 1081 while( --size.width ); 1082 } 1083 1084 if( mat2 ) 1085 { 1086 const double* src2data = mat2->data.db; 1087 size.width = size0; 1088 1089 do 1090 { 1091 double t = src1data[size.width-1] - src2data[size.width-1]; 1092 norm_diff += t*t; 1093 } 1094 while( --size.width ); 1095 1096 if( is_relative ) 1097 norm = norm_diff/(norm + DBL_EPSILON); 1098 else 1099 norm = norm_diff; 1100 } 1101 norm = sqrt(norm); 1102 EXIT; 1103 } 1104 } 1105 size.height = 1; 1106 mat1_step = mat2_step = CV_STUB_STEP; 1107 } 1108 else 1109 { 1110 mat1_step = mat1->step; 1111 mat2_step = mat2 ? mat2->step : 0; 1112 } 1113 } 1114 else if( !CV_IS_MATND(mat1) && !CV_IS_MATND(mat2) ) 1115 { 1116 CV_CALL( mat1 = cvGetMat( mat1, &stub1, &coi )); 1117 1118 if( mat2 ) 1119 { 1120 CV_CALL( mat2 = cvGetMat( mat2, &stub2, &coi2 )); 1121 1122 if( !CV_ARE_TYPES_EQ( mat1, mat2 )) 1123 CV_ERROR( CV_StsUnmatchedFormats, "" ); 1124 1125 if( !CV_ARE_SIZES_EQ( mat1, mat2 )) 1126 CV_ERROR( CV_StsUnmatchedSizes, "" ); 1127 1128 if( coi != coi2 && CV_MAT_CN( mat1->type ) > 1 ) 1129 CV_ERROR( CV_BadCOI, "" ); 1130 1131 mat2_flag = mat2->type; 1132 } 1133 1134 size = cvGetMatSize( mat1 ); 1135 type = CV_MAT_TYPE(mat1->type); 1136 depth = CV_MAT_DEPTH(type); 1137 cn = CV_MAT_CN(type); 1138 mat1_step = mat1->step; 1139 mat2_step = mat2 ? mat2->step : 0; 1140 1141 if( !mask && CV_IS_MAT_CONT( mat1->type & mat2_flag )) 1142 { 1143 size.width *= size.height; 1144 size.height = 1; 1145 mat1_step = mat2_step = CV_STUB_STEP; 1146 } 1147 } 1148 else 1149 { 1150 CvArr* arrs[] = { mat1, mat2 }; 1151 CvMatND stubs[2]; 1152 CvNArrayIterator iterator; 1153 int pass_hint; 1154 1155 if( !inittab ) 1156 { 1157 icvInitNormTabs( norm_tab, normmask_tab ); 1158 inittab = 1; 1159 } 1160 1161 if( mask ) 1162 CV_ERROR( CV_StsBadMask, 1163 "This operation on multi-dimensional arrays does not support mask" ); 1164 1165 CV_CALL( cvInitNArrayIterator( 1 + (mat2 != 0), arrs, 0, stubs, &iterator )); 1166 1167 type = CV_MAT_TYPE(iterator.hdr[0]->type); 1168 depth = CV_MAT_DEPTH(type); 1169 iterator.size.width *= CV_MAT_CN(type); 1170 1171 pass_hint = normType != 0 && (depth == CV_32F); 1172 1173 if( !mat2 || is_relative ) 1174 { 1175 if( !pass_hint ) 1176 { 1177 CvFunc2D_1A1P func; 1178 1179 CV_GET_FUNC_PTR( func, (CvFunc2D_1A1P)norm_tab[normType].fn_2d[depth]); 1180 1181 do 1182 { 1183 double temp = 0; 1184 IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP, 1185 iterator.size, &temp )); 1186 norm += temp; 1187 } 1188 while( cvNextNArraySlice( &iterator )); 1189 } 1190 else 1191 { 1192 CvFunc2D_1A1P1I func; 1193 1194 CV_GET_FUNC_PTR( func, (CvFunc2D_1A1P1I)norm_tab[normType].fn_2d[depth]); 1195 1196 do 1197 { 1198 double temp = 0; 1199 IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP, 1200 iterator.size, &temp, cvAlgHintAccurate )); 1201 norm += temp; 1202 } 1203 while( cvNextNArraySlice( &iterator )); 1204 } 1205 } 1206 1207 if( mat2 ) 1208 { 1209 if( !pass_hint ) 1210 { 1211 CvFunc2D_2A1P func; 1212 CV_GET_FUNC_PTR( func, (CvFunc2D_2A1P)norm_tab[3 + normType].fn_2d[depth]); 1213 1214 do 1215 { 1216 double temp = 0; 1217 IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP, 1218 iterator.ptr[1], CV_STUB_STEP, 1219 iterator.size, &temp )); 1220 norm_diff += temp; 1221 } 1222 while( cvNextNArraySlice( &iterator )); 1223 } 1224 else 1225 { 1226 CvFunc2D_2A1P1I func; 1227 CV_GET_FUNC_PTR( func, (CvFunc2D_2A1P1I)norm_tab[3 + normType].fn_2d[depth]); 1228 1229 do 1230 { 1231 double temp = 0; 1232 IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP, 1233 iterator.ptr[1], CV_STUB_STEP, 1234 iterator.size, &temp, cvAlgHintAccurate )); 1235 norm_diff += temp; 1236 } 1237 while( cvNextNArraySlice( &iterator )); 1238 } 1239 1240 if( is_relative ) 1241 norm = norm_diff/(norm + DBL_EPSILON); 1242 else 1243 norm = norm_diff; 1244 } 1245 EXIT; 1246 } 1247 1248 if( !inittab ) 1249 { 1250 icvInitNormTabs( norm_tab, normmask_tab ); 1251 inittab = 1; 1252 } 1253 1254 if( !mask ) 1255 { 1256 if( cn == 1 || coi == 0 ) 1257 { 1258 int pass_hint = depth == CV_32F && normType != 0; 1259 size.width *= cn; 1260 1261 if( !mat2 || is_relative ) 1262 { 1263 if( !pass_hint ) 1264 { 1265 CvFunc2D_1A1P func; 1266 CV_GET_FUNC_PTR( func, (CvFunc2D_1A1P)norm_tab[normType].fn_2d[depth]); 1267 1268 IPPI_CALL( func( mat1->data.ptr, mat1_step, size, &norm )); 1269 } 1270 else 1271 { 1272 CvFunc2D_1A1P1I func; 1273 CV_GET_FUNC_PTR( func, (CvFunc2D_1A1P1I)norm_tab[normType].fn_2d[depth]); 1274 1275 IPPI_CALL( func( mat1->data.ptr, mat1_step, size, &norm, cvAlgHintAccurate )); 1276 } 1277 } 1278 1279 if( mat2 ) 1280 { 1281 if( !pass_hint ) 1282 { 1283 CvFunc2D_2A1P func; 1284 CV_GET_FUNC_PTR( func, (CvFunc2D_2A1P)norm_tab[3 + normType].fn_2d[depth]); 1285 1286 IPPI_CALL( func( mat1->data.ptr, mat1_step, mat2->data.ptr, mat2_step, 1287 size, &norm_diff )); 1288 } 1289 else 1290 { 1291 CvFunc2D_2A1P1I func; 1292 CV_GET_FUNC_PTR( func, (CvFunc2D_2A1P1I)norm_tab[3 + normType].fn_2d[depth]); 1293 1294 IPPI_CALL( func( mat1->data.ptr, mat1_step, mat2->data.ptr, mat2_step, 1295 size, &norm_diff, cvAlgHintAccurate )); 1296 } 1297 1298 if( is_relative ) 1299 norm = norm_diff/(norm + DBL_EPSILON); 1300 else 1301 norm = norm_diff; 1302 } 1303 } 1304 else 1305 { 1306 if( !mat2 || is_relative ) 1307 { 1308 CvFunc2DnC_1A1P func; 1309 CV_GET_FUNC_PTR( func, (CvFunc2DnC_1A1P)norm_tab[6 + normType].fn_2d[depth]); 1310 1311 IPPI_CALL( func( mat1->data.ptr, mat1_step, size, cn, coi, &norm )); 1312 } 1313 1314 if( mat2 ) 1315 { 1316 CvFunc2DnC_2A1P func; 1317 CV_GET_FUNC_PTR( func, (CvFunc2DnC_2A1P)norm_tab[9 + normType].fn_2d[depth]); 1318 1319 IPPI_CALL( func( mat1->data.ptr, mat1_step, mat2->data.ptr, mat2_step, 1320 size, cn, coi, &norm_diff )); 1321 1322 if( is_relative ) 1323 norm = norm_diff/(norm + DBL_EPSILON); 1324 else 1325 norm = norm_diff; 1326 } 1327 } 1328 } 1329 else 1330 { 1331 CvMat maskstub, *matmask = (CvMat*)mask; 1332 1333 if( CV_MAT_CN(type) > 1 && coi == 0 ) 1334 CV_ERROR( CV_StsBadArg, "" ); 1335 1336 CV_CALL( matmask = cvGetMat( matmask, &maskstub )); 1337 1338 if( !CV_IS_MASK_ARR( matmask )) 1339 CV_ERROR( CV_StsBadMask, "" ); 1340 1341 if( !CV_ARE_SIZES_EQ( mat1, matmask )) 1342 CV_ERROR( CV_StsUnmatchedSizes, "" ); 1343 1344 mask_step = matmask->step; 1345 1346 if( CV_IS_MAT_CONT( mat1->type & mat2_flag & matmask->type )) 1347 { 1348 size.width *= size.height; 1349 size.height = 1; 1350 mat1_step = mat2_step = mask_step = CV_STUB_STEP; 1351 } 1352 1353 if( CV_MAT_CN(type) == 1 || coi == 0 ) 1354 { 1355 if( !mat2 || is_relative ) 1356 { 1357 CvFunc2D_2A1P func; 1358 CV_GET_FUNC_PTR( func, 1359 (CvFunc2D_2A1P)normmask_tab[normType].fn_2d[depth]); 1360 1361 IPPI_CALL( func( mat1->data.ptr, mat1_step, 1362 matmask->data.ptr, mask_step, size, &norm )); 1363 } 1364 1365 if( mat2 ) 1366 { 1367 CvFunc2D_3A1P func; 1368 CV_GET_FUNC_PTR( func, 1369 (CvFunc2D_3A1P)normmask_tab[3 + normType].fn_2d[depth]); 1370 1371 IPPI_CALL( func( mat1->data.ptr, mat1_step, mat2->data.ptr, mat2_step, 1372 matmask->data.ptr, mask_step, size, &norm_diff )); 1373 1374 if( is_relative ) 1375 norm = norm_diff/(norm + DBL_EPSILON); 1376 else 1377 norm = norm_diff; 1378 } 1379 } 1380 else 1381 { 1382 if( !mat2 || is_relative ) 1383 { 1384 CvFunc2DnC_2A1P func; 1385 CV_GET_FUNC_PTR( func, 1386 (CvFunc2DnC_2A1P)normmask_tab[6 + normType].fn_2d[depth]); 1387 1388 IPPI_CALL( func( mat1->data.ptr, mat1_step, 1389 matmask->data.ptr, mask_step, 1390 size, cn, coi, &norm )); 1391 } 1392 1393 if( mat2 ) 1394 { 1395 CvFunc2DnC_3A1P func; 1396 CV_GET_FUNC_PTR( func, 1397 (CvFunc2DnC_3A1P)normmask_tab[9 + normType].fn_2d[depth]); 1398 1399 IPPI_CALL( func( mat1->data.ptr, mat1_step, 1400 mat2->data.ptr, mat2_step, 1401 matmask->data.ptr, mask_step, 1402 size, cn, coi, &norm_diff )); 1403 1404 if( is_relative ) 1405 norm = norm_diff/(norm + DBL_EPSILON); 1406 else 1407 norm = norm_diff; 1408 } 1409 } 1410 } 1411 1412 __END__; 1413 1414 return norm; 1415 } 1416 1417 /* End of file. */ 1418