1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html
4
5
6 /* ////////////////////////////////////////////////////////////////////
7 //
8 // Mat basic operations: Copy, Set
9 //
10 // */
11
12 #include "precomp.hpp"
13 #include <opencv2/core/utils/logger.hpp>
14
15 namespace cv
16 {
17
18 //This and its overload below are used in various MatExpr operator overloads
19 //implemented to check that Matrix operands exist.
checkOperandsExist(const Mat & a)20 static void checkOperandsExist(const Mat& a)
21 {
22 if (a.empty())
23 {
24 CV_Error(CV_StsBadArg, "Matrix operand is an empty matrix.");
25 }
26 }
27
checkOperandsExist(const Mat & a,const Mat & b)28 static void checkOperandsExist(const Mat& a, const Mat& b)
29 {
30 if (a.empty() || b.empty())
31 {
32 CV_Error(CV_StsBadArg, "One or more matrix operands are empty.");
33 }
34 }
35
36
37 class MatOp_Identity CV_FINAL : public MatOp
38 {
39 public:
MatOp_Identity()40 MatOp_Identity() {}
~MatOp_Identity()41 virtual ~MatOp_Identity() {}
42
elementWise(const MatExpr &) const43 bool elementWise(const MatExpr& /*expr*/) const CV_OVERRIDE { return true; }
44 void assign(const MatExpr& expr, Mat& m, int type=-1) const CV_OVERRIDE;
45
46 static void makeExpr(MatExpr& res, const Mat& m);
47 };
48
49 static MatOp_Identity g_MatOp_Identity;
50
51 class MatOp_AddEx CV_FINAL : public MatOp
52 {
53 public:
MatOp_AddEx()54 MatOp_AddEx() {}
~MatOp_AddEx()55 virtual ~MatOp_AddEx() {}
56
elementWise(const MatExpr &) const57 bool elementWise(const MatExpr& /*expr*/) const CV_OVERRIDE { return true; }
58 void assign(const MatExpr& expr, Mat& m, int type=-1) const CV_OVERRIDE;
59
60 void add(const MatExpr& e1, const Scalar& s, MatExpr& res) const CV_OVERRIDE;
61 void subtract(const Scalar& s, const MatExpr& expr, MatExpr& res) const CV_OVERRIDE;
62 void multiply(const MatExpr& e1, double s, MatExpr& res) const CV_OVERRIDE;
63 void divide(double s, const MatExpr& e, MatExpr& res) const CV_OVERRIDE;
64
65 void transpose(const MatExpr& e1, MatExpr& res) const CV_OVERRIDE;
66 void abs(const MatExpr& expr, MatExpr& res) const CV_OVERRIDE;
67
68 static void makeExpr(MatExpr& res, const Mat& a, const Mat& b, double alpha, double beta, const Scalar& s=Scalar());
69 };
70
71 static MatOp_AddEx g_MatOp_AddEx;
72
73 class MatOp_Bin CV_FINAL : public MatOp
74 {
75 public:
MatOp_Bin()76 MatOp_Bin() {}
~MatOp_Bin()77 virtual ~MatOp_Bin() {}
78
elementWise(const MatExpr &) const79 bool elementWise(const MatExpr& /*expr*/) const CV_OVERRIDE { return true; }
80 void assign(const MatExpr& expr, Mat& m, int type=-1) const CV_OVERRIDE;
81
82 void multiply(const MatExpr& e1, double s, MatExpr& res) const CV_OVERRIDE;
83 void divide(double s, const MatExpr& e, MatExpr& res) const CV_OVERRIDE;
84
85 static void makeExpr(MatExpr& res, char op, const Mat& a, const Mat& b, double scale=1);
86 static void makeExpr(MatExpr& res, char op, const Mat& a, const Scalar& s);
87 };
88
89 static MatOp_Bin g_MatOp_Bin;
90
91 class MatOp_Cmp CV_FINAL : public MatOp
92 {
93 public:
MatOp_Cmp()94 MatOp_Cmp() {}
~MatOp_Cmp()95 virtual ~MatOp_Cmp() {}
96
elementWise(const MatExpr &) const97 bool elementWise(const MatExpr& /*expr*/) const CV_OVERRIDE { return true; }
98 void assign(const MatExpr& expr, Mat& m, int type=-1) const CV_OVERRIDE;
99
100 static void makeExpr(MatExpr& res, int cmpop, const Mat& a, const Mat& b);
101 static void makeExpr(MatExpr& res, int cmpop, const Mat& a, double alpha);
102 };
103
104 static MatOp_Cmp g_MatOp_Cmp;
105
106 class MatOp_GEMM CV_FINAL : public MatOp
107 {
108 public:
MatOp_GEMM()109 MatOp_GEMM() {}
~MatOp_GEMM()110 virtual ~MatOp_GEMM() {}
111
elementWise(const MatExpr &) const112 bool elementWise(const MatExpr& /*expr*/) const CV_OVERRIDE { return false; }
113 void assign(const MatExpr& expr, Mat& m, int type=-1) const CV_OVERRIDE;
114
115 void add(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const CV_OVERRIDE;
116 void subtract(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const CV_OVERRIDE;
117 void multiply(const MatExpr& e, double s, MatExpr& res) const CV_OVERRIDE;
118
119 void transpose(const MatExpr& expr, MatExpr& res) const CV_OVERRIDE;
120
size(const MatExpr & expr) const121 Size size(const MatExpr& expr) const CV_OVERRIDE
122 {
123 return Size(
124 (expr.flags & GEMM_2_T) ? expr.b.rows : expr.b.cols,
125 (expr.flags & GEMM_1_T) ? expr.a.cols : expr.a.rows
126 );
127 }
128
129 static void makeExpr(MatExpr& res, int flags, const Mat& a, const Mat& b,
130 double alpha=1, const Mat& c=Mat(), double beta=1);
131
132 };
133
134 static MatOp_GEMM g_MatOp_GEMM;
135
136 class MatOp_Invert CV_FINAL : public MatOp
137 {
138 public:
MatOp_Invert()139 MatOp_Invert() {}
~MatOp_Invert()140 virtual ~MatOp_Invert() {}
141
elementWise(const MatExpr &) const142 bool elementWise(const MatExpr& /*expr*/) const CV_OVERRIDE { return false; }
143 void assign(const MatExpr& expr, Mat& m, int type=-1) const CV_OVERRIDE;
144
145 void matmul(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res) const CV_OVERRIDE;
146
147 static void makeExpr(MatExpr& res, int method, const Mat& m);
148 };
149
150 static MatOp_Invert g_MatOp_Invert;
151
152 class MatOp_T CV_FINAL : public MatOp
153 {
154 public:
MatOp_T()155 MatOp_T() {}
~MatOp_T()156 virtual ~MatOp_T() {}
157
elementWise(const MatExpr &) const158 bool elementWise(const MatExpr& /*expr*/) const CV_OVERRIDE { return false; }
159 void assign(const MatExpr& expr, Mat& m, int type=-1) const CV_OVERRIDE;
160
161 void multiply(const MatExpr& e1, double s, MatExpr& res) const CV_OVERRIDE;
162 void transpose(const MatExpr& expr, MatExpr& res) const CV_OVERRIDE;
163
164 static void makeExpr(MatExpr& res, const Mat& a, double alpha=1);
165 };
166
167 static MatOp_T g_MatOp_T;
168
169 class MatOp_Solve CV_FINAL : public MatOp
170 {
171 public:
MatOp_Solve()172 MatOp_Solve() {}
~MatOp_Solve()173 virtual ~MatOp_Solve() {}
174
elementWise(const MatExpr &) const175 bool elementWise(const MatExpr& /*expr*/) const CV_OVERRIDE { return false; }
176 void assign(const MatExpr& expr, Mat& m, int type=-1) const CV_OVERRIDE;
177
178 static void makeExpr(MatExpr& res, int method, const Mat& a, const Mat& b);
179 };
180
181 static MatOp_Solve g_MatOp_Solve;
182
183 class MatOp_Initializer CV_FINAL : public MatOp
184 {
185 public:
MatOp_Initializer()186 MatOp_Initializer() {}
~MatOp_Initializer()187 virtual ~MatOp_Initializer() {}
188
elementWise(const MatExpr &) const189 bool elementWise(const MatExpr& /*expr*/) const CV_OVERRIDE { return false; }
190 void assign(const MatExpr& expr, Mat& m, int type=-1) const CV_OVERRIDE;
191
192 void multiply(const MatExpr& e, double s, MatExpr& res) const CV_OVERRIDE;
193
194 static void makeExpr(MatExpr& res, int method, Size sz, int type, double alpha=1);
195 static void makeExpr(MatExpr& res, int method, int ndims, const int* sizes, int type, double alpha=1);
196 };
197
getGlobalMatOpInitializer()198 static MatOp_Initializer* getGlobalMatOpInitializer()
199 {
200 CV_SINGLETON_LAZY_INIT(MatOp_Initializer, new MatOp_Initializer())
201 }
202
isIdentity(const MatExpr & e)203 static inline bool isIdentity(const MatExpr& e) { return e.op == &g_MatOp_Identity; }
isAddEx(const MatExpr & e)204 static inline bool isAddEx(const MatExpr& e) { return e.op == &g_MatOp_AddEx; }
isScaled(const MatExpr & e)205 static inline bool isScaled(const MatExpr& e) { return isAddEx(e) && (!e.b.data || e.beta == 0) && e.s == Scalar(); }
isBin(const MatExpr & e,char c)206 static inline bool isBin(const MatExpr& e, char c) { return e.op == &g_MatOp_Bin && e.flags == c; }
isCmp(const MatExpr & e)207 static inline bool isCmp(const MatExpr& e) { return e.op == &g_MatOp_Cmp; }
isReciprocal(const MatExpr & e)208 static inline bool isReciprocal(const MatExpr& e) { return isBin(e,'/') && (!e.b.data || e.beta == 0); }
isT(const MatExpr & e)209 static inline bool isT(const MatExpr& e) { return e.op == &g_MatOp_T; }
isInv(const MatExpr & e)210 static inline bool isInv(const MatExpr& e) { return e.op == &g_MatOp_Invert; }
isSolve(const MatExpr & e)211 static inline bool isSolve(const MatExpr& e) { return e.op == &g_MatOp_Solve; }
212 //static inline bool isGEMM(const MatExpr& e) { return e.op == &g_MatOp_GEMM; }
isMatProd(const MatExpr & e)213 static inline bool isMatProd(const MatExpr& e) { return e.op == &g_MatOp_GEMM && (!e.c.data || e.beta == 0); }
isInitializer(const MatExpr & e)214 static inline bool isInitializer(const MatExpr& e) { return e.op == getGlobalMatOpInitializer(); }
215
216 /////////////////////////////////////////////////////////////////////////////////////////////////////
217
MatOp()218 MatOp::MatOp() {}
~MatOp()219 MatOp::~MatOp() {}
220
221
elementWise(const MatExpr &) const222 bool MatOp::elementWise(const MatExpr& /*expr*/) const
223 {
224 return false;
225 }
226
roi(const MatExpr & expr,const Range & rowRange,const Range & colRange,MatExpr & e) const227 void MatOp::roi(const MatExpr& expr, const Range& rowRange, const Range& colRange, MatExpr& e) const
228 {
229 if( elementWise(expr) )
230 {
231 e = MatExpr(expr.op, expr.flags, Mat(), Mat(), Mat(),
232 expr.alpha, expr.beta, expr.s);
233 if(expr.a.data)
234 e.a = expr.a(rowRange, colRange);
235 if(expr.b.data)
236 e.b = expr.b(rowRange, colRange);
237 if(expr.c.data)
238 e.c = expr.c(rowRange, colRange);
239 }
240 else
241 {
242 Mat m;
243 expr.op->assign(expr, m);
244 e = MatExpr(&g_MatOp_Identity, 0, m(rowRange, colRange), Mat(), Mat());
245 }
246 }
247
diag(const MatExpr & expr,int d,MatExpr & e) const248 void MatOp::diag(const MatExpr& expr, int d, MatExpr& e) const
249 {
250 if( elementWise(expr) )
251 {
252 e = MatExpr(expr.op, expr.flags, Mat(), Mat(), Mat(),
253 expr.alpha, expr.beta, expr.s);
254 if(expr.a.data)
255 e.a = expr.a.diag(d);
256 if(expr.b.data)
257 e.b = expr.b.diag(d);
258 if(expr.c.data)
259 e.c = expr.c.diag(d);
260 }
261 else
262 {
263 Mat m;
264 expr.op->assign(expr, m);
265 e = MatExpr(&g_MatOp_Identity, 0, m.diag(d), Mat(), Mat());
266 }
267 }
268
269
augAssignAdd(const MatExpr & expr,Mat & m) const270 void MatOp::augAssignAdd(const MatExpr& expr, Mat& m) const
271 {
272 Mat temp;
273 expr.op->assign(expr, temp);
274 m += temp;
275 }
276
277
augAssignSubtract(const MatExpr & expr,Mat & m) const278 void MatOp::augAssignSubtract(const MatExpr& expr, Mat& m) const
279 {
280 Mat temp;
281 expr.op->assign(expr, temp);
282 m -= temp;
283 }
284
285
augAssignMultiply(const MatExpr & expr,Mat & m) const286 void MatOp::augAssignMultiply(const MatExpr& expr, Mat& m) const
287 {
288 Mat temp;
289 expr.op->assign(expr, temp);
290 m *= temp;
291 }
292
293
augAssignDivide(const MatExpr & expr,Mat & m) const294 void MatOp::augAssignDivide(const MatExpr& expr, Mat& m) const
295 {
296 Mat temp;
297 expr.op->assign(expr, temp);
298 m /= temp;
299 }
300
301
augAssignAnd(const MatExpr & expr,Mat & m) const302 void MatOp::augAssignAnd(const MatExpr& expr, Mat& m) const
303 {
304 Mat temp;
305 expr.op->assign(expr, temp);
306 m &= temp;
307 }
308
309
augAssignOr(const MatExpr & expr,Mat & m) const310 void MatOp::augAssignOr(const MatExpr& expr, Mat& m) const
311 {
312 Mat temp;
313 expr.op->assign(expr, temp);
314 m |= temp;
315 }
316
317
augAssignXor(const MatExpr & expr,Mat & m) const318 void MatOp::augAssignXor(const MatExpr& expr, Mat& m) const
319 {
320 Mat temp;
321 expr.op->assign(expr, temp);
322 m ^= temp;
323 }
324
325
add(const MatExpr & e1,const MatExpr & e2,MatExpr & res) const326 void MatOp::add(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const
327 {
328 CV_INSTRUMENT_REGION();
329
330 if( this == e2.op )
331 {
332 double alpha = 1, beta = 1;
333 Scalar s;
334 Mat m1, m2;
335 if( isAddEx(e1) && (!e1.b.data || e1.beta == 0) )
336 {
337 m1 = e1.a;
338 alpha = e1.alpha;
339 s = e1.s;
340 }
341 else
342 e1.op->assign(e1, m1);
343
344 if( isAddEx(e2) && (!e2.b.data || e2.beta == 0) )
345 {
346 m2 = e2.a;
347 beta = e2.alpha;
348 s += e2.s;
349 }
350 else
351 e2.op->assign(e2, m2);
352 MatOp_AddEx::makeExpr(res, m1, m2, alpha, beta, s);
353 }
354 else
355 e2.op->add(e1, e2, res);
356 }
357
358
add(const MatExpr & expr1,const Scalar & s,MatExpr & res) const359 void MatOp::add(const MatExpr& expr1, const Scalar& s, MatExpr& res) const
360 {
361 CV_INSTRUMENT_REGION();
362
363 Mat m1;
364 expr1.op->assign(expr1, m1);
365 MatOp_AddEx::makeExpr(res, m1, Mat(), 1, 0, s);
366 }
367
368
subtract(const MatExpr & e1,const MatExpr & e2,MatExpr & res) const369 void MatOp::subtract(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const
370 {
371 CV_INSTRUMENT_REGION();
372
373 if( this == e2.op )
374 {
375 double alpha = 1, beta = -1;
376 Scalar s;
377 Mat m1, m2;
378 if( isAddEx(e1) && (!e1.b.data || e1.beta == 0) )
379 {
380 m1 = e1.a;
381 alpha = e1.alpha;
382 s = e1.s;
383 }
384 else
385 e1.op->assign(e1, m1);
386
387 if( isAddEx(e2) && (!e2.b.data || e2.beta == 0) )
388 {
389 m2 = e2.a;
390 beta = -e2.alpha;
391 s -= e2.s;
392 }
393 else
394 e2.op->assign(e2, m2);
395 MatOp_AddEx::makeExpr(res, m1, m2, alpha, beta, s);
396 }
397 else
398 e2.op->subtract(e1, e2, res);
399 }
400
401
subtract(const Scalar & s,const MatExpr & expr,MatExpr & res) const402 void MatOp::subtract(const Scalar& s, const MatExpr& expr, MatExpr& res) const
403 {
404 CV_INSTRUMENT_REGION();
405
406 Mat m;
407 expr.op->assign(expr, m);
408 MatOp_AddEx::makeExpr(res, m, Mat(), -1, 0, s);
409 }
410
411
multiply(const MatExpr & e1,const MatExpr & e2,MatExpr & res,double scale) const412 void MatOp::multiply(const MatExpr& e1, const MatExpr& e2, MatExpr& res, double scale) const
413 {
414 CV_INSTRUMENT_REGION();
415
416 if( this == e2.op )
417 {
418 Mat m1, m2;
419
420 if( isReciprocal(e1) )
421 {
422 if( isScaled(e2) )
423 {
424 scale *= e2.alpha;
425 m2 = e2.a;
426 }
427 else
428 e2.op->assign(e2, m2);
429
430 MatOp_Bin::makeExpr(res, '/', m2, e1.a, scale/e1.alpha);
431 }
432 else
433 {
434 char op = '*';
435 if( isScaled(e1) )
436 {
437 m1 = e1.a;
438 scale *= e1.alpha;
439 }
440 else
441 e1.op->assign(e1, m1);
442
443 if( isScaled(e2) )
444 {
445 m2 = e2.a;
446 scale *= e2.alpha;
447 }
448 else if( isReciprocal(e2) )
449 {
450 op = '/';
451 m2 = e2.a;
452 scale *= e2.alpha;
453 }
454 else
455 e2.op->assign(e2, m2);
456
457 MatOp_Bin::makeExpr(res, op, m1, m2, scale);
458 }
459 }
460 else
461 e2.op->multiply(e1, e2, res, scale);
462 }
463
464
multiply(const MatExpr & expr,double s,MatExpr & res) const465 void MatOp::multiply(const MatExpr& expr, double s, MatExpr& res) const
466 {
467 CV_INSTRUMENT_REGION();
468
469 Mat m;
470 expr.op->assign(expr, m);
471 MatOp_AddEx::makeExpr(res, m, Mat(), s, 0);
472 }
473
474
divide(const MatExpr & e1,const MatExpr & e2,MatExpr & res,double scale) const475 void MatOp::divide(const MatExpr& e1, const MatExpr& e2, MatExpr& res, double scale) const
476 {
477 CV_INSTRUMENT_REGION();
478
479 if( this == e2.op )
480 {
481 if( isReciprocal(e1) && isReciprocal(e2) )
482 MatOp_Bin::makeExpr(res, '/', e2.a, e1.a, e1.alpha/e2.alpha);
483 else
484 {
485 Mat m1, m2;
486 char op = '/';
487
488 if( isScaled(e1) )
489 {
490 m1 = e1.a;
491 scale *= e1.alpha;
492 }
493 else
494 e1.op->assign(e1, m1);
495
496 if( isScaled(e2) )
497 {
498 m2 = e2.a;
499 scale /= e2.alpha;
500 }
501 else if( isReciprocal(e2) )
502 {
503 m2 = e2.a;
504 scale /= e2.alpha;
505 op = '*';
506 }
507 else
508 e2.op->assign(e2, m2);
509 MatOp_Bin::makeExpr(res, op, m1, m2, scale);
510 }
511 }
512 else
513 e2.op->divide(e1, e2, res, scale);
514 }
515
516
divide(double s,const MatExpr & expr,MatExpr & res) const517 void MatOp::divide(double s, const MatExpr& expr, MatExpr& res) const
518 {
519 CV_INSTRUMENT_REGION();
520
521 Mat m;
522 expr.op->assign(expr, m);
523 MatOp_Bin::makeExpr(res, '/', m, Mat(), s);
524 }
525
526
abs(const MatExpr & expr,MatExpr & res) const527 void MatOp::abs(const MatExpr& expr, MatExpr& res) const
528 {
529 CV_INSTRUMENT_REGION();
530
531 Mat m;
532 expr.op->assign(expr, m);
533 MatOp_Bin::makeExpr(res, 'a', m, Mat());
534 }
535
536
transpose(const MatExpr & expr,MatExpr & res) const537 void MatOp::transpose(const MatExpr& expr, MatExpr& res) const
538 {
539 CV_INSTRUMENT_REGION();
540
541 Mat m;
542 expr.op->assign(expr, m);
543 MatOp_T::makeExpr(res, m, 1);
544 }
545
546
matmul(const MatExpr & e1,const MatExpr & e2,MatExpr & res) const547 void MatOp::matmul(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const
548 {
549 if( this == e2.op )
550 {
551 double scale = 1;
552 int flags = 0;
553 Mat m1, m2;
554
555 if( isT(e1) )
556 {
557 flags = CV_GEMM_A_T;
558 scale = e1.alpha;
559 m1 = e1.a;
560 }
561 else if( isScaled(e1) )
562 {
563 scale = e1.alpha;
564 m1 = e1.a;
565 }
566 else
567 e1.op->assign(e1, m1);
568
569 if( isT(e2) )
570 {
571 flags |= CV_GEMM_B_T;
572 scale *= e2.alpha;
573 m2 = e2.a;
574 }
575 else if( isScaled(e2) )
576 {
577 scale *= e2.alpha;
578 m2 = e2.a;
579 }
580 else
581 e2.op->assign(e2, m2);
582
583 MatOp_GEMM::makeExpr(res, flags, m1, m2, scale);
584 }
585 else
586 e2.op->matmul(e1, e2, res);
587 }
588
589
invert(const MatExpr & expr,int method,MatExpr & res) const590 void MatOp::invert(const MatExpr& expr, int method, MatExpr& res) const
591 {
592 Mat m;
593 expr.op->assign(expr, m);
594 MatOp_Invert::makeExpr(res, method, m);
595 }
596
597
size(const MatExpr & expr) const598 Size MatOp::size(const MatExpr& expr) const
599 {
600 return !expr.a.empty() ? expr.a.size() : expr.b.empty() ? expr.b.size() : expr.c.size();
601 }
602
type(const MatExpr & expr) const603 int MatOp::type(const MatExpr& expr) const
604 {
605 CV_INSTRUMENT_REGION();
606
607 return !expr.a.empty() ? expr.a.type() : expr.b.empty() ? expr.b.type() : expr.c.type();
608 }
609
610 //////////////////////////////////////////////////////////////////////////////////////////////////
611
MatExpr(const Mat & m)612 MatExpr::MatExpr(const Mat& m) : op(&g_MatOp_Identity), flags(0), a(m), b(Mat()), c(Mat()), alpha(1), beta(0), s(Scalar())
613 {
614 }
615
row(int y) const616 MatExpr MatExpr::row(int y) const
617 {
618 MatExpr e;
619 op->roi(*this, Range(y, y+1), Range::all(), e);
620 return e;
621 }
622
col(int x) const623 MatExpr MatExpr::col(int x) const
624 {
625 MatExpr e;
626 op->roi(*this, Range::all(), Range(x, x+1), e);
627 return e;
628 }
629
diag(int d) const630 MatExpr MatExpr::diag(int d) const
631 {
632 MatExpr e;
633 op->diag(*this, d, e);
634 return e;
635 }
636
operator ()(const Range & rowRange,const Range & colRange) const637 MatExpr MatExpr::operator()( const Range& rowRange, const Range& colRange ) const
638 {
639 MatExpr e;
640 op->roi(*this, rowRange, colRange, e);
641 return e;
642 }
643
operator ()(const Rect & roi) const644 MatExpr MatExpr::operator()( const Rect& roi ) const
645 {
646 MatExpr e;
647 op->roi(*this, Range(roi.y, roi.y + roi.height), Range(roi.x, roi.x + roi.width), e);
648 return e;
649 }
650
cross(const Mat & m) const651 Mat MatExpr::cross(const Mat& m) const
652 {
653 return ((Mat)*this).cross(m);
654 }
655
dot(const Mat & m) const656 double MatExpr::dot(const Mat& m) const
657 {
658 return ((Mat)*this).dot(m);
659 }
660
t() const661 MatExpr MatExpr::t() const
662 {
663 MatExpr e;
664 op->transpose(*this, e);
665 return e;
666 }
667
inv(int method) const668 MatExpr MatExpr::inv(int method) const
669 {
670 MatExpr e;
671 op->invert(*this, method, e);
672 return e;
673 }
674
mul(const MatExpr & e,double scale) const675 MatExpr MatExpr::mul(const MatExpr& e, double scale) const
676 {
677 MatExpr en;
678 op->multiply(*this, e, en, scale);
679 return en;
680 }
681
mul(const Mat & m,double scale) const682 MatExpr MatExpr::mul(const Mat& m, double scale) const
683 {
684 MatExpr e;
685 op->multiply(*this, MatExpr(m), e, scale);
686 return e;
687 }
688
operator +(const Mat & a,const Mat & b)689 MatExpr operator + (const Mat& a, const Mat& b)
690 {
691 checkOperandsExist(a, b);
692 MatExpr e;
693 MatOp_AddEx::makeExpr(e, a, b, 1, 1);
694 return e;
695 }
696
operator +(const Mat & a,const Scalar & s)697 MatExpr operator + (const Mat& a, const Scalar& s)
698 {
699 checkOperandsExist(a);
700 MatExpr e;
701 MatOp_AddEx::makeExpr(e, a, Mat(), 1, 0, s);
702 return e;
703 }
704
operator +(const Scalar & s,const Mat & a)705 MatExpr operator + (const Scalar& s, const Mat& a)
706 {
707 checkOperandsExist(a);
708 MatExpr e;
709 MatOp_AddEx::makeExpr(e, a, Mat(), 1, 0, s);
710 return e;
711 }
712
operator +(const MatExpr & e,const Mat & m)713 MatExpr operator + (const MatExpr& e, const Mat& m)
714 {
715 MatExpr en;
716 e.op->add(e, MatExpr(m), en);
717 return en;
718 }
719
operator +(const Mat & m,const MatExpr & e)720 MatExpr operator + (const Mat& m, const MatExpr& e)
721 {
722 checkOperandsExist(m);
723 MatExpr en;
724 e.op->add(e, MatExpr(m), en);
725 return en;
726 }
727
operator +(const MatExpr & e,const Scalar & s)728 MatExpr operator + (const MatExpr& e, const Scalar& s)
729 {
730 MatExpr en;
731 e.op->add(e, s, en);
732 return en;
733 }
734
operator +(const Scalar & s,const MatExpr & e)735 MatExpr operator + (const Scalar& s, const MatExpr& e)
736 {
737 MatExpr en;
738 e.op->add(e, s, en);
739 return en;
740 }
741
operator +(const MatExpr & e1,const MatExpr & e2)742 MatExpr operator + (const MatExpr& e1, const MatExpr& e2)
743 {
744 MatExpr en;
745 e1.op->add(e1, e2, en);
746 return en;
747 }
748
operator -(const Mat & a,const Mat & b)749 MatExpr operator - (const Mat& a, const Mat& b)
750 {
751 checkOperandsExist(a, b);
752 MatExpr e;
753 MatOp_AddEx::makeExpr(e, a, b, 1, -1);
754 return e;
755 }
756
operator -(const Mat & a,const Scalar & s)757 MatExpr operator - (const Mat& a, const Scalar& s)
758 {
759 checkOperandsExist(a);
760 MatExpr e;
761 MatOp_AddEx::makeExpr(e, a, Mat(), 1, 0, -s);
762 return e;
763 }
764
operator -(const Scalar & s,const Mat & a)765 MatExpr operator - (const Scalar& s, const Mat& a)
766 {
767 checkOperandsExist(a);
768 MatExpr e;
769 MatOp_AddEx::makeExpr(e, a, Mat(), -1, 0, s);
770 return e;
771 }
772
operator -(const MatExpr & e,const Mat & m)773 MatExpr operator - (const MatExpr& e, const Mat& m)
774 {
775 checkOperandsExist(m);
776 MatExpr en;
777 e.op->subtract(e, MatExpr(m), en);
778 return en;
779 }
780
operator -(const Mat & m,const MatExpr & e)781 MatExpr operator - (const Mat& m, const MatExpr& e)
782 {
783 checkOperandsExist(m);
784 MatExpr en;
785 e.op->subtract(MatExpr(m), e, en);
786 return en;
787 }
788
operator -(const MatExpr & e,const Scalar & s)789 MatExpr operator - (const MatExpr& e, const Scalar& s)
790 {
791 MatExpr en;
792 e.op->add(e, -s, en);
793 return en;
794 }
795
operator -(const Scalar & s,const MatExpr & e)796 MatExpr operator - (const Scalar& s, const MatExpr& e)
797 {
798 MatExpr en;
799 e.op->subtract(s, e, en);
800 return en;
801 }
802
operator -(const MatExpr & e1,const MatExpr & e2)803 MatExpr operator - (const MatExpr& e1, const MatExpr& e2)
804 {
805 MatExpr en;
806 e1.op->subtract(e1, e2, en);
807 return en;
808 }
809
operator -(const Mat & m)810 MatExpr operator - (const Mat& m)
811 {
812 checkOperandsExist(m);
813 MatExpr e;
814 MatOp_AddEx::makeExpr(e, m, Mat(), -1, 0);
815 return e;
816 }
817
operator -(const MatExpr & e)818 MatExpr operator - (const MatExpr& e)
819 {
820 MatExpr en;
821 e.op->subtract(Scalar(0), e, en);
822 return en;
823 }
824
operator *(const Mat & a,const Mat & b)825 MatExpr operator * (const Mat& a, const Mat& b)
826 {
827 checkOperandsExist(a, b);
828 MatExpr e;
829 MatOp_GEMM::makeExpr(e, 0, a, b);
830 return e;
831 }
832
operator *(const Mat & a,double s)833 MatExpr operator * (const Mat& a, double s)
834 {
835 checkOperandsExist(a);
836 MatExpr e;
837 MatOp_AddEx::makeExpr(e, a, Mat(), s, 0);
838 return e;
839 }
840
operator *(double s,const Mat & a)841 MatExpr operator * (double s, const Mat& a)
842 {
843 checkOperandsExist(a);
844 MatExpr e;
845 MatOp_AddEx::makeExpr(e, a, Mat(), s, 0);
846 return e;
847 }
848
operator *(const MatExpr & e,const Mat & m)849 MatExpr operator * (const MatExpr& e, const Mat& m)
850 {
851 MatExpr en;
852 e.op->matmul(e, MatExpr(m), en);
853 return en;
854 }
855
operator *(const Mat & m,const MatExpr & e)856 MatExpr operator * (const Mat& m, const MatExpr& e)
857 {
858 checkOperandsExist(m);
859 MatExpr en;
860 e.op->matmul(MatExpr(m), e, en);
861 return en;
862 }
863
operator *(const MatExpr & e,double s)864 MatExpr operator * (const MatExpr& e, double s)
865 {
866 MatExpr en;
867 e.op->multiply(e, s, en);
868 return en;
869 }
870
operator *(double s,const MatExpr & e)871 MatExpr operator * (double s, const MatExpr& e)
872 {
873 MatExpr en;
874 e.op->multiply(e, s, en);
875 return en;
876 }
877
operator *(const MatExpr & e1,const MatExpr & e2)878 MatExpr operator * (const MatExpr& e1, const MatExpr& e2)
879 {
880 MatExpr en;
881 e1.op->matmul(e1, e2, en);
882 return en;
883 }
884
operator /(const Mat & a,const Mat & b)885 MatExpr operator / (const Mat& a, const Mat& b)
886 {
887 checkOperandsExist(a, b);
888 MatExpr e;
889 MatOp_Bin::makeExpr(e, '/', a, b);
890 return e;
891 }
892
operator /(const Mat & a,double s)893 MatExpr operator / (const Mat& a, double s)
894 {
895 checkOperandsExist(a);
896 MatExpr e;
897 MatOp_AddEx::makeExpr(e, a, Mat(), 1./s, 0);
898 return e;
899 }
900
operator /(double s,const Mat & a)901 MatExpr operator / (double s, const Mat& a)
902 {
903 checkOperandsExist(a);
904 MatExpr e;
905 MatOp_Bin::makeExpr(e, '/', a, Mat(), s);
906 return e;
907 }
908
operator /(const MatExpr & e,const Mat & m)909 MatExpr operator / (const MatExpr& e, const Mat& m)
910 {
911 MatExpr en;
912 e.op->divide(e, MatExpr(m), en);
913 return en;
914 }
915
operator /(const Mat & m,const MatExpr & e)916 MatExpr operator / (const Mat& m, const MatExpr& e)
917 {
918 checkOperandsExist(m);
919 MatExpr en;
920 e.op->divide(MatExpr(m), e, en);
921 return en;
922 }
923
operator /(const MatExpr & e,double s)924 MatExpr operator / (const MatExpr& e, double s)
925 {
926 MatExpr en;
927 e.op->multiply(e, 1./s, en);
928 return en;
929 }
930
operator /(double s,const MatExpr & e)931 MatExpr operator / (double s, const MatExpr& e)
932 {
933 MatExpr en;
934 e.op->divide(s, e, en);
935 return en;
936 }
937
operator /(const MatExpr & e1,const MatExpr & e2)938 MatExpr operator / (const MatExpr& e1, const MatExpr& e2)
939 {
940 MatExpr en;
941 e1.op->divide(e1, e2, en);
942 return en;
943 }
944
operator <(const Mat & a,const Mat & b)945 MatExpr operator < (const Mat& a, const Mat& b)
946 {
947 checkOperandsExist(a, b);
948 MatExpr e;
949 MatOp_Cmp::makeExpr(e, CV_CMP_LT, a, b);
950 return e;
951 }
952
operator <(const Mat & a,double s)953 MatExpr operator < (const Mat& a, double s)
954 {
955 checkOperandsExist(a);
956 MatExpr e;
957 MatOp_Cmp::makeExpr(e, CV_CMP_LT, a, s);
958 return e;
959 }
960
operator <(double s,const Mat & a)961 MatExpr operator < (double s, const Mat& a)
962 {
963 checkOperandsExist(a);
964 MatExpr e;
965 MatOp_Cmp::makeExpr(e, CV_CMP_GT, a, s);
966 return e;
967 }
968
operator <=(const Mat & a,const Mat & b)969 MatExpr operator <= (const Mat& a, const Mat& b)
970 {
971 checkOperandsExist(a, b);
972 MatExpr e;
973 MatOp_Cmp::makeExpr(e, CV_CMP_LE, a, b);
974 return e;
975 }
976
operator <=(const Mat & a,double s)977 MatExpr operator <= (const Mat& a, double s)
978 {
979 checkOperandsExist(a);
980 MatExpr e;
981 MatOp_Cmp::makeExpr(e, CV_CMP_LE, a, s);
982 return e;
983 }
984
operator <=(double s,const Mat & a)985 MatExpr operator <= (double s, const Mat& a)
986 {
987 checkOperandsExist(a);
988 MatExpr e;
989 MatOp_Cmp::makeExpr(e, CV_CMP_GE, a, s);
990 return e;
991 }
992
operator ==(const Mat & a,const Mat & b)993 MatExpr operator == (const Mat& a, const Mat& b)
994 {
995 checkOperandsExist(a, b);
996 MatExpr e;
997 MatOp_Cmp::makeExpr(e, CV_CMP_EQ, a, b);
998 return e;
999 }
1000
operator ==(const Mat & a,double s)1001 MatExpr operator == (const Mat& a, double s)
1002 {
1003 checkOperandsExist(a);
1004 MatExpr e;
1005 MatOp_Cmp::makeExpr(e, CV_CMP_EQ, a, s);
1006 return e;
1007 }
1008
operator ==(double s,const Mat & a)1009 MatExpr operator == (double s, const Mat& a)
1010 {
1011 checkOperandsExist(a);
1012 MatExpr e;
1013 MatOp_Cmp::makeExpr(e, CV_CMP_EQ, a, s);
1014 return e;
1015 }
1016
operator !=(const Mat & a,const Mat & b)1017 MatExpr operator != (const Mat& a, const Mat& b)
1018 {
1019 checkOperandsExist(a, b);
1020 MatExpr e;
1021 MatOp_Cmp::makeExpr(e, CV_CMP_NE, a, b);
1022 return e;
1023 }
1024
operator !=(const Mat & a,double s)1025 MatExpr operator != (const Mat& a, double s)
1026 {
1027 checkOperandsExist(a);
1028 MatExpr e;
1029 MatOp_Cmp::makeExpr(e, CV_CMP_NE, a, s);
1030 return e;
1031 }
1032
operator !=(double s,const Mat & a)1033 MatExpr operator != (double s, const Mat& a)
1034 {
1035 checkOperandsExist(a);
1036 MatExpr e;
1037 MatOp_Cmp::makeExpr(e, CV_CMP_NE, a, s);
1038 return e;
1039 }
1040
operator >=(const Mat & a,const Mat & b)1041 MatExpr operator >= (const Mat& a, const Mat& b)
1042 {
1043 checkOperandsExist(a, b);
1044 MatExpr e;
1045 MatOp_Cmp::makeExpr(e, CV_CMP_GE, a, b);
1046 return e;
1047 }
1048
operator >=(const Mat & a,double s)1049 MatExpr operator >= (const Mat& a, double s)
1050 {
1051 checkOperandsExist(a);
1052 MatExpr e;
1053 MatOp_Cmp::makeExpr(e, CV_CMP_GE, a, s);
1054 return e;
1055 }
1056
operator >=(double s,const Mat & a)1057 MatExpr operator >= (double s, const Mat& a)
1058 {
1059 checkOperandsExist(a);
1060 MatExpr e;
1061 MatOp_Cmp::makeExpr(e, CV_CMP_LE, a, s);
1062 return e;
1063 }
1064
operator >(const Mat & a,const Mat & b)1065 MatExpr operator > (const Mat& a, const Mat& b)
1066 {
1067 checkOperandsExist(a, b);
1068 MatExpr e;
1069 MatOp_Cmp::makeExpr(e, CV_CMP_GT, a, b);
1070 return e;
1071 }
1072
operator >(const Mat & a,double s)1073 MatExpr operator > (const Mat& a, double s)
1074 {
1075 checkOperandsExist(a);
1076 MatExpr e;
1077 MatOp_Cmp::makeExpr(e, CV_CMP_GT, a, s);
1078 return e;
1079 }
1080
operator >(double s,const Mat & a)1081 MatExpr operator > (double s, const Mat& a)
1082 {
1083 checkOperandsExist(a);
1084 MatExpr e;
1085 MatOp_Cmp::makeExpr(e, CV_CMP_LT, a, s);
1086 return e;
1087 }
1088
min(const Mat & a,const Mat & b)1089 MatExpr min(const Mat& a, const Mat& b)
1090 {
1091 CV_INSTRUMENT_REGION();
1092
1093 checkOperandsExist(a, b);
1094 MatExpr e;
1095 MatOp_Bin::makeExpr(e, 'm', a, b);
1096 return e;
1097 }
1098
min(const Mat & a,double s)1099 MatExpr min(const Mat& a, double s)
1100 {
1101 CV_INSTRUMENT_REGION();
1102
1103 checkOperandsExist(a);
1104 MatExpr e;
1105 MatOp_Bin::makeExpr(e, 'n', a, s);
1106 return e;
1107 }
1108
min(double s,const Mat & a)1109 MatExpr min(double s, const Mat& a)
1110 {
1111 CV_INSTRUMENT_REGION();
1112
1113 checkOperandsExist(a);
1114 MatExpr e;
1115 MatOp_Bin::makeExpr(e, 'n', a, s);
1116 return e;
1117 }
1118
max(const Mat & a,const Mat & b)1119 MatExpr max(const Mat& a, const Mat& b)
1120 {
1121 CV_INSTRUMENT_REGION();
1122
1123 checkOperandsExist(a, b);
1124 MatExpr e;
1125 MatOp_Bin::makeExpr(e, 'M', a, b);
1126 return e;
1127 }
1128
max(const Mat & a,double s)1129 MatExpr max(const Mat& a, double s)
1130 {
1131 CV_INSTRUMENT_REGION();
1132
1133 checkOperandsExist(a);
1134 MatExpr e;
1135 MatOp_Bin::makeExpr(e, 'N', a, s);
1136 return e;
1137 }
1138
max(double s,const Mat & a)1139 MatExpr max(double s, const Mat& a)
1140 {
1141 CV_INSTRUMENT_REGION();
1142
1143 checkOperandsExist(a);
1144 MatExpr e;
1145 MatOp_Bin::makeExpr(e, 'N', a, s);
1146 return e;
1147 }
1148
operator &(const Mat & a,const Mat & b)1149 MatExpr operator & (const Mat& a, const Mat& b)
1150 {
1151 checkOperandsExist(a, b);
1152 MatExpr e;
1153 MatOp_Bin::makeExpr(e, '&', a, b);
1154 return e;
1155 }
1156
operator &(const Mat & a,const Scalar & s)1157 MatExpr operator & (const Mat& a, const Scalar& s)
1158 {
1159 checkOperandsExist(a);
1160 MatExpr e;
1161 MatOp_Bin::makeExpr(e, '&', a, s);
1162 return e;
1163 }
1164
operator &(const Scalar & s,const Mat & a)1165 MatExpr operator & (const Scalar& s, const Mat& a)
1166 {
1167 checkOperandsExist(a);
1168 MatExpr e;
1169 MatOp_Bin::makeExpr(e, '&', a, s);
1170 return e;
1171 }
1172
operator |(const Mat & a,const Mat & b)1173 MatExpr operator | (const Mat& a, const Mat& b)
1174 {
1175 checkOperandsExist(a, b);
1176 MatExpr e;
1177 MatOp_Bin::makeExpr(e, '|', a, b);
1178 return e;
1179 }
1180
operator |(const Mat & a,const Scalar & s)1181 MatExpr operator | (const Mat& a, const Scalar& s)
1182 {
1183 checkOperandsExist(a);
1184 MatExpr e;
1185 MatOp_Bin::makeExpr(e, '|', a, s);
1186 return e;
1187 }
1188
operator |(const Scalar & s,const Mat & a)1189 MatExpr operator | (const Scalar& s, const Mat& a)
1190 {
1191 checkOperandsExist(a);
1192 MatExpr e;
1193 MatOp_Bin::makeExpr(e, '|', a, s);
1194 return e;
1195 }
1196
operator ^(const Mat & a,const Mat & b)1197 MatExpr operator ^ (const Mat& a, const Mat& b)
1198 {
1199 checkOperandsExist(a, b);
1200 MatExpr e;
1201 MatOp_Bin::makeExpr(e, '^', a, b);
1202 return e;
1203 }
1204
operator ^(const Mat & a,const Scalar & s)1205 MatExpr operator ^ (const Mat& a, const Scalar& s)
1206 {
1207 checkOperandsExist(a);
1208 MatExpr e;
1209 MatOp_Bin::makeExpr(e, '^', a, s);
1210 return e;
1211 }
1212
operator ^(const Scalar & s,const Mat & a)1213 MatExpr operator ^ (const Scalar& s, const Mat& a)
1214 {
1215 checkOperandsExist(a);
1216 MatExpr e;
1217 MatOp_Bin::makeExpr(e, '^', a, s);
1218 return e;
1219 }
1220
operator ~(const Mat & a)1221 MatExpr operator ~(const Mat& a)
1222 {
1223 checkOperandsExist(a);
1224 MatExpr e;
1225 MatOp_Bin::makeExpr(e, '~', a, Scalar());
1226 return e;
1227 }
1228
abs(const Mat & a)1229 MatExpr abs(const Mat& a)
1230 {
1231 CV_INSTRUMENT_REGION();
1232
1233 checkOperandsExist(a);
1234 MatExpr e;
1235 MatOp_Bin::makeExpr(e, 'a', a, Scalar());
1236 return e;
1237 }
1238
abs(const MatExpr & e)1239 MatExpr abs(const MatExpr& e)
1240 {
1241 CV_INSTRUMENT_REGION();
1242
1243 MatExpr en;
1244 e.op->abs(e, en);
1245 return en;
1246 }
1247
1248
size() const1249 Size MatExpr::size() const
1250 {
1251 if( isT(*this) || isInv(*this) )
1252 return Size(a.rows, a.cols);
1253 if( isSolve(*this) )
1254 return Size(b.cols, a.cols);
1255 if( isInitializer(*this) )
1256 return a.size();
1257 return op ? op->size(*this) : Size();
1258 }
1259
1260
type() const1261 int MatExpr::type() const
1262 {
1263 CV_INSTRUMENT_REGION();
1264
1265 if( isInitializer(*this) )
1266 return a.type();
1267 if( isCmp(*this) )
1268 return CV_MAKETYPE(CV_8U, a.channels());
1269 return op ? op->type(*this) : -1;
1270 }
1271
1272
1273 /////////////////////////////////////////////////////////////////////////////////////////////////////
1274
assign(const MatExpr & e,Mat & m,int _type) const1275 void MatOp_Identity::assign(const MatExpr& e, Mat& m, int _type) const
1276 {
1277 if( _type == -1 || _type == e.a.type() )
1278 m = e.a;
1279 else
1280 {
1281 CV_Assert( CV_MAT_CN(_type) == e.a.channels() );
1282 e.a.convertTo(m, _type);
1283 }
1284 }
1285
makeExpr(MatExpr & res,const Mat & m)1286 inline void MatOp_Identity::makeExpr(MatExpr& res, const Mat& m)
1287 {
1288 res = MatExpr(&g_MatOp_Identity, 0, m, Mat(), Mat(), 1, 0);
1289 }
1290
1291 /////////////////////////////////////////////////////////////////////////////////////////////////////
1292
assign(const MatExpr & e,Mat & m,int _type) const1293 void MatOp_AddEx::assign(const MatExpr& e, Mat& m, int _type) const
1294 {
1295 Mat temp, &dst = _type == -1 || e.a.type() == _type ? m : temp;
1296 if( e.b.data )
1297 {
1298 if( e.s == Scalar() || !e.s.isReal() )
1299 {
1300 if( e.alpha == 1 )
1301 {
1302 if( e.beta == 1 )
1303 cv::add(e.a, e.b, dst);
1304 else if( e.beta == -1 )
1305 cv::subtract(e.a, e.b, dst);
1306 else
1307 cv::scaleAdd(e.b, e.beta, e.a, dst);
1308 }
1309 else if( e.beta == 1 )
1310 {
1311 if( e.alpha == -1 )
1312 cv::subtract(e.b, e.a, dst);
1313 else
1314 cv::scaleAdd(e.a, e.alpha, e.b, dst);
1315 }
1316 else
1317 cv::addWeighted(e.a, e.alpha, e.b, e.beta, 0, dst);
1318
1319 if( !e.s.isReal() )
1320 cv::add(dst, e.s, dst);
1321 }
1322 else
1323 {
1324 if (e.a.channels() > 1)
1325 CV_LOG_ONCE_WARNING(NULL, "OpenCV/MatExpr: processing of multi-channel arrays might be changed in the future: "
1326 "https://github.com/opencv/opencv/issues/16739");
1327 cv::addWeighted(e.a, e.alpha, e.b, e.beta, e.s[0], dst);
1328 }
1329 }
1330 else if( e.s.isReal() && (dst.data != m.data || fabs(e.alpha) != 1))
1331 {
1332 if (e.a.channels() > 1 && e.s[0] != 0.0)
1333 CV_LOG_ONCE_WARNING(NULL, "OpenCV/MatExpr: processing of multi-channel arrays might be changed in the future: "
1334 "https://github.com/opencv/opencv/issues/16739");
1335 e.a.convertTo(m, _type, e.alpha, e.s[0]);
1336 return;
1337 }
1338 else if( e.alpha == 1 )
1339 cv::add(e.a, e.s, dst);
1340 else if( e.alpha == -1 )
1341 cv::subtract(e.s, e.a, dst);
1342 else
1343 {
1344 e.a.convertTo(dst, e.a.type(), e.alpha);
1345 cv::add(dst, e.s, dst);
1346 }
1347
1348 if( dst.data != m.data )
1349 dst.convertTo(m, m.type());
1350 }
1351
1352
add(const MatExpr & e,const Scalar & s,MatExpr & res) const1353 void MatOp_AddEx::add(const MatExpr& e, const Scalar& s, MatExpr& res) const
1354 {
1355 CV_INSTRUMENT_REGION();
1356
1357 res = e;
1358 res.s += s;
1359 }
1360
1361
subtract(const Scalar & s,const MatExpr & e,MatExpr & res) const1362 void MatOp_AddEx::subtract(const Scalar& s, const MatExpr& e, MatExpr& res) const
1363 {
1364 CV_INSTRUMENT_REGION();
1365
1366 res = e;
1367 res.alpha = -res.alpha;
1368 res.beta = -res.beta;
1369 res.s = s - res.s;
1370 }
1371
multiply(const MatExpr & e,double s,MatExpr & res) const1372 void MatOp_AddEx::multiply(const MatExpr& e, double s, MatExpr& res) const
1373 {
1374 CV_INSTRUMENT_REGION();
1375
1376 res = e;
1377 res.alpha *= s;
1378 res.beta *= s;
1379 res.s *= s;
1380 }
1381
divide(double s,const MatExpr & e,MatExpr & res) const1382 void MatOp_AddEx::divide(double s, const MatExpr& e, MatExpr& res) const
1383 {
1384 CV_INSTRUMENT_REGION();
1385
1386 if( isScaled(e) )
1387 MatOp_Bin::makeExpr(res, '/', e.a, Mat(), s/e.alpha);
1388 else
1389 MatOp::divide(s, e, res);
1390 }
1391
1392
transpose(const MatExpr & e,MatExpr & res) const1393 void MatOp_AddEx::transpose(const MatExpr& e, MatExpr& res) const
1394 {
1395 CV_INSTRUMENT_REGION();
1396
1397 if( isScaled(e) )
1398 MatOp_T::makeExpr(res, e.a, e.alpha);
1399 else
1400 MatOp::transpose(e, res);
1401 }
1402
abs(const MatExpr & e,MatExpr & res) const1403 void MatOp_AddEx::abs(const MatExpr& e, MatExpr& res) const
1404 {
1405 CV_INSTRUMENT_REGION();
1406
1407 if( (!e.b.data || e.beta == 0) && fabs(e.alpha) == 1 )
1408 MatOp_Bin::makeExpr(res, 'a', e.a, -e.s*e.alpha);
1409 else if( e.b.data && e.alpha + e.beta == 0 && e.alpha*e.beta == -1 )
1410 MatOp_Bin::makeExpr(res, 'a', e.a, e.b);
1411 else
1412 MatOp::abs(e, res);
1413 }
1414
makeExpr(MatExpr & res,const Mat & a,const Mat & b,double alpha,double beta,const Scalar & s)1415 inline void MatOp_AddEx::makeExpr(MatExpr& res, const Mat& a, const Mat& b, double alpha, double beta, const Scalar& s)
1416 {
1417 res = MatExpr(&g_MatOp_AddEx, 0, a, b, Mat(), alpha, beta, s);
1418 }
1419
1420 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1421
assign(const MatExpr & e,Mat & m,int _type) const1422 void MatOp_Bin::assign(const MatExpr& e, Mat& m, int _type) const
1423 {
1424 Mat temp, &dst = _type == -1 || e.a.type() == _type ? m : temp;
1425
1426 if( e.flags == '*' )
1427 cv::multiply(e.a, e.b, dst, e.alpha);
1428 else if( e.flags == '/' && e.b.data )
1429 cv::divide(e.a, e.b, dst, e.alpha);
1430 else if( e.flags == '/' && !e.b.data )
1431 cv::divide(e.alpha, e.a, dst );
1432 else if( e.flags == '&' && e.b.data )
1433 bitwise_and(e.a, e.b, dst);
1434 else if( e.flags == '&' && !e.b.data )
1435 bitwise_and(e.a, e.s, dst);
1436 else if( e.flags == '|' && e.b.data )
1437 bitwise_or(e.a, e.b, dst);
1438 else if( e.flags == '|' && !e.b.data )
1439 bitwise_or(e.a, e.s, dst);
1440 else if( e.flags == '^' && e.b.data )
1441 bitwise_xor(e.a, e.b, dst);
1442 else if( e.flags == '^' && !e.b.data )
1443 bitwise_xor(e.a, e.s, dst);
1444 else if( e.flags == '~' && !e.b.data )
1445 bitwise_not(e.a, dst);
1446 else if( e.flags == 'm' )
1447 cv::min(e.a, e.b, dst);
1448 else if( e.flags == 'n' )
1449 cv::min(e.a, e.s[0], dst);
1450 else if( e.flags == 'M' )
1451 cv::max(e.a, e.b, dst);
1452 else if( e.flags == 'N' )
1453 cv::max(e.a, e.s[0], dst);
1454 else if( e.flags == 'a' && e.b.data )
1455 cv::absdiff(e.a, e.b, dst);
1456 else if( e.flags == 'a' && !e.b.data )
1457 cv::absdiff(e.a, e.s, dst);
1458 else
1459 CV_Error(CV_StsError, "Unknown operation");
1460
1461 if( dst.data != m.data )
1462 dst.convertTo(m, _type);
1463 }
1464
multiply(const MatExpr & e,double s,MatExpr & res) const1465 void MatOp_Bin::multiply(const MatExpr& e, double s, MatExpr& res) const
1466 {
1467 CV_INSTRUMENT_REGION();
1468
1469 if( e.flags == '*' || e.flags == '/' )
1470 {
1471 res = e;
1472 res.alpha *= s;
1473 }
1474 else
1475 MatOp::multiply(e, s, res);
1476 }
1477
divide(double s,const MatExpr & e,MatExpr & res) const1478 void MatOp_Bin::divide(double s, const MatExpr& e, MatExpr& res) const
1479 {
1480 CV_INSTRUMENT_REGION();
1481
1482 if( e.flags == '/' && (!e.b.data || e.beta == 0) )
1483 MatOp_AddEx::makeExpr(res, e.a, Mat(), s/e.alpha, 0);
1484 else
1485 MatOp::divide(s, e, res);
1486 }
1487
makeExpr(MatExpr & res,char op,const Mat & a,const Mat & b,double scale)1488 inline void MatOp_Bin::makeExpr(MatExpr& res, char op, const Mat& a, const Mat& b, double scale)
1489 {
1490 res = MatExpr(&g_MatOp_Bin, op, a, b, Mat(), scale, b.data ? 1 : 0);
1491 }
1492
makeExpr(MatExpr & res,char op,const Mat & a,const Scalar & s)1493 inline void MatOp_Bin::makeExpr(MatExpr& res, char op, const Mat& a, const Scalar& s)
1494 {
1495 res = MatExpr(&g_MatOp_Bin, op, a, Mat(), Mat(), 1, 0, s);
1496 }
1497
1498 ///////////////////////////////////////////////////////////////////////////////////////////////////////
1499
assign(const MatExpr & e,Mat & m,int _type) const1500 void MatOp_Cmp::assign(const MatExpr& e, Mat& m, int _type) const
1501 {
1502 Mat temp, &dst = _type == -1 || _type == CV_8U ? m : temp;
1503
1504 if( e.b.data )
1505 cv::compare(e.a, e.b, dst, e.flags);
1506 else
1507 cv::compare(e.a, e.alpha, dst, e.flags);
1508
1509 if( dst.data != m.data )
1510 dst.convertTo(m, _type);
1511 }
1512
makeExpr(MatExpr & res,int cmpop,const Mat & a,const Mat & b)1513 inline void MatOp_Cmp::makeExpr(MatExpr& res, int cmpop, const Mat& a, const Mat& b)
1514 {
1515 res = MatExpr(&g_MatOp_Cmp, cmpop, a, b, Mat(), 1, 1);
1516 }
1517
makeExpr(MatExpr & res,int cmpop,const Mat & a,double alpha)1518 inline void MatOp_Cmp::makeExpr(MatExpr& res, int cmpop, const Mat& a, double alpha)
1519 {
1520 res = MatExpr(&g_MatOp_Cmp, cmpop, a, Mat(), Mat(), alpha, 1);
1521 }
1522
1523 /////////////////////////////////////////////////////////////////////////////////////////////////////////
1524
assign(const MatExpr & e,Mat & m,int _type) const1525 void MatOp_T::assign(const MatExpr& e, Mat& m, int _type) const
1526 {
1527 Mat temp, &dst = _type == -1 || _type == e.a.type() ? m : temp;
1528
1529 cv::transpose(e.a, dst);
1530
1531 if( dst.data != m.data || e.alpha != 1 )
1532 dst.convertTo(m, _type, e.alpha);
1533 }
1534
multiply(const MatExpr & e,double s,MatExpr & res) const1535 void MatOp_T::multiply(const MatExpr& e, double s, MatExpr& res) const
1536 {
1537 CV_INSTRUMENT_REGION();
1538
1539 res = e;
1540 res.alpha *= s;
1541 }
1542
transpose(const MatExpr & e,MatExpr & res) const1543 void MatOp_T::transpose(const MatExpr& e, MatExpr& res) const
1544 {
1545 CV_INSTRUMENT_REGION();
1546
1547 if( e.alpha == 1 )
1548 MatOp_Identity::makeExpr(res, e.a);
1549 else
1550 MatOp_AddEx::makeExpr(res, e.a, Mat(), e.alpha, 0);
1551 }
1552
makeExpr(MatExpr & res,const Mat & a,double alpha)1553 inline void MatOp_T::makeExpr(MatExpr& res, const Mat& a, double alpha)
1554 {
1555 res = MatExpr(&g_MatOp_T, 0, a, Mat(), Mat(), alpha, 0);
1556 }
1557
1558 /////////////////////////////////////////////////////////////////////////////////////////////////////////
1559
assign(const MatExpr & e,Mat & m,int _type) const1560 void MatOp_GEMM::assign(const MatExpr& e, Mat& m, int _type) const
1561 {
1562 Mat temp, &dst = _type == -1 || _type == e.a.type() ? m : temp;
1563
1564 cv::gemm(e.a, e.b, e.alpha, e.c, e.beta, dst, e.flags);
1565 if( dst.data != m.data )
1566 dst.convertTo(m, _type);
1567 }
1568
add(const MatExpr & e1,const MatExpr & e2,MatExpr & res) const1569 void MatOp_GEMM::add(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const
1570 {
1571 CV_INSTRUMENT_REGION();
1572
1573 bool i1 = isIdentity(e1), i2 = isIdentity(e2);
1574 double alpha1 = i1 ? 1 : e1.alpha, alpha2 = i2 ? 1 : e2.alpha;
1575
1576 if( isMatProd(e1) && (i2 || isScaled(e2) || isT(e2)) )
1577 MatOp_GEMM::makeExpr(res, (e1.flags & ~CV_GEMM_C_T)|(isT(e2) ? CV_GEMM_C_T : 0),
1578 e1.a, e1.b, alpha1, e2.a, alpha2);
1579 else if( isMatProd(e2) && (i1 || isScaled(e1) || isT(e1)) )
1580 MatOp_GEMM::makeExpr(res, (e2.flags & ~CV_GEMM_C_T)|(isT(e1) ? CV_GEMM_C_T : 0),
1581 e2.a, e2.b, alpha2, e1.a, alpha1);
1582 else if( this == e2.op )
1583 MatOp::add(e1, e2, res);
1584 else
1585 e2.op->add(e1, e2, res);
1586 }
1587
subtract(const MatExpr & e1,const MatExpr & e2,MatExpr & res) const1588 void MatOp_GEMM::subtract(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const
1589 {
1590 CV_INSTRUMENT_REGION();
1591
1592 bool i1 = isIdentity(e1), i2 = isIdentity(e2);
1593 double alpha1 = i1 ? 1 : e1.alpha, alpha2 = i2 ? 1 : e2.alpha;
1594
1595 if( isMatProd(e1) && (i2 || isScaled(e2) || isT(e2)) )
1596 MatOp_GEMM::makeExpr(res, (e1.flags & ~CV_GEMM_C_T)|(isT(e2) ? CV_GEMM_C_T : 0),
1597 e1.a, e1.b, alpha1, e2.a, -alpha2);
1598 else if( isMatProd(e2) && (i1 || isScaled(e1) || isT(e1)) )
1599 MatOp_GEMM::makeExpr(res, (e2.flags & ~CV_GEMM_C_T)|(isT(e1) ? CV_GEMM_C_T : 0),
1600 e2.a, e2.b, -alpha2, e1.a, alpha1);
1601 else if( this == e2.op )
1602 MatOp::subtract(e1, e2, res);
1603 else
1604 e2.op->subtract(e1, e2, res);
1605 }
1606
multiply(const MatExpr & e,double s,MatExpr & res) const1607 void MatOp_GEMM::multiply(const MatExpr& e, double s, MatExpr& res) const
1608 {
1609 CV_INSTRUMENT_REGION();
1610
1611 res = e;
1612 res.alpha *= s;
1613 res.beta *= s;
1614 }
1615
transpose(const MatExpr & e,MatExpr & res) const1616 void MatOp_GEMM::transpose(const MatExpr& e, MatExpr& res) const
1617 {
1618 CV_INSTRUMENT_REGION();
1619
1620 res = e;
1621 res.flags = (!(e.flags & CV_GEMM_A_T) ? CV_GEMM_B_T : 0) |
1622 (!(e.flags & CV_GEMM_B_T) ? CV_GEMM_A_T : 0) |
1623 (!(e.flags & CV_GEMM_C_T) ? CV_GEMM_C_T : 0);
1624 swap(res.a, res.b);
1625 }
1626
makeExpr(MatExpr & res,int flags,const Mat & a,const Mat & b,double alpha,const Mat & c,double beta)1627 inline void MatOp_GEMM::makeExpr(MatExpr& res, int flags, const Mat& a, const Mat& b,
1628 double alpha, const Mat& c, double beta)
1629 {
1630 res = MatExpr(&g_MatOp_GEMM, flags, a, b, c, alpha, beta);
1631 }
1632
1633 ///////////////////////////////////////////////////////////////////////////////////////////////////////
1634
assign(const MatExpr & e,Mat & m,int _type) const1635 void MatOp_Invert::assign(const MatExpr& e, Mat& m, int _type) const
1636 {
1637 Mat temp, &dst = _type == -1 || _type == e.a.type() ? m : temp;
1638
1639 cv::invert(e.a, dst, e.flags);
1640 if( dst.data != m.data )
1641 dst.convertTo(m, _type);
1642 }
1643
matmul(const MatExpr & e1,const MatExpr & e2,MatExpr & res) const1644 void MatOp_Invert::matmul(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const
1645 {
1646 if( isInv(e1) && isIdentity(e2) )
1647 MatOp_Solve::makeExpr(res, e1.flags, e1.a, e2.a);
1648 else if( this == e2.op )
1649 MatOp::matmul(e1, e2, res);
1650 else
1651 e2.op->matmul(e1, e2, res);
1652 }
1653
makeExpr(MatExpr & res,int method,const Mat & m)1654 inline void MatOp_Invert::makeExpr(MatExpr& res, int method, const Mat& m)
1655 {
1656 res = MatExpr(&g_MatOp_Invert, method, m, Mat(), Mat(), 1, 0);
1657 }
1658
1659 /////////////////////////////////////////////////////////////////////////////////////////////////////////
1660
assign(const MatExpr & e,Mat & m,int _type) const1661 void MatOp_Solve::assign(const MatExpr& e, Mat& m, int _type) const
1662 {
1663 Mat temp, &dst = _type == -1 || _type == e.a.type() ? m : temp;
1664
1665 cv::solve(e.a, e.b, dst, e.flags);
1666 if( dst.data != m.data )
1667 dst.convertTo(m, _type);
1668 }
1669
makeExpr(MatExpr & res,int method,const Mat & a,const Mat & b)1670 inline void MatOp_Solve::makeExpr(MatExpr& res, int method, const Mat& a, const Mat& b)
1671 {
1672 res = MatExpr(&g_MatOp_Solve, method, a, b, Mat(), 1, 1);
1673 }
1674
1675 //////////////////////////////////////////////////////////////////////////////////////////////////////////
1676
assign(const MatExpr & e,Mat & m,int _type) const1677 void MatOp_Initializer::assign(const MatExpr& e, Mat& m, int _type) const
1678 {
1679 if( _type == -1 )
1680 _type = e.a.type();
1681
1682 if( e.a.dims <= 2 )
1683 m.create(e.a.size(), _type);
1684 else
1685 m.create(e.a.dims, e.a.size, _type);
1686
1687 if( e.flags == 'I' && e.a.dims <= 2 )
1688 setIdentity(m, Scalar(e.alpha));
1689 else if( e.flags == '0' )
1690 m = Scalar();
1691 else if( e.flags == '1' )
1692 m = Scalar(e.alpha);
1693 else
1694 CV_Error(CV_StsError, "Invalid matrix initializer type");
1695 }
1696
multiply(const MatExpr & e,double s,MatExpr & res) const1697 void MatOp_Initializer::multiply(const MatExpr& e, double s, MatExpr& res) const
1698 {
1699 CV_INSTRUMENT_REGION();
1700
1701 res = e;
1702 res.alpha *= s;
1703 }
1704
makeExpr(MatExpr & res,int method,Size sz,int type,double alpha)1705 inline void MatOp_Initializer::makeExpr(MatExpr& res, int method, Size sz, int type, double alpha)
1706 {
1707 res = MatExpr(getGlobalMatOpInitializer(), method, Mat(sz, type, (void*)(size_t)0xEEEEEEEE), Mat(), Mat(), alpha, 0);
1708 }
1709
makeExpr(MatExpr & res,int method,int ndims,const int * sizes,int type,double alpha)1710 inline void MatOp_Initializer::makeExpr(MatExpr& res, int method, int ndims, const int* sizes, int type, double alpha)
1711 {
1712 res = MatExpr(getGlobalMatOpInitializer(), method, Mat(ndims, sizes, type, (void*)(size_t)0xEEEEEEEE), Mat(), Mat(), alpha, 0);
1713 }
1714
1715 ///////////////////////////////////////////////////////////////////////////////////////////////////////////
1716
t() const1717 MatExpr Mat::t() const
1718 {
1719 CV_INSTRUMENT_REGION();
1720
1721 checkOperandsExist(*this);
1722 MatExpr e;
1723 MatOp_T::makeExpr(e, *this);
1724 return e;
1725 }
1726
inv(int method) const1727 MatExpr Mat::inv(int method) const
1728 {
1729 CV_INSTRUMENT_REGION();
1730
1731 MatExpr e;
1732 MatOp_Invert::makeExpr(e, method, *this);
1733 return e;
1734 }
1735
1736
mul(InputArray m,double scale) const1737 MatExpr Mat::mul(InputArray m, double scale) const
1738 {
1739 CV_INSTRUMENT_REGION();
1740
1741 MatExpr e;
1742 MatOp_Bin::makeExpr(e, '*', *this, m.getMat(), scale);
1743 return e;
1744 }
1745
zeros(int rows,int cols,int type)1746 MatExpr Mat::zeros(int rows, int cols, int type)
1747 {
1748 CV_INSTRUMENT_REGION();
1749
1750 MatExpr e;
1751 MatOp_Initializer::makeExpr(e, '0', Size(cols, rows), type);
1752 return e;
1753 }
1754
zeros(Size size,int type)1755 MatExpr Mat::zeros(Size size, int type)
1756 {
1757 CV_INSTRUMENT_REGION();
1758
1759 MatExpr e;
1760 MatOp_Initializer::makeExpr(e, '0', size, type);
1761 return e;
1762 }
1763
zeros(int ndims,const int * sizes,int type)1764 MatExpr Mat::zeros(int ndims, const int* sizes, int type)
1765 {
1766 CV_INSTRUMENT_REGION();
1767
1768 MatExpr e;
1769 MatOp_Initializer::makeExpr(e, '0', ndims, sizes, type);
1770 return e;
1771 }
1772
ones(int rows,int cols,int type)1773 MatExpr Mat::ones(int rows, int cols, int type)
1774 {
1775 CV_INSTRUMENT_REGION();
1776
1777 MatExpr e;
1778 MatOp_Initializer::makeExpr(e, '1', Size(cols, rows), type);
1779 return e;
1780 }
1781
ones(Size size,int type)1782 MatExpr Mat::ones(Size size, int type)
1783 {
1784 CV_INSTRUMENT_REGION();
1785
1786 MatExpr e;
1787 MatOp_Initializer::makeExpr(e, '1', size, type);
1788 return e;
1789 }
1790
ones(int ndims,const int * sizes,int type)1791 MatExpr Mat::ones(int ndims, const int* sizes, int type)
1792 {
1793 CV_INSTRUMENT_REGION();
1794
1795 MatExpr e;
1796 MatOp_Initializer::makeExpr(e, '1', ndims, sizes, type);
1797 return e;
1798 }
1799
eye(int rows,int cols,int type)1800 MatExpr Mat::eye(int rows, int cols, int type)
1801 {
1802 CV_INSTRUMENT_REGION();
1803
1804 MatExpr e;
1805 MatOp_Initializer::makeExpr(e, 'I', Size(cols, rows), type);
1806 return e;
1807 }
1808
eye(Size size,int type)1809 MatExpr Mat::eye(Size size, int type)
1810 {
1811 CV_INSTRUMENT_REGION();
1812
1813 MatExpr e;
1814 MatOp_Initializer::makeExpr(e, 'I', size, type);
1815 return e;
1816 }
1817
swap(MatExpr & other)1818 void MatExpr::swap(MatExpr& other)
1819 {
1820 using std::swap;
1821
1822 swap(op, other.op);
1823 swap(flags, other.flags);
1824
1825 swap(a, other.a);
1826 swap(b, other.b);
1827 swap(c, other.c);
1828
1829 swap(alpha, other.alpha);
1830 swap(beta, other.beta);
1831
1832 swap(s, other.s);
1833 }
1834
_InputArray(const MatExpr & expr)1835 _InputArray::_InputArray(const MatExpr& expr)
1836 {
1837 if (!isIdentity(expr))
1838 {
1839 Mat result = expr; // TODO improve through refcount == 1 of expr.a (inplace operation is possible - except gemm?)
1840 MatExpr result_expr(result);
1841 swap(const_cast<MatExpr&>(expr), result_expr);
1842 }
1843 CV_Assert(isIdentity(expr));
1844 init(FIXED_TYPE + FIXED_SIZE + MAT + ACCESS_READ, &expr.a);
1845 }
1846
1847 } // cv::
1848