From: Vitaly Tuzov Date: Wed, 11 Jul 2018 19:00:57 +0000 (+0300) Subject: Merge pull request #11904 from terfendail/matx_solve_fix X-Git-Tag: accepted/tizen/6.0/unified/20201030.111113~1^2~600^2~28 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d0a36868121cdfbd840e99d291e6f23f6f890b56;p=platform%2Fupstream%2Fopencv.git Merge pull request #11904 from terfendail/matx_solve_fix Fixed Matx::solve function for non-square matrixes (#11904) --- diff --git a/modules/core/include/opencv2/core/operations.hpp b/modules/core/include/opencv2/core/operations.hpp index 75864ea..3570d06 100644 --- a/modules/core/include/opencv2/core/operations.hpp +++ b/modules/core/include/opencv2/core/operations.hpp @@ -61,7 +61,16 @@ namespace cv namespace internal { -template struct Matx_FastInvOp +template struct Matx_FastInvOp +{ + bool operator()(const Matx<_Tp, m, n>&, Matx<_Tp, n, m>&, int) const + { + CV_Assert(false); + return false; + } +}; + +template struct Matx_FastInvOp<_Tp, m, m> { bool operator()(const Matx<_Tp, m, m>& a, Matx<_Tp, m, m>& b, int method) const { @@ -78,7 +87,7 @@ template struct Matx_FastInvOp } }; -template struct Matx_FastInvOp<_Tp, 2> +template struct Matx_FastInvOp<_Tp, 2, 2> { bool operator()(const Matx<_Tp, 2, 2>& a, Matx<_Tp, 2, 2>& b, int) const { @@ -94,7 +103,7 @@ template struct Matx_FastInvOp<_Tp, 2> } }; -template struct Matx_FastInvOp<_Tp, 3> +template struct Matx_FastInvOp<_Tp, 3, 3> { bool operator()(const Matx<_Tp, 3, 3>& a, Matx<_Tp, 3, 3>& b, int) const { @@ -118,7 +127,17 @@ template struct Matx_FastInvOp<_Tp, 3> }; -template struct Matx_FastSolveOp +template struct Matx_FastSolveOp +{ + bool operator()(const Matx<_Tp, m, l>&, const Matx<_Tp, m, n>&, + Matx<_Tp, l, n>&, int) const + { + CV_Assert(false); + return false; + } +}; + +template struct Matx_FastSolveOp<_Tp, m, m, n> { bool operator()(const Matx<_Tp, m, m>& a, const Matx<_Tp, m, n>& b, Matx<_Tp, m, n>& x, int method) const @@ -132,7 +151,7 @@ template struct Matx_FastSolveOp } }; -template struct Matx_FastSolveOp<_Tp, 2, 1> +template struct Matx_FastSolveOp<_Tp, 2, 2, 1> { bool operator()(const Matx<_Tp, 2, 2>& a, const Matx<_Tp, 2, 1>& b, Matx<_Tp, 2, 1>& x, int) const @@ -147,7 +166,7 @@ template struct Matx_FastSolveOp<_Tp, 2, 1> } }; -template struct Matx_FastSolveOp<_Tp, 3, 1> +template struct Matx_FastSolveOp<_Tp, 3, 3, 1> { bool operator()(const Matx<_Tp, 3, 3>& a, const Matx<_Tp, 3, 1>& b, Matx<_Tp, 3, 1>& x, int) const @@ -195,7 +214,7 @@ Matx<_Tp, n, m> Matx<_Tp, m, n>::inv(int method, bool *p_is_ok /*= NULL*/) const Matx<_Tp, n, m> b; bool ok; if( m == n && (method == DECOMP_LU || method == DECOMP_CHOLESKY) ) - ok = cv::internal::Matx_FastInvOp<_Tp, m>()(*reinterpret_cast*>(this), reinterpret_cast&>(b), method); + ok = cv::internal::Matx_FastInvOp<_Tp, m, n>()(*this, b, method); else { Mat A(*this, false), B(b, false); @@ -210,8 +229,8 @@ Matx<_Tp, n, l> Matx<_Tp, m, n>::solve(const Matx<_Tp, m, l>& rhs, int method) c { Matx<_Tp, n, l> x; bool ok; - if( method == DECOMP_LU || method == DECOMP_CHOLESKY ) - ok = cv::internal::Matx_FastSolveOp<_Tp, m, l>()(*this, rhs, x, method); + if( m == n && (method == DECOMP_LU || method == DECOMP_CHOLESKY) ) + ok = cv::internal::Matx_FastSolveOp<_Tp, m, n, l>()(*this, rhs, x, method); else { Mat A(*this, false), B(rhs, false), X(x, false); diff --git a/modules/core/test/test_math.cpp b/modules/core/test/test_math.cpp index 896df47..2adc8dc 100644 --- a/modules/core/test/test_math.cpp +++ b/modules/core/test/test_math.cpp @@ -3129,6 +3129,21 @@ TEST(Core_QR_Solver, accuracy64f) ASSERT_FALSE(solve(A, B, solutionQR, DECOMP_QR)); } +TEST(Core_Solve, regression_11888) +{ + cv::Matx A( + 2, 1, + 3, 1, + 6, 1 + ); + cv::Vec b(4, 5, 7); + cv::Matx xQR = A.solve(b, DECOMP_QR); + cv::Matx xSVD = A.solve(b, DECOMP_SVD); + EXPECT_LE(cvtest::norm(xQR, xSVD, CV_RELATIVE_L2), FLT_EPSILON); + cv::Matx iA = A.inv(DECOMP_SVD); + EXPECT_LE(cvtest::norm(A*iA, Matx::eye(), CV_RELATIVE_L2), 0.6); +} + softdouble naiveExp(softdouble x) { int exponent = x.getExp();