1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-30 15:53:03 +04:00

Merge pull request #26926 from MaximSmolskiy:fix-getPerspectiveTransform-for-singular-case

Fix getPerspectiveTransform for singular case #26926

### Pull Request Readiness Checklist

Fix #26916 

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [x] There is a reference to the original bug report and related work
- [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
Maxim Smolskiy
2025-03-02 12:44:39 +03:00
committed by GitHub
parent 87cc1643f4
commit dbd3ef9a6f
2 changed files with 71 additions and 4 deletions
+36 -4
View File
@@ -3392,7 +3392,7 @@ cv::Matx23d cv::getRotationMatrix2D_(Point2f center, double angle, double scale)
* vi = ---------------------
* c20*xi + c21*yi + c22
*
* Coefficients are calculated by solving linear system:
* Coefficients are calculated by solving one of 2 linear systems:
* / x0 y0 1 0 0 0 -x0*u0 -y0*u0 \ /c00\ /u0\
* | x1 y1 1 0 0 0 -x1*u1 -y1*u1 | |c01| |u1|
* | x2 y2 1 0 0 0 -x2*u2 -y2*u2 | |c02| |u2|
@@ -3404,12 +3404,28 @@ cv::Matx23d cv::getRotationMatrix2D_(Point2f center, double angle, double scale)
*
* where:
* cij - matrix coefficients, c22 = 1
*
* or
*
* / x0 y0 1 0 0 0 -x0*u0 -y0*u0 -u0 \ /c00\ /0\
* | x1 y1 1 0 0 0 -x1*u1 -y1*u1 -u1 | |c01| |0|
* | x2 y2 1 0 0 0 -x2*u2 -y2*u2 -u2 | |c02| |0|
* | x3 y3 1 0 0 0 -x3*u3 -y3*u3 -u3 |.|c10|=|0|,
* | 0 0 0 x0 y0 1 -x0*v0 -y0*v0 -v0 | |c11| |0|
* | 0 0 0 x1 y1 1 -x1*v1 -y1*v1 -v1 | |c12| |0|
* | 0 0 0 x2 y2 1 -x2*v2 -y2*v2 -v2 | |c20| |0|
* \ 0 0 0 x3 y3 1 -x3*v3 -y3*v3 -v3 / |c21| \0/
* \c22/
*
* where:
* cij - matrix coefficients, c00^2 + c01^2 + c02^2 + c10^2 + c11^2 + c12^2 + c20^2 + c21^2 + c22^2 = 1
*/
cv::Mat cv::getPerspectiveTransform(const Point2f src[], const Point2f dst[], int solveMethod)
{
CV_INSTRUMENT_REGION();
Mat M(3, 3, CV_64F), X(8, 1, CV_64F, M.ptr());
// try c22 = 1
Mat M(3, 3, CV_64F), X8(8, 1, CV_64F, M.ptr());
double a[8][8], b[8];
Mat A(8, 8, CV_64F, a), B(8, 1, CV_64F, b);
@@ -3428,8 +3444,24 @@ cv::Mat cv::getPerspectiveTransform(const Point2f src[], const Point2f dst[], in
b[i+4] = dst[i].y;
}
solve(A, B, X, solveMethod);
M.ptr<double>()[8] = 1.;
if (solve(A, B, X8, solveMethod) && norm(A * X8, B) < 1e-8)
{
M.ptr<double>()[8] = 1.;
return M;
}
// c00^2 + c01^2 + c02^2 + c10^2 + c11^2 + c12^2 + c20^2 + c21^2 + c22^2 = 1
hconcat(A, -B, A);
Mat AtA;
mulTransposed(A, AtA, true);
Mat D, U;
SVDecomp(AtA, D, U, noArray());
Mat X9(9, 1, CV_64F, M.ptr());
U.col(8).copyTo(X9);
return M;
}