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 // License Agreement 11 // For Open Source Computer Vision Library 12 // 13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. 14 // Copyright (C) 2009-2010, Willow Garage Inc., all rights reserved. 15 // Third party copyrights are property of their respective owners. 16 // 17 // Redistribution and use in source and binary forms, with or without modification, 18 // are permitted provided that the following conditions are met: 19 // 20 // * Redistribution's of source code must retain the above copyright notice, 21 // this list of conditions and the following disclaimer. 22 // 23 // * Redistribution's in binary form must reproduce the above copyright notice, 24 // this list of conditions and the following disclaimer in the documentation 25 // and/or other materials provided with the distribution. 26 // 27 // * The name of the copyright holders may not be used to endorse or promote products 28 // derived from this software without specific prior written permission. 29 // 30 // This software is provided by the copyright holders and contributors "as is" and 31 // any express or implied warranties, including, but not limited to, the implied 32 // warranties of merchantability and fitness for a particular purpose are disclaimed. 33 // In no event shall the Intel Corporation or contributors be liable for any direct, 34 // indirect, incidental, special, exemplary, or consequential damages 35 // (including, but not limited to, procurement of substitute goods or services; 36 // loss of use, data, or profits; or business interruption) however caused 37 // and on any theory of liability, whether in contract, strict liability, 38 // or tort (including negligence or otherwise) arising in any way out of 39 // the use of this software, even if advised of the possibility of such damage. 40 // 41 //M*/ 42 43 /* //////////////////////////////////////////////////////////////////// 44 // 45 // Mat basic operations: Copy, Set 46 // 47 // */ 48 49 #include "precomp.hpp" 50 51 namespace cv 52 { 53 54 class MatOp_Identity : public MatOp 55 { 56 public: 57 MatOp_Identity() {} 58 virtual ~MatOp_Identity() {} 59 60 bool elementWise(const MatExpr& /*expr*/) const { return true; } 61 void assign(const MatExpr& expr, Mat& m, int type=-1) const; 62 63 static void makeExpr(MatExpr& res, const Mat& m); 64 }; 65 66 static MatOp_Identity g_MatOp_Identity; 67 68 class MatOp_AddEx : public MatOp 69 { 70 public: 71 MatOp_AddEx() {} 72 virtual ~MatOp_AddEx() {} 73 74 bool elementWise(const MatExpr& /*expr*/) const { return true; } 75 void assign(const MatExpr& expr, Mat& m, int type=-1) const; 76 77 void add(const MatExpr& e1, const Scalar& s, MatExpr& res) const; 78 void subtract(const Scalar& s, const MatExpr& expr, MatExpr& res) const; 79 void multiply(const MatExpr& e1, double s, MatExpr& res) const; 80 void divide(double s, const MatExpr& e, MatExpr& res) const; 81 82 void transpose(const MatExpr& e1, MatExpr& res) const; 83 void abs(const MatExpr& expr, MatExpr& res) const; 84 85 static void makeExpr(MatExpr& res, const Mat& a, const Mat& b, double alpha, double beta, const Scalar& s=Scalar()); 86 }; 87 88 static MatOp_AddEx g_MatOp_AddEx; 89 90 class MatOp_Bin : public MatOp 91 { 92 public: 93 MatOp_Bin() {} 94 virtual ~MatOp_Bin() {} 95 96 bool elementWise(const MatExpr& /*expr*/) const { return true; } 97 void assign(const MatExpr& expr, Mat& m, int type=-1) const; 98 99 void multiply(const MatExpr& e1, double s, MatExpr& res) const; 100 void divide(double s, const MatExpr& e, MatExpr& res) const; 101 102 static void makeExpr(MatExpr& res, char op, const Mat& a, const Mat& b, double scale=1); 103 static void makeExpr(MatExpr& res, char op, const Mat& a, const Scalar& s); 104 }; 105 106 static MatOp_Bin g_MatOp_Bin; 107 108 class MatOp_Cmp : public MatOp 109 { 110 public: 111 MatOp_Cmp() {} 112 virtual ~MatOp_Cmp() {} 113 114 bool elementWise(const MatExpr& /*expr*/) const { return true; } 115 void assign(const MatExpr& expr, Mat& m, int type=-1) const; 116 117 static void makeExpr(MatExpr& res, int cmpop, const Mat& a, const Mat& b); 118 static void makeExpr(MatExpr& res, int cmpop, const Mat& a, double alpha); 119 }; 120 121 static MatOp_Cmp g_MatOp_Cmp; 122 123 class MatOp_GEMM : public MatOp 124 { 125 public: 126 MatOp_GEMM() {} 127 virtual ~MatOp_GEMM() {} 128 129 bool elementWise(const MatExpr& /*expr*/) const { return false; } 130 void assign(const MatExpr& expr, Mat& m, int type=-1) const; 131 132 void add(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const; 133 void subtract(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const; 134 void multiply(const MatExpr& e, double s, MatExpr& res) const; 135 136 void transpose(const MatExpr& expr, MatExpr& res) const; 137 138 static void makeExpr(MatExpr& res, int flags, const Mat& a, const Mat& b, 139 double alpha=1, const Mat& c=Mat(), double beta=1); 140 }; 141 142 static MatOp_GEMM g_MatOp_GEMM; 143 144 class MatOp_Invert : public MatOp 145 { 146 public: 147 MatOp_Invert() {} 148 virtual ~MatOp_Invert() {} 149 150 bool elementWise(const MatExpr& /*expr*/) const { return false; } 151 void assign(const MatExpr& expr, Mat& m, int type=-1) const; 152 153 void matmul(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res) const; 154 155 static void makeExpr(MatExpr& res, int method, const Mat& m); 156 }; 157 158 static MatOp_Invert g_MatOp_Invert; 159 160 class MatOp_T : public MatOp 161 { 162 public: 163 MatOp_T() {} 164 virtual ~MatOp_T() {} 165 166 bool elementWise(const MatExpr& /*expr*/) const { return false; } 167 void assign(const MatExpr& expr, Mat& m, int type=-1) const; 168 169 void multiply(const MatExpr& e1, double s, MatExpr& res) const; 170 void transpose(const MatExpr& expr, MatExpr& res) const; 171 172 static void makeExpr(MatExpr& res, const Mat& a, double alpha=1); 173 }; 174 175 static MatOp_T g_MatOp_T; 176 177 class MatOp_Solve : public MatOp 178 { 179 public: 180 MatOp_Solve() {} 181 virtual ~MatOp_Solve() {} 182 183 bool elementWise(const MatExpr& /*expr*/) const { return false; } 184 void assign(const MatExpr& expr, Mat& m, int type=-1) const; 185 186 static void makeExpr(MatExpr& res, int method, const Mat& a, const Mat& b); 187 }; 188 189 static MatOp_Solve g_MatOp_Solve; 190 191 class MatOp_Initializer : public MatOp 192 { 193 public: 194 MatOp_Initializer() {} 195 virtual ~MatOp_Initializer() {} 196 197 bool elementWise(const MatExpr& /*expr*/) const { return false; } 198 void assign(const MatExpr& expr, Mat& m, int type=-1) const; 199 200 void multiply(const MatExpr& e, double s, MatExpr& res) const; 201 202 static void makeExpr(MatExpr& res, int method, Size sz, int type, double alpha=1); 203 static void makeExpr(MatExpr& res, int method, int ndims, const int* sizes, int type, double alpha=1); 204 }; 205 206 static MatOp_Initializer* getGlobalMatOpInitializer() 207 { 208 static MatOp_Initializer initializer; 209 return &initializer; 210 } 211 212 static inline bool isIdentity(const MatExpr& e) { return e.op == &g_MatOp_Identity; } 213 static inline bool isAddEx(const MatExpr& e) { return e.op == &g_MatOp_AddEx; } 214 static inline bool isScaled(const MatExpr& e) { return isAddEx(e) && (!e.b.data || e.beta == 0) && e.s == Scalar(); } 215 static inline bool isBin(const MatExpr& e, char c) { return e.op == &g_MatOp_Bin && e.flags == c; } 216 static inline bool isCmp(const MatExpr& e) { return e.op == &g_MatOp_Cmp; } 217 static inline bool isReciprocal(const MatExpr& e) { return isBin(e,'/') && (!e.b.data || e.beta == 0); } 218 static inline bool isT(const MatExpr& e) { return e.op == &g_MatOp_T; } 219 static inline bool isInv(const MatExpr& e) { return e.op == &g_MatOp_Invert; } 220 static inline bool isSolve(const MatExpr& e) { return e.op == &g_MatOp_Solve; } 221 static inline bool isGEMM(const MatExpr& e) { return e.op == &g_MatOp_GEMM; } 222 static inline bool isMatProd(const MatExpr& e) { return e.op == &g_MatOp_GEMM && (!e.c.data || e.beta == 0); } 223 static inline bool isInitializer(const MatExpr& e) { return e.op == getGlobalMatOpInitializer(); } 224 225 ///////////////////////////////////////////////////////////////////////////////////////////////////// 226 227 MatOp::MatOp() {} 228 MatOp::~MatOp() {} 229 230 231 bool MatOp::elementWise(const MatExpr& /*expr*/) const 232 { 233 return false; 234 } 235 236 void MatOp::roi(const MatExpr& expr, const Range& rowRange, const Range& colRange, MatExpr& e) const 237 { 238 if( elementWise(expr) ) 239 { 240 e = MatExpr(expr.op, expr.flags, Mat(), Mat(), Mat(), 241 expr.alpha, expr.beta, expr.s); 242 if(expr.a.data) 243 e.a = expr.a(rowRange, colRange); 244 if(expr.b.data) 245 e.b = expr.b(rowRange, colRange); 246 if(expr.c.data) 247 e.c = expr.c(rowRange, colRange); 248 } 249 else 250 { 251 Mat m; 252 expr.op->assign(expr, m); 253 e = MatExpr(&g_MatOp_Identity, 0, m(rowRange, colRange), Mat(), Mat()); 254 } 255 } 256 257 void MatOp::diag(const MatExpr& expr, int d, MatExpr& e) const 258 { 259 if( elementWise(expr) ) 260 { 261 e = MatExpr(expr.op, expr.flags, Mat(), Mat(), Mat(), 262 expr.alpha, expr.beta, expr.s); 263 if(expr.a.data) 264 e.a = expr.a.diag(d); 265 if(expr.b.data) 266 e.b = expr.b.diag(d); 267 if(expr.c.data) 268 e.c = expr.c.diag(d); 269 } 270 else 271 { 272 Mat m; 273 expr.op->assign(expr, m); 274 e = MatExpr(&g_MatOp_Identity, 0, m.diag(d), Mat(), Mat()); 275 } 276 } 277 278 279 void MatOp::augAssignAdd(const MatExpr& expr, Mat& m) const 280 { 281 Mat temp; 282 expr.op->assign(expr, temp); 283 m += temp; 284 } 285 286 287 void MatOp::augAssignSubtract(const MatExpr& expr, Mat& m) const 288 { 289 Mat temp; 290 expr.op->assign(expr, temp); 291 m -= temp; 292 } 293 294 295 void MatOp::augAssignMultiply(const MatExpr& expr, Mat& m) const 296 { 297 Mat temp; 298 expr.op->assign(expr, temp); 299 m *= temp; 300 } 301 302 303 void MatOp::augAssignDivide(const MatExpr& expr, Mat& m) const 304 { 305 Mat temp; 306 expr.op->assign(expr, temp); 307 m /= temp; 308 } 309 310 311 void MatOp::augAssignAnd(const MatExpr& expr, Mat& m) const 312 { 313 Mat temp; 314 expr.op->assign(expr, temp); 315 m &= temp; 316 } 317 318 319 void MatOp::augAssignOr(const MatExpr& expr, Mat& m) const 320 { 321 Mat temp; 322 expr.op->assign(expr, temp); 323 m |= temp; 324 } 325 326 327 void MatOp::augAssignXor(const MatExpr& expr, Mat& m) const 328 { 329 Mat temp; 330 expr.op->assign(expr, temp); 331 m ^= temp; 332 } 333 334 335 void MatOp::add(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const 336 { 337 if( this == e2.op ) 338 { 339 double alpha = 1, beta = 1; 340 Scalar s; 341 Mat m1, m2; 342 if( isAddEx(e1) && (!e1.b.data || e1.beta == 0) ) 343 { 344 m1 = e1.a; 345 alpha = e1.alpha; 346 s = e1.s; 347 } 348 else 349 e1.op->assign(e1, m1); 350 351 if( isAddEx(e2) && (!e2.b.data || e2.beta == 0) ) 352 { 353 m2 = e2.a; 354 beta = e2.alpha; 355 s += e2.s; 356 } 357 else 358 e2.op->assign(e2, m2); 359 MatOp_AddEx::makeExpr(res, m1, m2, alpha, beta, s); 360 } 361 else 362 e2.op->add(e1, e2, res); 363 } 364 365 366 void MatOp::add(const MatExpr& expr1, const Scalar& s, MatExpr& res) const 367 { 368 Mat m1; 369 expr1.op->assign(expr1, m1); 370 MatOp_AddEx::makeExpr(res, m1, Mat(), 1, 0, s); 371 } 372 373 374 void MatOp::subtract(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const 375 { 376 if( this == e2.op ) 377 { 378 double alpha = 1, beta = -1; 379 Scalar s; 380 Mat m1, m2; 381 if( isAddEx(e1) && (!e1.b.data || e1.beta == 0) ) 382 { 383 m1 = e1.a; 384 alpha = e1.alpha; 385 s = e1.s; 386 } 387 else 388 e1.op->assign(e1, m1); 389 390 if( isAddEx(e2) && (!e2.b.data || e2.beta == 0) ) 391 { 392 m2 = e2.a; 393 beta = -e2.alpha; 394 s -= e2.s; 395 } 396 else 397 e2.op->assign(e2, m2); 398 MatOp_AddEx::makeExpr(res, m1, m2, alpha, beta, s); 399 } 400 else 401 e2.op->subtract(e1, e2, res); 402 } 403 404 405 void MatOp::subtract(const Scalar& s, const MatExpr& expr, MatExpr& res) const 406 { 407 Mat m; 408 expr.op->assign(expr, m); 409 MatOp_AddEx::makeExpr(res, m, Mat(), -1, 0, s); 410 } 411 412 413 void MatOp::multiply(const MatExpr& e1, const MatExpr& e2, MatExpr& res, double scale) const 414 { 415 if( this == e2.op ) 416 { 417 Mat m1, m2; 418 419 if( isReciprocal(e1) ) 420 { 421 if( isScaled(e2) ) 422 { 423 scale *= e2.alpha; 424 m2 = e2.a; 425 } 426 else 427 e2.op->assign(e2, m2); 428 429 MatOp_Bin::makeExpr(res, '/', m2, e1.a, scale/e1.alpha); 430 } 431 else 432 { 433 char op = '*'; 434 if( isScaled(e1) ) 435 { 436 m1 = e1.a; 437 scale *= e1.alpha; 438 } 439 else 440 e1.op->assign(e1, m1); 441 442 if( isScaled(e2) ) 443 { 444 m2 = e2.a; 445 scale *= e2.alpha; 446 } 447 else if( isReciprocal(e2) ) 448 { 449 op = '/'; 450 m2 = e2.a; 451 scale /= e2.alpha; 452 } 453 else 454 e2.op->assign(e2, m2); 455 456 MatOp_Bin::makeExpr(res, op, m1, m2, scale); 457 } 458 } 459 else 460 e2.op->multiply(e1, e2, res, scale); 461 } 462 463 464 void MatOp::multiply(const MatExpr& expr, double s, MatExpr& res) const 465 { 466 Mat m; 467 expr.op->assign(expr, m); 468 MatOp_AddEx::makeExpr(res, m, Mat(), s, 0); 469 } 470 471 472 void MatOp::divide(const MatExpr& e1, const MatExpr& e2, MatExpr& res, double scale) const 473 { 474 if( this == e2.op ) 475 { 476 if( isReciprocal(e1) && isReciprocal(e2) ) 477 MatOp_Bin::makeExpr(res, '/', e2.a, e1.a, e1.alpha/e2.alpha); 478 else 479 { 480 Mat m1, m2; 481 char op = '/'; 482 483 if( isScaled(e1) ) 484 { 485 m1 = e1.a; 486 scale *= e1.alpha; 487 } 488 else 489 e1.op->assign(e1, m1); 490 491 if( isScaled(e2) ) 492 { 493 m2 = e2.a; 494 scale /= e2.alpha; 495 } 496 else if( isReciprocal(e2) ) 497 { 498 m2 = e2.a; 499 scale /= e2.alpha; 500 op = '*'; 501 } 502 else 503 e2.op->assign(e2, m2); 504 MatOp_Bin::makeExpr(res, op, m1, m2, scale); 505 } 506 } 507 else 508 e2.op->divide(e1, e2, res, scale); 509 } 510 511 512 void MatOp::divide(double s, const MatExpr& expr, MatExpr& res) const 513 { 514 Mat m; 515 expr.op->assign(expr, m); 516 MatOp_Bin::makeExpr(res, '/', m, Mat(), s); 517 } 518 519 520 void MatOp::abs(const MatExpr& expr, MatExpr& res) const 521 { 522 Mat m; 523 expr.op->assign(expr, m); 524 MatOp_Bin::makeExpr(res, 'a', m, Mat()); 525 } 526 527 528 void MatOp::transpose(const MatExpr& expr, MatExpr& res) const 529 { 530 Mat m; 531 expr.op->assign(expr, m); 532 MatOp_T::makeExpr(res, m, 1); 533 } 534 535 536 void MatOp::matmul(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const 537 { 538 if( this == e2.op ) 539 { 540 double scale = 1; 541 int flags = 0; 542 Mat m1, m2; 543 544 if( isT(e1) ) 545 { 546 flags = CV_GEMM_A_T; 547 scale = e1.alpha; 548 m1 = e1.a; 549 } 550 else if( isScaled(e1) ) 551 { 552 scale = e1.alpha; 553 m1 = e1.a; 554 } 555 else 556 e1.op->assign(e1, m1); 557 558 if( isT(e2) ) 559 { 560 flags |= CV_GEMM_B_T; 561 scale *= e2.alpha; 562 m2 = e2.a; 563 } 564 else if( isScaled(e2) ) 565 { 566 scale *= e2.alpha; 567 m2 = e2.a; 568 } 569 else 570 e2.op->assign(e2, m2); 571 572 MatOp_GEMM::makeExpr(res, flags, m1, m2, scale); 573 } 574 else 575 e2.op->matmul(e1, e2, res); 576 } 577 578 579 void MatOp::invert(const MatExpr& expr, int method, MatExpr& res) const 580 { 581 Mat m; 582 expr.op->assign(expr, m); 583 MatOp_Invert::makeExpr(res, method, m); 584 } 585 586 587 Size MatOp::size(const MatExpr& expr) const 588 { 589 return !expr.a.empty() ? expr.a.size() : expr.b.empty() ? expr.b.size() : expr.c.size(); 590 } 591 592 int MatOp::type(const MatExpr& expr) const 593 { 594 return !expr.a.empty() ? expr.a.type() : expr.b.empty() ? expr.b.type() : expr.c.type(); 595 } 596 597 ////////////////////////////////////////////////////////////////////////////////////////////////// 598 599 MatExpr::MatExpr(const Mat& m) : op(&g_MatOp_Identity), flags(0), a(m), b(Mat()), c(Mat()), alpha(1), beta(0), s(Scalar()) 600 { 601 } 602 603 MatExpr MatExpr::row(int y) const 604 { 605 MatExpr e; 606 op->roi(*this, Range(y, y+1), Range::all(), e); 607 return e; 608 } 609 610 MatExpr MatExpr::col(int x) const 611 { 612 MatExpr e; 613 op->roi(*this, Range::all(), Range(x, x+1), e); 614 return e; 615 } 616 617 MatExpr MatExpr::diag(int d) const 618 { 619 MatExpr e; 620 op->diag(*this, d, e); 621 return e; 622 } 623 624 MatExpr MatExpr::operator()( const Range& rowRange, const Range& colRange ) const 625 { 626 MatExpr e; 627 op->roi(*this, rowRange, colRange, e); 628 return e; 629 } 630 631 MatExpr MatExpr::operator()( const Rect& roi ) const 632 { 633 MatExpr e; 634 op->roi(*this, Range(roi.y, roi.y + roi.height), Range(roi.x, roi.x + roi.width), e); 635 return e; 636 } 637 638 Mat MatExpr::cross(const Mat& m) const 639 { 640 return ((Mat)*this).cross(m); 641 } 642 643 double MatExpr::dot(const Mat& m) const 644 { 645 return ((Mat)*this).dot(m); 646 } 647 648 MatExpr MatExpr::t() const 649 { 650 MatExpr e; 651 op->transpose(*this, e); 652 return e; 653 } 654 655 MatExpr MatExpr::inv(int method) const 656 { 657 MatExpr e; 658 op->invert(*this, method, e); 659 return e; 660 } 661 662 MatExpr MatExpr::mul(const MatExpr& e, double scale) const 663 { 664 MatExpr en; 665 op->multiply(*this, e, en, scale); 666 return en; 667 } 668 669 MatExpr MatExpr::mul(const Mat& m, double scale) const 670 { 671 MatExpr e; 672 op->multiply(*this, MatExpr(m), e, scale); 673 return e; 674 } 675 676 MatExpr operator + (const Mat& a, const Mat& b) 677 { 678 MatExpr e; 679 MatOp_AddEx::makeExpr(e, a, b, 1, 1); 680 return e; 681 } 682 683 MatExpr operator + (const Mat& a, const Scalar& s) 684 { 685 MatExpr e; 686 MatOp_AddEx::makeExpr(e, a, Mat(), 1, 0, s); 687 return e; 688 } 689 690 MatExpr operator + (const Scalar& s, const Mat& a) 691 { 692 MatExpr e; 693 MatOp_AddEx::makeExpr(e, a, Mat(), 1, 0, s); 694 return e; 695 } 696 697 MatExpr operator + (const MatExpr& e, const Mat& m) 698 { 699 MatExpr en; 700 e.op->add(e, MatExpr(m), en); 701 return en; 702 } 703 704 MatExpr operator + (const Mat& m, const MatExpr& e) 705 { 706 MatExpr en; 707 e.op->add(e, MatExpr(m), en); 708 return en; 709 } 710 711 MatExpr operator + (const MatExpr& e, const Scalar& s) 712 { 713 MatExpr en; 714 e.op->add(e, s, en); 715 return en; 716 } 717 718 MatExpr operator + (const Scalar& s, const MatExpr& e) 719 { 720 MatExpr en; 721 e.op->add(e, s, en); 722 return en; 723 } 724 725 MatExpr operator + (const MatExpr& e1, const MatExpr& e2) 726 { 727 MatExpr en; 728 e1.op->add(e1, e2, en); 729 return en; 730 } 731 732 MatExpr operator - (const Mat& a, const Mat& b) 733 { 734 MatExpr e; 735 MatOp_AddEx::makeExpr(e, a, b, 1, -1); 736 return e; 737 } 738 739 MatExpr operator - (const Mat& a, const Scalar& s) 740 { 741 MatExpr e; 742 MatOp_AddEx::makeExpr(e, a, Mat(), 1, 0, -s); 743 return e; 744 } 745 746 MatExpr operator - (const Scalar& s, const Mat& a) 747 { 748 MatExpr e; 749 MatOp_AddEx::makeExpr(e, a, Mat(), -1, 0, s); 750 return e; 751 } 752 753 MatExpr operator - (const MatExpr& e, const Mat& m) 754 { 755 MatExpr en; 756 e.op->subtract(e, MatExpr(m), en); 757 return en; 758 } 759 760 MatExpr operator - (const Mat& m, const MatExpr& e) 761 { 762 MatExpr en; 763 e.op->subtract(MatExpr(m), e, en); 764 return en; 765 } 766 767 MatExpr operator - (const MatExpr& e, const Scalar& s) 768 { 769 MatExpr en; 770 e.op->add(e, -s, en); 771 return en; 772 } 773 774 MatExpr operator - (const Scalar& s, const MatExpr& e) 775 { 776 MatExpr en; 777 e.op->subtract(s, e, en); 778 return en; 779 } 780 781 MatExpr operator - (const MatExpr& e1, const MatExpr& e2) 782 { 783 MatExpr en; 784 e1.op->subtract(e1, e2, en); 785 return en; 786 } 787 788 MatExpr operator - (const Mat& m) 789 { 790 MatExpr e; 791 MatOp_AddEx::makeExpr(e, m, Mat(), -1, 0); 792 return e; 793 } 794 795 MatExpr operator - (const MatExpr& e) 796 { 797 MatExpr en; 798 e.op->subtract(Scalar(0), e, en); 799 return en; 800 } 801 802 MatExpr operator * (const Mat& a, const Mat& b) 803 { 804 MatExpr e; 805 MatOp_GEMM::makeExpr(e, 0, a, b); 806 return e; 807 } 808 809 MatExpr operator * (const Mat& a, double s) 810 { 811 MatExpr e; 812 MatOp_AddEx::makeExpr(e, a, Mat(), s, 0); 813 return e; 814 } 815 816 MatExpr operator * (double s, const Mat& a) 817 { 818 MatExpr e; 819 MatOp_AddEx::makeExpr(e, a, Mat(), s, 0); 820 return e; 821 } 822 823 MatExpr operator * (const MatExpr& e, const Mat& m) 824 { 825 MatExpr en; 826 e.op->matmul(e, MatExpr(m), en); 827 return en; 828 } 829 830 MatExpr operator * (const Mat& m, const MatExpr& e) 831 { 832 MatExpr en; 833 e.op->matmul(MatExpr(m), e, en); 834 return en; 835 } 836 837 MatExpr operator * (const MatExpr& e, double s) 838 { 839 MatExpr en; 840 e.op->multiply(e, s, en); 841 return en; 842 } 843 844 MatExpr operator * (double s, const MatExpr& e) 845 { 846 MatExpr en; 847 e.op->multiply(e, s, en); 848 return en; 849 } 850 851 MatExpr operator * (const MatExpr& e1, const MatExpr& e2) 852 { 853 MatExpr en; 854 e1.op->matmul(e1, e2, en); 855 return en; 856 } 857 858 MatExpr operator / (const Mat& a, const Mat& b) 859 { 860 MatExpr e; 861 MatOp_Bin::makeExpr(e, '/', a, b); 862 return e; 863 } 864 865 MatExpr operator / (const Mat& a, double s) 866 { 867 MatExpr e; 868 MatOp_AddEx::makeExpr(e, a, Mat(), 1./s, 0); 869 return e; 870 } 871 872 MatExpr operator / (double s, const Mat& a) 873 { 874 MatExpr e; 875 MatOp_Bin::makeExpr(e, '/', a, Mat(), s); 876 return e; 877 } 878 879 MatExpr operator / (const MatExpr& e, const Mat& m) 880 { 881 MatExpr en; 882 e.op->divide(e, MatExpr(m), en); 883 return en; 884 } 885 886 MatExpr operator / (const Mat& m, const MatExpr& e) 887 { 888 MatExpr en; 889 e.op->divide(MatExpr(m), e, en); 890 return en; 891 } 892 893 MatExpr operator / (const MatExpr& e, double s) 894 { 895 MatExpr en; 896 e.op->multiply(e, 1./s, en); 897 return en; 898 } 899 900 MatExpr operator / (double s, const MatExpr& e) 901 { 902 MatExpr en; 903 e.op->divide(s, e, en); 904 return en; 905 } 906 907 MatExpr operator / (const MatExpr& e1, const MatExpr& e2) 908 { 909 MatExpr en; 910 e1.op->divide(e1, e2, en); 911 return en; 912 } 913 914 MatExpr operator < (const Mat& a, const Mat& b) 915 { 916 MatExpr e; 917 MatOp_Cmp::makeExpr(e, CV_CMP_LT, a, b); 918 return e; 919 } 920 921 MatExpr operator < (const Mat& a, double s) 922 { 923 MatExpr e; 924 MatOp_Cmp::makeExpr(e, CV_CMP_LT, a, s); 925 return e; 926 } 927 928 MatExpr operator < (double s, const Mat& a) 929 { 930 MatExpr e; 931 MatOp_Cmp::makeExpr(e, CV_CMP_GT, a, s); 932 return e; 933 } 934 935 MatExpr operator <= (const Mat& a, const Mat& b) 936 { 937 MatExpr e; 938 MatOp_Cmp::makeExpr(e, CV_CMP_LE, a, b); 939 return e; 940 } 941 942 MatExpr operator <= (const Mat& a, double s) 943 { 944 MatExpr e; 945 MatOp_Cmp::makeExpr(e, CV_CMP_LE, a, s); 946 return e; 947 } 948 949 MatExpr operator <= (double s, const Mat& a) 950 { 951 MatExpr e; 952 MatOp_Cmp::makeExpr(e, CV_CMP_GE, a, s); 953 return e; 954 } 955 956 MatExpr operator == (const Mat& a, const Mat& b) 957 { 958 MatExpr e; 959 MatOp_Cmp::makeExpr(e, CV_CMP_EQ, a, b); 960 return e; 961 } 962 963 MatExpr operator == (const Mat& a, double s) 964 { 965 MatExpr e; 966 MatOp_Cmp::makeExpr(e, CV_CMP_EQ, a, s); 967 return e; 968 } 969 970 MatExpr operator == (double s, const Mat& a) 971 { 972 MatExpr e; 973 MatOp_Cmp::makeExpr(e, CV_CMP_EQ, a, s); 974 return e; 975 } 976 977 MatExpr operator != (const Mat& a, const Mat& b) 978 { 979 MatExpr e; 980 MatOp_Cmp::makeExpr(e, CV_CMP_NE, a, b); 981 return e; 982 } 983 984 MatExpr operator != (const Mat& a, double s) 985 { 986 MatExpr e; 987 MatOp_Cmp::makeExpr(e, CV_CMP_NE, a, s); 988 return e; 989 } 990 991 MatExpr operator != (double s, const Mat& a) 992 { 993 MatExpr e; 994 MatOp_Cmp::makeExpr(e, CV_CMP_NE, a, s); 995 return e; 996 } 997 998 MatExpr operator >= (const Mat& a, const Mat& b) 999 { 1000 MatExpr e; 1001 MatOp_Cmp::makeExpr(e, CV_CMP_GE, a, b); 1002 return e; 1003 } 1004 1005 MatExpr operator >= (const Mat& a, double s) 1006 { 1007 MatExpr e; 1008 MatOp_Cmp::makeExpr(e, CV_CMP_GE, a, s); 1009 return e; 1010 } 1011 1012 MatExpr operator >= (double s, const Mat& a) 1013 { 1014 MatExpr e; 1015 MatOp_Cmp::makeExpr(e, CV_CMP_LE, a, s); 1016 return e; 1017 } 1018 1019 MatExpr operator > (const Mat& a, const Mat& b) 1020 { 1021 MatExpr e; 1022 MatOp_Cmp::makeExpr(e, CV_CMP_GT, a, b); 1023 return e; 1024 } 1025 1026 MatExpr operator > (const Mat& a, double s) 1027 { 1028 MatExpr e; 1029 MatOp_Cmp::makeExpr(e, CV_CMP_GT, a, s); 1030 return e; 1031 } 1032 1033 MatExpr operator > (double s, const Mat& a) 1034 { 1035 MatExpr e; 1036 MatOp_Cmp::makeExpr(e, CV_CMP_LT, a, s); 1037 return e; 1038 } 1039 1040 MatExpr min(const Mat& a, const Mat& b) 1041 { 1042 MatExpr e; 1043 MatOp_Bin::makeExpr(e, 'm', a, b); 1044 return e; 1045 } 1046 1047 MatExpr min(const Mat& a, double s) 1048 { 1049 MatExpr e; 1050 MatOp_Bin::makeExpr(e, 'n', a, s); 1051 return e; 1052 } 1053 1054 MatExpr min(double s, const Mat& a) 1055 { 1056 MatExpr e; 1057 MatOp_Bin::makeExpr(e, 'n', a, s); 1058 return e; 1059 } 1060 1061 MatExpr max(const Mat& a, const Mat& b) 1062 { 1063 MatExpr e; 1064 MatOp_Bin::makeExpr(e, 'M', a, b); 1065 return e; 1066 } 1067 1068 MatExpr max(const Mat& a, double s) 1069 { 1070 MatExpr e; 1071 MatOp_Bin::makeExpr(e, 'N', a, s); 1072 return e; 1073 } 1074 1075 MatExpr max(double s, const Mat& a) 1076 { 1077 MatExpr e; 1078 MatOp_Bin::makeExpr(e, 'N', a, s); 1079 return e; 1080 } 1081 1082 MatExpr operator & (const Mat& a, const Mat& b) 1083 { 1084 MatExpr e; 1085 MatOp_Bin::makeExpr(e, '&', a, b); 1086 return e; 1087 } 1088 1089 MatExpr operator & (const Mat& a, const Scalar& s) 1090 { 1091 MatExpr e; 1092 MatOp_Bin::makeExpr(e, '&', a, s); 1093 return e; 1094 } 1095 1096 MatExpr operator & (const Scalar& s, const Mat& a) 1097 { 1098 MatExpr e; 1099 MatOp_Bin::makeExpr(e, '&', a, s); 1100 return e; 1101 } 1102 1103 MatExpr operator | (const Mat& a, const Mat& b) 1104 { 1105 MatExpr e; 1106 MatOp_Bin::makeExpr(e, '|', a, b); 1107 return e; 1108 } 1109 1110 MatExpr operator | (const Mat& a, const Scalar& s) 1111 { 1112 MatExpr e; 1113 MatOp_Bin::makeExpr(e, '|', a, s); 1114 return e; 1115 } 1116 1117 MatExpr operator | (const Scalar& s, const Mat& a) 1118 { 1119 MatExpr e; 1120 MatOp_Bin::makeExpr(e, '|', a, s); 1121 return e; 1122 } 1123 1124 MatExpr operator ^ (const Mat& a, const Mat& b) 1125 { 1126 MatExpr e; 1127 MatOp_Bin::makeExpr(e, '^', a, b); 1128 return e; 1129 } 1130 1131 MatExpr operator ^ (const Mat& a, const Scalar& s) 1132 { 1133 MatExpr e; 1134 MatOp_Bin::makeExpr(e, '^', a, s); 1135 return e; 1136 } 1137 1138 MatExpr operator ^ (const Scalar& s, const Mat& a) 1139 { 1140 MatExpr e; 1141 MatOp_Bin::makeExpr(e, '^', a, s); 1142 return e; 1143 } 1144 1145 MatExpr operator ~(const Mat& a) 1146 { 1147 MatExpr e; 1148 MatOp_Bin::makeExpr(e, '~', a, Scalar()); 1149 return e; 1150 } 1151 1152 MatExpr abs(const Mat& a) 1153 { 1154 MatExpr e; 1155 MatOp_Bin::makeExpr(e, 'a', a, Scalar()); 1156 return e; 1157 } 1158 1159 MatExpr abs(const MatExpr& e) 1160 { 1161 MatExpr en; 1162 e.op->abs(e, en); 1163 return en; 1164 } 1165 1166 1167 Size MatExpr::size() const 1168 { 1169 if( isT(*this) || isInv(*this) ) 1170 return Size(a.rows, a.cols); 1171 if( isGEMM(*this) ) 1172 return Size(b.cols, a.rows); 1173 if( isSolve(*this) ) 1174 return Size(b.cols, a.cols); 1175 if( isInitializer(*this) ) 1176 return a.size(); 1177 return op ? op->size(*this) : Size(); 1178 } 1179 1180 1181 int MatExpr::type() const 1182 { 1183 if( isInitializer(*this) ) 1184 return a.type(); 1185 if( isCmp(*this) ) 1186 return CV_8U; 1187 return op ? op->type(*this) : -1; 1188 } 1189 1190 1191 ///////////////////////////////////////////////////////////////////////////////////////////////////// 1192 1193 void MatOp_Identity::assign(const MatExpr& e, Mat& m, int _type) const 1194 { 1195 if( _type == -1 || _type == e.a.type() ) 1196 m = e.a; 1197 else 1198 { 1199 CV_Assert( CV_MAT_CN(_type) == e.a.channels() ); 1200 e.a.convertTo(m, _type); 1201 } 1202 } 1203 1204 inline void MatOp_Identity::makeExpr(MatExpr& res, const Mat& m) 1205 { 1206 res = MatExpr(&g_MatOp_Identity, 0, m, Mat(), Mat(), 1, 0); 1207 } 1208 1209 ///////////////////////////////////////////////////////////////////////////////////////////////////// 1210 1211 void MatOp_AddEx::assign(const MatExpr& e, Mat& m, int _type) const 1212 { 1213 Mat temp, &dst = _type == -1 || e.a.type() == _type ? m : temp; 1214 if( e.b.data ) 1215 { 1216 if( e.s == Scalar() || !e.s.isReal() ) 1217 { 1218 if( e.alpha == 1 ) 1219 { 1220 if( e.beta == 1 ) 1221 cv::add(e.a, e.b, dst); 1222 else if( e.beta == -1 ) 1223 cv::subtract(e.a, e.b, dst); 1224 else 1225 cv::scaleAdd(e.b, e.beta, e.a, dst); 1226 } 1227 else if( e.beta == 1 ) 1228 { 1229 if( e.alpha == -1 ) 1230 cv::subtract(e.b, e.a, dst); 1231 else 1232 cv::scaleAdd(e.a, e.alpha, e.b, dst); 1233 } 1234 else 1235 cv::addWeighted(e.a, e.alpha, e.b, e.beta, 0, dst); 1236 1237 if( !e.s.isReal() ) 1238 cv::add(dst, e.s, dst); 1239 } 1240 else 1241 cv::addWeighted(e.a, e.alpha, e.b, e.beta, e.s[0], dst); 1242 } 1243 else if( e.s.isReal() && (dst.data != m.data || fabs(e.alpha) != 1)) 1244 { 1245 e.a.convertTo(m, _type, e.alpha, e.s[0]); 1246 return; 1247 } 1248 else if( e.alpha == 1 ) 1249 cv::add(e.a, e.s, dst); 1250 else if( e.alpha == -1 ) 1251 cv::subtract(e.s, e.a, dst); 1252 else 1253 { 1254 e.a.convertTo(dst, e.a.type(), e.alpha); 1255 cv::add(dst, e.s, dst); 1256 } 1257 1258 if( dst.data != m.data ) 1259 dst.convertTo(m, m.type()); 1260 } 1261 1262 1263 void MatOp_AddEx::add(const MatExpr& e, const Scalar& s, MatExpr& res) const 1264 { 1265 res = e; 1266 res.s += s; 1267 } 1268 1269 1270 void MatOp_AddEx::subtract(const Scalar& s, const MatExpr& e, MatExpr& res) const 1271 { 1272 res = e; 1273 res.alpha = -res.alpha; 1274 res.beta = -res.beta; 1275 res.s = s - res.s; 1276 } 1277 1278 void MatOp_AddEx::multiply(const MatExpr& e, double s, MatExpr& res) const 1279 { 1280 res = e; 1281 res.alpha *= s; 1282 res.beta *= s; 1283 res.s *= s; 1284 } 1285 1286 void MatOp_AddEx::divide(double s, const MatExpr& e, MatExpr& res) const 1287 { 1288 if( isScaled(e) ) 1289 MatOp_Bin::makeExpr(res, '/', e.a, Mat(), s/e.alpha); 1290 else 1291 MatOp::divide(s, e, res); 1292 } 1293 1294 1295 void MatOp_AddEx::transpose(const MatExpr& e, MatExpr& res) const 1296 { 1297 if( isScaled(e) ) 1298 MatOp_T::makeExpr(res, e.a, e.alpha); 1299 else 1300 MatOp::transpose(e, res); 1301 } 1302 1303 void MatOp_AddEx::abs(const MatExpr& e, MatExpr& res) const 1304 { 1305 if( (!e.b.data || e.beta == 0) && fabs(e.alpha) == 1 ) 1306 MatOp_Bin::makeExpr(res, 'a', e.a, -e.s*e.alpha); 1307 else if( e.b.data && e.alpha + e.beta == 0 && e.alpha*e.beta == -1 ) 1308 MatOp_Bin::makeExpr(res, 'a', e.a, e.b); 1309 else 1310 MatOp::abs(e, res); 1311 } 1312 1313 inline void MatOp_AddEx::makeExpr(MatExpr& res, const Mat& a, const Mat& b, double alpha, double beta, const Scalar& s) 1314 { 1315 res = MatExpr(&g_MatOp_AddEx, 0, a, b, Mat(), alpha, beta, s); 1316 } 1317 1318 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 1319 1320 void MatOp_Bin::assign(const MatExpr& e, Mat& m, int _type) const 1321 { 1322 Mat temp, &dst = _type == -1 || e.a.type() == _type ? m : temp; 1323 1324 if( e.flags == '*' ) 1325 cv::multiply(e.a, e.b, dst, e.alpha); 1326 else if( e.flags == '/' && e.b.data ) 1327 cv::divide(e.a, e.b, dst, e.alpha); 1328 else if( e.flags == '/' && !e.b.data ) 1329 cv::divide(e.alpha, e.a, dst ); 1330 else if( e.flags == '&' && e.b.data ) 1331 bitwise_and(e.a, e.b, dst); 1332 else if( e.flags == '&' && !e.b.data ) 1333 bitwise_and(e.a, e.s, dst); 1334 else if( e.flags == '|' && e.b.data ) 1335 bitwise_or(e.a, e.b, dst); 1336 else if( e.flags == '|' && !e.b.data ) 1337 bitwise_or(e.a, e.s, dst); 1338 else if( e.flags == '^' && e.b.data ) 1339 bitwise_xor(e.a, e.b, dst); 1340 else if( e.flags == '^' && !e.b.data ) 1341 bitwise_xor(e.a, e.s, dst); 1342 else if( e.flags == '~' && !e.b.data ) 1343 bitwise_not(e.a, dst); 1344 else if( e.flags == 'm' ) 1345 cv::min(e.a, e.b, dst); 1346 else if( e.flags == 'n' ) 1347 cv::min(e.a, e.s[0], dst); 1348 else if( e.flags == 'M' ) 1349 cv::max(e.a, e.b, dst); 1350 else if( e.flags == 'N' ) 1351 cv::max(e.a, e.s[0], dst); 1352 else if( e.flags == 'a' && e.b.data ) 1353 cv::absdiff(e.a, e.b, dst); 1354 else if( e.flags == 'a' && !e.b.data ) 1355 cv::absdiff(e.a, e.s, dst); 1356 else 1357 CV_Error(CV_StsError, "Unknown operation"); 1358 1359 if( dst.data != m.data ) 1360 dst.convertTo(m, _type); 1361 } 1362 1363 void MatOp_Bin::multiply(const MatExpr& e, double s, MatExpr& res) const 1364 { 1365 if( e.flags == '*' || e.flags == '/' ) 1366 { 1367 res = e; 1368 res.alpha *= s; 1369 } 1370 else 1371 MatOp::multiply(e, s, res); 1372 } 1373 1374 void MatOp_Bin::divide(double s, const MatExpr& e, MatExpr& res) const 1375 { 1376 if( e.flags == '/' && (!e.b.data || e.beta == 0) ) 1377 MatOp_AddEx::makeExpr(res, e.a, Mat(), s/e.alpha, 0); 1378 else 1379 MatOp::divide(s, e, res); 1380 } 1381 1382 inline void MatOp_Bin::makeExpr(MatExpr& res, char op, const Mat& a, const Mat& b, double scale) 1383 { 1384 res = MatExpr(&g_MatOp_Bin, op, a, b, Mat(), scale, b.data ? 1 : 0); 1385 } 1386 1387 inline void MatOp_Bin::makeExpr(MatExpr& res, char op, const Mat& a, const Scalar& s) 1388 { 1389 res = MatExpr(&g_MatOp_Bin, op, a, Mat(), Mat(), 1, 0, s); 1390 } 1391 1392 /////////////////////////////////////////////////////////////////////////////////////////////////////// 1393 1394 void MatOp_Cmp::assign(const MatExpr& e, Mat& m, int _type) const 1395 { 1396 Mat temp, &dst = _type == -1 || _type == CV_8U ? m : temp; 1397 1398 if( e.b.data ) 1399 cv::compare(e.a, e.b, dst, e.flags); 1400 else 1401 cv::compare(e.a, e.alpha, dst, e.flags); 1402 1403 if( dst.data != m.data ) 1404 dst.convertTo(m, _type); 1405 } 1406 1407 inline void MatOp_Cmp::makeExpr(MatExpr& res, int cmpop, const Mat& a, const Mat& b) 1408 { 1409 res = MatExpr(&g_MatOp_Cmp, cmpop, a, b, Mat(), 1, 1); 1410 } 1411 1412 inline void MatOp_Cmp::makeExpr(MatExpr& res, int cmpop, const Mat& a, double alpha) 1413 { 1414 res = MatExpr(&g_MatOp_Cmp, cmpop, a, Mat(), Mat(), alpha, 1); 1415 } 1416 1417 ///////////////////////////////////////////////////////////////////////////////////////////////////////// 1418 1419 void MatOp_T::assign(const MatExpr& e, Mat& m, int _type) const 1420 { 1421 Mat temp, &dst = _type == -1 || _type == e.a.type() ? m : temp; 1422 1423 cv::transpose(e.a, dst); 1424 1425 if( dst.data != m.data || e.alpha != 1 ) 1426 dst.convertTo(m, _type, e.alpha); 1427 } 1428 1429 void MatOp_T::multiply(const MatExpr& e, double s, MatExpr& res) const 1430 { 1431 res = e; 1432 res.alpha *= s; 1433 } 1434 1435 void MatOp_T::transpose(const MatExpr& e, MatExpr& res) const 1436 { 1437 if( e.alpha == 1 ) 1438 MatOp_Identity::makeExpr(res, e.a); 1439 else 1440 MatOp_AddEx::makeExpr(res, e.a, Mat(), e.alpha, 0); 1441 } 1442 1443 inline void MatOp_T::makeExpr(MatExpr& res, const Mat& a, double alpha) 1444 { 1445 res = MatExpr(&g_MatOp_T, 0, a, Mat(), Mat(), alpha, 0); 1446 } 1447 1448 ///////////////////////////////////////////////////////////////////////////////////////////////////////// 1449 1450 void MatOp_GEMM::assign(const MatExpr& e, Mat& m, int _type) const 1451 { 1452 Mat temp, &dst = _type == -1 || _type == e.a.type() ? m : temp; 1453 1454 cv::gemm(e.a, e.b, e.alpha, e.c, e.beta, dst, e.flags); 1455 if( dst.data != m.data ) 1456 dst.convertTo(m, _type); 1457 } 1458 1459 void MatOp_GEMM::add(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const 1460 { 1461 bool i1 = isIdentity(e1), i2 = isIdentity(e2); 1462 double alpha1 = i1 ? 1 : e1.alpha, alpha2 = i2 ? 1 : e2.alpha; 1463 1464 if( isMatProd(e1) && (i2 || isScaled(e2) || isT(e2)) ) 1465 MatOp_GEMM::makeExpr(res, (e1.flags & ~CV_GEMM_C_T)|(isT(e2) ? CV_GEMM_C_T : 0), 1466 e1.a, e1.b, alpha1, e2.a, alpha2); 1467 else if( isMatProd(e2) && (i1 || isScaled(e1) || isT(e1)) ) 1468 MatOp_GEMM::makeExpr(res, (e2.flags & ~CV_GEMM_C_T)|(isT(e1) ? CV_GEMM_C_T : 0), 1469 e2.a, e2.b, alpha2, e1.a, alpha1); 1470 else if( this == e2.op ) 1471 MatOp::add(e1, e2, res); 1472 else 1473 e2.op->add(e1, e2, res); 1474 } 1475 1476 void MatOp_GEMM::subtract(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const 1477 { 1478 bool i1 = isIdentity(e1), i2 = isIdentity(e2); 1479 double alpha1 = i1 ? 1 : e1.alpha, alpha2 = i2 ? 1 : e2.alpha; 1480 1481 if( isMatProd(e1) && (i2 || isScaled(e2) || isT(e2)) ) 1482 MatOp_GEMM::makeExpr(res, (e1.flags & ~CV_GEMM_C_T)|(isT(e2) ? CV_GEMM_C_T : 0), 1483 e1.a, e1.b, alpha1, e2.a, -alpha2); 1484 else if( isMatProd(e2) && (i1 || isScaled(e1) || isT(e1)) ) 1485 MatOp_GEMM::makeExpr(res, (e2.flags & ~CV_GEMM_C_T)|(isT(e1) ? CV_GEMM_C_T : 0), 1486 e2.a, e2.b, -alpha2, e1.a, alpha1); 1487 else if( this == e2.op ) 1488 MatOp::subtract(e1, e2, res); 1489 else 1490 e2.op->subtract(e1, e2, res); 1491 } 1492 1493 void MatOp_GEMM::multiply(const MatExpr& e, double s, MatExpr& res) const 1494 { 1495 res = e; 1496 res.alpha *= s; 1497 res.beta *= s; 1498 } 1499 1500 void MatOp_GEMM::transpose(const MatExpr& e, MatExpr& res) const 1501 { 1502 res = e; 1503 res.flags = (!(e.flags & CV_GEMM_A_T) ? CV_GEMM_B_T : 0) | 1504 (!(e.flags & CV_GEMM_B_T) ? CV_GEMM_A_T : 0) | 1505 (!(e.flags & CV_GEMM_C_T) ? CV_GEMM_C_T : 0); 1506 swap(res.a, res.b); 1507 } 1508 1509 inline void MatOp_GEMM::makeExpr(MatExpr& res, int flags, const Mat& a, const Mat& b, 1510 double alpha, const Mat& c, double beta) 1511 { 1512 res = MatExpr(&g_MatOp_GEMM, flags, a, b, c, alpha, beta); 1513 } 1514 1515 /////////////////////////////////////////////////////////////////////////////////////////////////////// 1516 1517 void MatOp_Invert::assign(const MatExpr& e, Mat& m, int _type) const 1518 { 1519 Mat temp, &dst = _type == -1 || _type == e.a.type() ? m : temp; 1520 1521 cv::invert(e.a, dst, e.flags); 1522 if( dst.data != m.data ) 1523 dst.convertTo(m, _type); 1524 } 1525 1526 void MatOp_Invert::matmul(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const 1527 { 1528 if( isInv(e1) && isIdentity(e2) ) 1529 MatOp_Solve::makeExpr(res, e1.flags, e1.a, e2.a); 1530 else if( this == e2.op ) 1531 MatOp::matmul(e1, e2, res); 1532 else 1533 e2.op->matmul(e1, e2, res); 1534 } 1535 1536 inline void MatOp_Invert::makeExpr(MatExpr& res, int method, const Mat& m) 1537 { 1538 res = MatExpr(&g_MatOp_Invert, method, m, Mat(), Mat(), 1, 0); 1539 } 1540 1541 ///////////////////////////////////////////////////////////////////////////////////////////////////////// 1542 1543 void MatOp_Solve::assign(const MatExpr& e, Mat& m, int _type) const 1544 { 1545 Mat temp, &dst = _type == -1 || _type == e.a.type() ? m : temp; 1546 1547 cv::solve(e.a, e.b, dst, e.flags); 1548 if( dst.data != m.data ) 1549 dst.convertTo(m, _type); 1550 } 1551 1552 inline void MatOp_Solve::makeExpr(MatExpr& res, int method, const Mat& a, const Mat& b) 1553 { 1554 res = MatExpr(&g_MatOp_Solve, method, a, b, Mat(), 1, 1); 1555 } 1556 1557 ////////////////////////////////////////////////////////////////////////////////////////////////////////// 1558 1559 void MatOp_Initializer::assign(const MatExpr& e, Mat& m, int _type) const 1560 { 1561 if( _type == -1 ) 1562 _type = e.a.type(); 1563 1564 if( e.a.dims <= 2 ) 1565 m.create(e.a.size(), _type); 1566 else 1567 m.create(e.a.dims, e.a.size, _type); 1568 1569 if( e.flags == 'I' && e.a.dims <= 2 ) 1570 setIdentity(m, Scalar(e.alpha)); 1571 else if( e.flags == '0' ) 1572 m = Scalar(); 1573 else if( e.flags == '1' ) 1574 m = Scalar(e.alpha); 1575 else 1576 CV_Error(CV_StsError, "Invalid matrix initializer type"); 1577 } 1578 1579 void MatOp_Initializer::multiply(const MatExpr& e, double s, MatExpr& res) const 1580 { 1581 res = e; 1582 res.alpha *= s; 1583 } 1584 1585 inline void MatOp_Initializer::makeExpr(MatExpr& res, int method, Size sz, int type, double alpha) 1586 { 1587 res = MatExpr(getGlobalMatOpInitializer(), method, Mat(sz, type, (void*)0), Mat(), Mat(), alpha, 0); 1588 } 1589 1590 inline void MatOp_Initializer::makeExpr(MatExpr& res, int method, int ndims, const int* sizes, int type, double alpha) 1591 { 1592 res = MatExpr(getGlobalMatOpInitializer(), method, Mat(ndims, sizes, type, (void*)0), Mat(), Mat(), alpha, 0); 1593 } 1594 1595 /////////////////////////////////////////////////////////////////////////////////////////////////////////// 1596 1597 MatExpr Mat::t() const 1598 { 1599 MatExpr e; 1600 MatOp_T::makeExpr(e, *this); 1601 return e; 1602 } 1603 1604 MatExpr Mat::inv(int method) const 1605 { 1606 MatExpr e; 1607 MatOp_Invert::makeExpr(e, method, *this); 1608 return e; 1609 } 1610 1611 1612 MatExpr Mat::mul(InputArray m, double scale) const 1613 { 1614 MatExpr e; 1615 if(m.kind() == _InputArray::EXPR) 1616 { 1617 const MatExpr& me = *(const MatExpr*)m.getObj(); 1618 me.op->multiply(MatExpr(*this), me, e, scale); 1619 } 1620 else 1621 MatOp_Bin::makeExpr(e, '*', *this, m.getMat(), scale); 1622 return e; 1623 } 1624 1625 MatExpr Mat::zeros(int rows, int cols, int type) 1626 { 1627 MatExpr e; 1628 MatOp_Initializer::makeExpr(e, '0', Size(cols, rows), type); 1629 return e; 1630 } 1631 1632 MatExpr Mat::zeros(Size size, int type) 1633 { 1634 MatExpr e; 1635 MatOp_Initializer::makeExpr(e, '0', size, type); 1636 return e; 1637 } 1638 1639 MatExpr Mat::zeros(int ndims, const int* sizes, int type) 1640 { 1641 MatExpr e; 1642 MatOp_Initializer::makeExpr(e, '0', ndims, sizes, type); 1643 return e; 1644 } 1645 1646 MatExpr Mat::ones(int rows, int cols, int type) 1647 { 1648 MatExpr e; 1649 MatOp_Initializer::makeExpr(e, '1', Size(cols, rows), type); 1650 return e; 1651 } 1652 1653 MatExpr Mat::ones(Size size, int type) 1654 { 1655 MatExpr e; 1656 MatOp_Initializer::makeExpr(e, '1', size, type); 1657 return e; 1658 } 1659 1660 MatExpr Mat::ones(int ndims, const int* sizes, int type) 1661 { 1662 MatExpr e; 1663 MatOp_Initializer::makeExpr(e, '1', ndims, sizes, type); 1664 return e; 1665 } 1666 1667 MatExpr Mat::eye(int rows, int cols, int type) 1668 { 1669 MatExpr e; 1670 MatOp_Initializer::makeExpr(e, 'I', Size(cols, rows), type); 1671 return e; 1672 } 1673 1674 MatExpr Mat::eye(Size size, int type) 1675 { 1676 MatExpr e; 1677 MatOp_Initializer::makeExpr(e, 'I', size, type); 1678 return e; 1679 } 1680 1681 } 1682 1683 /* End of file. */ 1684