18 #include <opencv2/imgproc.hpp>
33 cv::Mat
getRTMatrix(
const cv::Mat& R_,
const cv::Mat& T_,
int forceType)
39 if (R.type() == CV_64F)
41 assert(T.type() == CV_64F);
42 cv::Mat Matrix = cv::Mat::eye(4, 4, CV_64FC1);
44 cv::Mat R33 = cv::Mat(Matrix, cv::Rect(0, 0, 3, 3));
47 cv::Rodrigues(R, R33);
49 else if (R.total() == 9)
52 R.convertTo(R64, CV_64F);
55 for (
int i = 0; i < 3; i++)
56 Matrix.at<
double>(i, 3) = T.ptr<
double>(0)[i];
59 else if (R.depth() == CV_32F)
61 cv::Mat Matrix = cv::Mat::eye(4, 4, CV_32FC1);
62 cv::Mat R33 = cv::Mat(Matrix, cv::Rect(0, 0, 3, 3));
65 cv::Rodrigues(R, R33);
67 else if (R.total() == 9)
70 R.convertTo(R32, CV_32F);
74 for (
int i = 0; i < 3; i++)
75 Matrix.at<
float>(i, 3) = T.ptr<
float>(0)[i];
84 M.convertTo(MTyped, forceType);
88 vector<cv::Mat>
solvePnP(
const vector<cv::Point3f>& objPoints,
89 const std::vector<cv::Point2f>& imgPoints,
90 cv::InputArray cameraMatrix, cv::InputArray distCoeffs)
93 float reprojErr1, reprojErr2;
97 Solver.
solveGeneric(objPoints, imgPoints, cameraMatrix, distCoeffs, Rvec, Tvec,
98 reprojErr1, Rvec2, Tvec2, reprojErr2);
103 void solvePnP(
const vector<cv::Point3f>& objPoints,
104 const std::vector<cv::Point2f>& imgPoints, cv::InputArray cameraMatrix,
105 cv::InputArray distCoeffs, cv::Mat& rvec, cv::Mat& tvec)
107 float reprojErr1, reprojErr2;
108 cv::Mat Rvec2, Tvec2;
111 Solver.
solveGeneric(objPoints, imgPoints, cameraMatrix, distCoeffs, rvec, tvec,
112 reprojErr1, Rvec2, Tvec2, reprojErr2);
115 std::vector<std::pair<cv::Mat, double>>
solvePnP_(
float size,
116 const std::vector<cv::Point2f>& imgPoints,
117 cv::InputArray cameraMatrix,
118 cv::InputArray distCoeffs)
120 cv::Mat Rvec, Tvec, Rvec2, Tvec2;
121 float reprojErr1, reprojErr2;
124 Solver.
solveSquare(size, imgPoints, cameraMatrix, distCoeffs, Rvec, Tvec, reprojErr1,
125 Rvec2, Tvec2, reprojErr2);
128 return { make_pair(
getRTMatrix(Rvec, Tvec, CV_32F), reprojErr1),
129 make_pair(
getRTMatrix(Rvec2, Tvec2, CV_32F), reprojErr2) };
132 std::vector<std::pair<cv::Mat, double>>
solvePnP_(
const std::vector<cv::Point3f>& objPoints,
133 const std::vector<cv::Point2f>& imgPoints,
134 cv::InputArray cameraMatrix,
135 cv::InputArray distCoeffs)
138 float reprojErr1, reprojErr2;
139 cv::Mat Rvec2, Tvec2;
142 Solver.
solveGeneric(objPoints, imgPoints, cameraMatrix, distCoeffs, Rvec, Tvec,
143 reprojErr1, Rvec2, Tvec2, reprojErr2);
146 return { make_pair(
getRTMatrix(Rvec, Tvec, CV_32F), reprojErr1),
147 make_pair(
getRTMatrix(Rvec2, Tvec2, CV_32F), reprojErr2) };
160 cv::InputArray _cameraMatrix, cv::InputArray _distCoeffs,
161 cv::OutputArray _rvec1, cv::OutputArray _tvec1,
162 float& err1, cv::OutputArray _rvec2,
163 cv::OutputArray _tvec2,
float& err2)
165 cv::Mat normalizedImagePoints;
167 if (_cameraMatrix.empty())
170 _imagePoints.copyTo(normalizedImagePoints);
175 cv::undistortPoints(_imagePoints, normalizedImagePoints, _cameraMatrix, _distCoeffs);
180 solveGeneric(_objectPoints, normalizedImagePoints, Ma, Mb);
186 sortPosesByReprojError(_objectPoints, _imagePoints, _cameraMatrix, _distCoeffs, Ma, Mb,
190 rot2vec(M1.colRange(0, 3).rowRange(0, 3), _rvec1);
191 rot2vec(M2.colRange(0, 3).rowRange(0, 3), _rvec2);
193 M1.colRange(3, 4).rowRange(0, 3).copyTo(_tvec1);
194 M2.colRange(3, 4).rowRange(0, 3).copyTo(_tvec2);
198 cv::InputArray _normalizedInputPoints,
199 cv::OutputArray _Ma, cv::OutputArray _Mb)
202 size_t n = _objectPoints.rows() * _objectPoints.cols();
203 int objType = _objectPoints.type();
204 int type_input = _normalizedInputPoints.type();
205 assert((objType == CV_32FC3) | (objType == CV_64FC3));
206 assert((type_input == CV_32FC2) | (type_input == CV_64FC2));
207 assert((_objectPoints.rows() == 1) | (_objectPoints.cols() == 1));
208 assert((_objectPoints.rows() >= 4) | (_objectPoints.cols() >= 4));
209 assert((_normalizedInputPoints.rows() == 1) | (_normalizedInputPoints.cols() == 1));
210 assert(
static_cast<size_t>(_objectPoints.rows() * _objectPoints.cols()) == n);
212 cv::Mat normalizedInputPoints;
213 if (type_input == CV_32FC2)
215 _normalizedInputPoints.getMat().convertTo(normalizedInputPoints, CV_64FC2);
219 normalizedInputPoints = _normalizedInputPoints.getMat();
222 cv::Mat objectInputPoints;
223 if (type_input == CV_32FC3)
225 _objectPoints.getMat().convertTo(objectInputPoints, CV_64FC3);
229 objectInputPoints = _objectPoints.getMat();
232 cv::Mat canonicalObjPoints;
233 cv::Mat MmodelPoints2Canonical;
236 makeCanonicalObjectPoints(objectInputPoints, canonicalObjPoints, MmodelPoints2Canonical);
243 cv::Mat MaCanon, MbCanon;
244 solveCanonicalForm(canonicalObjPoints, normalizedInputPoints, H, MaCanon, MbCanon);
247 cv::Mat Ma = MaCanon * MmodelPoints2Canonical;
248 cv::Mat Mb = MbCanon * MmodelPoints2Canonical;
256 cv::InputArray _normalizedInputPoints,
257 cv::InputArray _H, cv::OutputArray _Ma,
260 _Ma.create(4, 4, CV_64FC1);
261 _Mb.create(4, 4, CV_64FC1);
263 cv::Mat Ma = _Ma.getMat();
264 cv::Mat Mb = _Mb.getMat();
265 cv::Mat H = _H.getMat();
269 Ma.at<
double>(3, 3) = 1;
271 Mb.at<
double>(3, 3) = 1;
274 double j00, j01, j10, j11, v0, v1;
276 j00 = H.at<
double>(0, 0) - H.at<
double>(2, 0) * H.at<
double>(0, 2);
277 j01 = H.at<
double>(0, 1) - H.at<
double>(2, 1) * H.at<
double>(0, 2);
278 j10 = H.at<
double>(1, 0) - H.at<
double>(2, 0) * H.at<
double>(1, 2);
279 j11 = H.at<
double>(1, 1) - H.at<
double>(2, 1) * H.at<
double>(1, 2);
282 v0 = H.at<
double>(0, 2);
283 v1 = H.at<
double>(1, 2);
286 cv::Mat Ra = Ma.colRange(0, 3).rowRange(0, 3);
287 cv::Mat Rb = Mb.colRange(0, 3).rowRange(0, 3);
288 computeRotations(j00, j01, j10, j11, v0, v1, Ra, Rb);
291 cv::Mat ta = Ma.colRange(3, 4).rowRange(0, 3);
292 cv::Mat tb = Mb.colRange(3, 4).rowRange(0, 3);
293 computeTranslation(_canonicalObjPoints, _normalizedInputPoints, Ra, ta);
294 computeTranslation(_canonicalObjPoints, _normalizedInputPoints, Rb, tb);
298 InputArray _cameraMatrix, InputArray _distCoeffs,
299 OutputArray _rvec1, OutputArray _tvec1,
float& err1,
300 OutputArray _rvec2, OutputArray _tvec2,
float& err2)
303 _rvec1.create(3, 1, CV_64FC1);
304 _tvec1.create(3, 1, CV_64FC1);
305 _rvec2.create(3, 1, CV_64FC1);
306 _tvec2.create(3, 1, CV_64FC1);
308 cv::Mat normalizedInputPoints;
309 cv::Mat objectPoints2D;
312 generateSquareObjectCorners2D(squareLength, objectPoints2D);
317 if (_cameraMatrix.empty())
320 _imagePoints.copyTo(normalizedInputPoints);
325 cv::undistortPoints(_imagePoints, normalizedInputPoints, _cameraMatrix, _distCoeffs);
328 if (normalizedInputPoints.type() == CV_32FC2)
330 normalizedInputPoints.convertTo(normalizedInputPoints, CV_64F);
334 homographyFromSquarePoints(normalizedInputPoints, squareLength / 2.0, H);
338 solveCanonicalForm(objectPoints2D, normalizedInputPoints, H, Ma, Mb);
342 cv::Mat objectPoints3D;
343 generateSquareObjectCorners3D(squareLength, objectPoints3D);
345 sortPosesByReprojError(objectPoints3D, normalizedInputPoints, _cameraMatrix,
346 _distCoeffs, Ma, Mb, M1, M2, err1, err2);
349 rot2vec(M1.colRange(0, 3).rowRange(0, 3), _rvec1);
350 rot2vec(M2.colRange(0, 3).rowRange(0, 3), _rvec2);
352 M1.colRange(3, 4).rowRange(0, 3).copyTo(_tvec1);
353 M2.colRange(3, 4).rowRange(0, 3).copyTo(_tvec2);
358 _objectPoints.create(1, 4, CV_64FC3);
359 cv::Mat objectPoints = _objectPoints.getMat();
360 objectPoints.ptr<Vec3d>(0)[0] = Vec3d(-squareLength / 2.0, squareLength / 2.0, 0.0);
361 objectPoints.ptr<Vec3d>(0)[1] = Vec3d(squareLength / 2.0, squareLength / 2.0, 0.0);
362 objectPoints.ptr<Vec3d>(0)[2] = Vec3d(squareLength / 2.0, -squareLength / 2.0, 0.0);
363 objectPoints.ptr<Vec3d>(0)[3] = Vec3d(-squareLength / 2.0, -squareLength / 2.0, 0.0);
368 _objectPoints.create(1, 4, CV_64FC2);
369 cv::Mat objectPoints = _objectPoints.getMat();
370 objectPoints.ptr<Vec2d>(0)[0] = Vec2d(-squareLength / 2.0, squareLength / 2.0);
371 objectPoints.ptr<Vec2d>(0)[1] = Vec2d(squareLength / 2.0, squareLength / 2.0);
372 objectPoints.ptr<Vec2d>(0)[2] = Vec2d(squareLength / 2.0, -squareLength / 2.0);
373 objectPoints.ptr<Vec2d>(0)[3] = Vec2d(-squareLength / 2.0, -squareLength / 2.0);
378 assert(_objectPoints.type() == CV_64FC3);
380 size_t n =
static_cast<size_t>(_objectPoints.rows() * _objectPoints.cols());
386 for (
size_t i = 0; i < n; i++)
388 cv::Mat p(_objectPoints.getMat().at<Point3d>(i));
389 q = R * p + _tvec.getMat();
391 if (q.depth() == CV_64FC1)
397 z =
static_cast<double>(q.at<
float>(2));
406 return zBar /
static_cast<double>(n);
411 assert(_R.type() == CV_64FC1);
412 assert(_R.rows() == 3);
413 assert(_R.cols() == 3);
415 _r.create(3, 1, CV_64FC1);
417 cv::Mat R = _R.getMat();
418 cv::Mat rvec = _r.getMat();
420 double trace = R.at<
double>(0, 0) + R.at<
double>(1, 1) + R.at<
double>(2, 2);
421 double w_norm = acos((trace - 1.0) / 2.0);
423 double eps = std::numeric_limits<float>::epsilon();
424 double d = 1 / (2 * sin(w_norm)) * w_norm;
431 c0 = R.at<
double>(2, 1) - R.at<
double>(1, 2);
432 c1 = R.at<
double>(0, 2) - R.at<
double>(2, 0);
433 c2 = R.at<
double>(1, 0) - R.at<
double>(0, 1);
434 rvec.at<
double>(0) =
d * c0;
435 rvec.at<
double>(1) =
d * c1;
436 rvec.at<
double>(2) =
d * c2;
441 InputArray _R, OutputArray _t)
448 assert(_objectPoints.type() == CV_64FC2);
449 assert(_normalizedImgPoints.type() == CV_64FC2);
450 assert(_R.type() == CV_64FC1);
452 assert((_R.rows() == 3) & (_R.cols() == 3));
453 assert((_objectPoints.rows() == 1) | (_objectPoints.cols() == 1));
454 assert((_normalizedImgPoints.rows() == 1) | (_normalizedImgPoints.cols() == 1));
456 size_t n =
static_cast<size_t>(_normalizedImgPoints.rows() * _normalizedImgPoints.cols());
457 assert(n ==
static_cast<size_t>(_objectPoints.rows() * _objectPoints.cols()));
459 cv::Mat objectPoints = _objectPoints.getMat();
460 cv::Mat imgPoints = _normalizedImgPoints.getMat();
462 _t.create(3, 1, CV_64FC1);
464 cv::Mat R = _R.getMat();
481 double S00, S01, S02;
482 double S10, S11, S12;
483 double S20, S21, S22;
491 for (
size_t i = 0; i < n; i++)
493 rx = R.at<
double>(0, 0) * objectPoints.at<Vec2d>(i)(0) +
494 R.at<
double>(0, 1) * objectPoints.at<Vec2d>(i)(1);
495 ry = R.at<
double>(1, 0) * objectPoints.at<Vec2d>(i)(0) +
496 R.at<
double>(1, 1) * objectPoints.at<Vec2d>(i)(1);
497 rz = R.at<
double>(2, 0) * objectPoints.at<Vec2d>(i)(0) +
498 R.at<
double>(2, 1) * objectPoints.at<Vec2d>(i)(1);
500 a2 = -imgPoints.at<Vec2d>(i)(0);
501 b2 = -imgPoints.at<Vec2d>(i)(1);
507 ATA22 = ATA22 + a2 * a2 + b2 * b2;
514 ATb2 = ATb2 + a2 * bx + b2 * by;
517 double detAInv = 1.0 / (ATA00 * ATA11 * ATA22 - ATA00 * ATA12 * ATA21 - ATA02 * ATA11 * ATA20);
520 S00 = ATA11 * ATA22 - ATA12 * ATA21;
522 S02 = -ATA02 * ATA11;
524 S11 = ATA00 * ATA22 - ATA02 * ATA20;
525 S12 = -ATA00 * ATA12;
526 S20 = -ATA11 * ATA20;
527 S21 = -ATA00 * ATA21;
532 t.at<
double>(0) = detAInv * (S00 * ATb0 + S01 * ATb1 + S02 * ATb2);
533 t.at<
double>(1) = detAInv * (S10 * ATb0 + S11 * ATb1 + S12 * ATb2);
534 t.at<
double>(2) = detAInv * (S20 * ATb0 + S21 * ATb1 + S22 * ATb2);
538 double p,
double q, OutputArray _R1, OutputArray _R2)
541 _R1.create(3, 3, CV_64FC1);
542 _R2.create(3, 3, CV_64FC1);
544 double a00, a01, a10, a11, ata00, ata01, ata11, b00, b01, b10, b11, binv00, binv01,
547 double rtilde00, rtilde01, rtilde10, rtilde11;
548 double rtilde00_2, rtilde01_2, rtilde10_2, rtilde11_2;
549 double b0, b1, gamma, dtinv;
553 cv::Mat v(3, 1, CV_64FC1);
557 rotateVec2ZAxis(v, Rv);
562 double rv00, rv01, rv02;
563 double rv10, rv11, rv12;
564 double rv20, rv21, rv22;
565 rv00 = Rv.at<
double>(0, 0);
566 rv01 = Rv.at<
double>(0, 1);
567 rv02 = Rv.at<
double>(0, 2);
569 rv10 = Rv.at<
double>(1, 0);
570 rv11 = Rv.at<
double>(1, 1);
571 rv12 = Rv.at<
double>(1, 2);
573 rv20 = Rv.at<
double>(2, 0);
574 rv21 = Rv.at<
double>(2, 1);
575 rv22 = Rv.at<
double>(2, 2);
577 b00 = rv00 - p * rv20;
578 b01 = rv01 - p * rv21;
579 b10 = rv10 - q * rv20;
580 b11 = rv11 - q * rv21;
582 dtinv = 1.0 / ((b00 * b11 - b01 * b10));
584 binv00 = dtinv * b11;
585 binv01 = -dtinv * b01;
586 binv10 = -dtinv * b10;
587 binv11 = dtinv * b00;
589 a00 = binv00 * j00 + binv01 * j10;
590 a01 = binv00 * j01 + binv01 * j11;
591 a10 = binv10 * j00 + binv11 * j10;
592 a11 = binv10 * j01 + binv11 * j11;
595 ata00 = a00 * a00 + a01 * a01;
596 ata01 = a00 * a10 + a01 * a11;
597 ata11 = a10 * a10 + a11 * a11;
600 0.5 * (ata00 + ata11 + sqrt((ata00 - ata11) * (ata00 - ata11) + 4.0 * ata01 * ata01)));
603 rtilde00 = a00 / gamma;
604 rtilde01 = a01 / gamma;
605 rtilde10 = a10 / gamma;
606 rtilde11 = a11 / gamma;
608 rtilde00_2 = rtilde00 * rtilde00;
609 rtilde01_2 = rtilde01 * rtilde01;
610 rtilde10_2 = rtilde10 * rtilde10;
611 rtilde11_2 = rtilde11 * rtilde11;
613 b0 = sqrt(-rtilde00_2 - rtilde10_2 + 1);
614 b1 = sqrt(-rtilde01_2 - rtilde11_2 + 1);
615 sp = (-rtilde00 * rtilde01 - rtilde10 * rtilde11);
623 Mat R1 = _R1.getMat();
624 Mat R2 = _R2.getMat();
626 R1.at<
double>(0, 0) = (rtilde00)*rv00 + (rtilde10)*rv01 + (b0)*rv02;
627 R1.at<
double>(0, 1) = (rtilde01)*rv00 + (rtilde11)*rv01 + (b1)*rv02;
628 R1.at<
double>(0, 2) = (b1 * rtilde10 - b0 * rtilde11) * rv00 +
629 (b0 * rtilde01 - b1 * rtilde00) * rv01 +
630 (rtilde00 * rtilde11 - rtilde01 * rtilde10) * rv02;
631 R1.at<
double>(1, 0) = (rtilde00)*rv10 + (rtilde10)*rv11 + (b0)*rv12;
632 R1.at<
double>(1, 1) = (rtilde01)*rv10 + (rtilde11)*rv11 + (b1)*rv12;
633 R1.at<
double>(1, 2) = (b1 * rtilde10 - b0 * rtilde11) * rv10 +
634 (b0 * rtilde01 - b1 * rtilde00) * rv11 +
635 (rtilde00 * rtilde11 - rtilde01 * rtilde10) * rv12;
636 R1.at<
double>(2, 0) = (rtilde00)*rv20 + (rtilde10)*rv21 + (b0)*rv22;
637 R1.at<
double>(2, 1) = (rtilde01)*rv20 + (rtilde11)*rv21 + (b1)*rv22;
638 R1.at<
double>(2, 2) = (b1 * rtilde10 - b0 * rtilde11) * rv20 +
639 (b0 * rtilde01 - b1 * rtilde00) * rv21 +
640 (rtilde00 * rtilde11 - rtilde01 * rtilde10) * rv22;
642 R2.at<
double>(0, 0) = (rtilde00)*rv00 + (rtilde10)*rv01 + (-b0) * rv02;
643 R2.at<
double>(0, 1) = (rtilde01)*rv00 + (rtilde11)*rv01 + (-b1) * rv02;
644 R2.at<
double>(0, 2) = (b0 * rtilde11 - b1 * rtilde10) * rv00 +
645 (b1 * rtilde00 - b0 * rtilde01) * rv01 +
646 (rtilde00 * rtilde11 - rtilde01 * rtilde10) * rv02;
647 R2.at<
double>(1, 0) = (rtilde00)*rv10 + (rtilde10)*rv11 + (-b0) * rv12;
648 R2.at<
double>(1, 1) = (rtilde01)*rv10 + (rtilde11)*rv11 + (-b1) * rv12;
649 R2.at<
double>(1, 2) = (b0 * rtilde11 - b1 * rtilde10) * rv10 +
650 (b1 * rtilde00 - b0 * rtilde01) * rv11 +
651 (rtilde00 * rtilde11 - rtilde01 * rtilde10) * rv12;
652 R2.at<
double>(2, 0) = (rtilde00)*rv20 + (rtilde10)*rv21 + (-b0) * rv22;
653 R2.at<
double>(2, 1) = (rtilde01)*rv20 + (rtilde11)*rv21 + (-b1) * rv22;
654 R2.at<
double>(2, 2) = (b0 * rtilde11 - b1 * rtilde10) * rv20 +
655 (b1 * rtilde00 - b0 * rtilde01) * rv21 +
656 (rtilde00 * rtilde11 - rtilde01 * rtilde10) * rv22;
661 double halfLength, OutputArray H_)
663 assert((_targetPoints.type() == CV_32FC2) | (_targetPoints.type() == CV_64FC2));
665 cv::Mat pts = _targetPoints.getMat();
666 H_.create(3, 3, CV_64FC1);
674 if (_targetPoints.type() == CV_32FC2)
676 p1x = -pts.at<Vec2f>(0)(0);
677 p1y = -pts.at<Vec2f>(0)(1);
679 p2x = -pts.at<Vec2f>(1)(0);
680 p2y = -pts.at<Vec2f>(1)(1);
682 p3x = -pts.at<Vec2f>(2)(0);
683 p3y = -pts.at<Vec2f>(2)(1);
685 p4x = -pts.at<Vec2f>(3)(0);
686 p4y = -pts.at<Vec2f>(3)(1);
690 p1x = -pts.at<Vec2d>(0)(0);
691 p1y = -pts.at<Vec2d>(0)(1);
693 p2x = -pts.at<Vec2d>(1)(0);
694 p2y = -pts.at<Vec2d>(1)(1);
696 p3x = -pts.at<Vec2d>(2)(0);
697 p3y = -pts.at<Vec2d>(2)(1);
699 p4x = -pts.at<Vec2d>(3)(0);
700 p4y = -pts.at<Vec2d>(3)(1);
704 double detsInv = -1 / (halfLength * (p1x * p2y - p2x * p1y - p1x * p4y + p2x * p3y -
705 p3x * p2y + p4x * p1y + p3x * p4y - p4x * p3y));
708 detsInv * (p1x * p3x * p2y - p2x * p3x * p1y - p1x * p4x * p2y + p2x * p4x * p1y -
709 p1x * p3x * p4y + p1x * p4x * p3y + p2x * p3x * p4y - p2x * p4x * p3y);
711 detsInv * (p1x * p2x * p3y - p1x * p3x * p2y - p1x * p2x * p4y + p2x * p4x * p1y +
712 p1x * p3x * p4y - p3x * p4x * p1y - p2x * p4x * p3y + p3x * p4x * p2y);
714 detsInv * halfLength *
715 (p1x * p2x * p3y - p2x * p3x * p1y - p1x * p2x * p4y + p1x * p4x * p2y -
716 p1x * p4x * p3y + p3x * p4x * p1y + p2x * p3x * p4y - p3x * p4x * p2y);
718 detsInv * (p1x * p2y * p3y - p2x * p1y * p3y - p1x * p2y * p4y + p2x * p1y * p4y -
719 p3x * p1y * p4y + p4x * p1y * p3y + p3x * p2y * p4y - p4x * p2y * p3y);
721 detsInv * (p2x * p1y * p3y - p3x * p1y * p2y - p1x * p2y * p4y + p4x * p1y * p2y +
722 p1x * p3y * p4y - p4x * p1y * p3y - p2x * p3y * p4y + p3x * p2y * p4y);
724 detsInv * halfLength *
725 (p1x * p2y * p3y - p3x * p1y * p2y - p2x * p1y * p4y + p4x * p1y * p2y -
726 p1x * p3y * p4y + p3x * p1y * p4y + p2x * p3y * p4y - p4x * p2y * p3y);
727 H.at<
double>(2, 0) = -detsInv * (p1x * p3y - p3x * p1y - p1x * p4y - p2x * p3y +
728 p3x * p2y + p4x * p1y + p2x * p4y - p4x * p2y);
729 H.at<
double>(2, 1) = detsInv * (p1x * p2y - p2x * p1y - p1x * p3y + p3x * p1y +
730 p2x * p4y - p4x * p2y - p3x * p4y + p4x * p3y);
731 H.at<
double>(2, 2) = 1.0;
735 OutputArray _canonicalObjPoints,
736 OutputArray _MmodelPoints2Canonical)
738 int objType = _objectPoints.type();
739 assert((objType == CV_64FC3) | (objType == CV_32FC3));
741 size_t n = _objectPoints.rows() * _objectPoints.cols();
743 _canonicalObjPoints.create(1, n, CV_64FC2);
744 _MmodelPoints2Canonical.create(4, 4, CV_64FC1);
746 cv::Mat objectPoints = _objectPoints.getMat();
747 cv::Mat canonicalObjPoints = _canonicalObjPoints.getMat();
749 cv::Mat UZero(3, n, CV_64FC1);
754 bool isOnZPlane =
true;
755 for (
size_t i = 0; i < n; i++)
758 if (objType == CV_32FC3)
760 x =
static_cast<double>(objectPoints.at<Vec3f>(i)[0]);
761 y =
static_cast<double>(objectPoints.at<Vec3f>(i)[1]);
762 z =
static_cast<double>(objectPoints.at<Vec3f>(i)[2]);
766 x = objectPoints.at<Vec3d>(i)[0];
767 y = objectPoints.at<Vec3d>(i)[1];
768 z = objectPoints.at<Vec3d>(i)[2];
779 UZero.at<
double>(0, i) = x;
780 UZero.at<
double>(1, i) = y;
781 UZero.at<
double>(2, i) = z;
783 xBar = xBar / (double)n;
784 yBar = yBar / (double)n;
785 zBar = zBar / (double)n;
787 for (
size_t i = 0; i < n; i++)
789 UZero.at<
double>(0, i) -= xBar;
790 UZero.at<
double>(1, i) -= yBar;
791 UZero.at<
double>(2, i) -= zBar;
794 cv::Mat MCenter(4, 4, CV_64FC1);
796 MCenter.at<
double>(0, 0) = 1;
797 MCenter.at<
double>(1, 1) = 1;
798 MCenter.at<
double>(2, 2) = 1;
799 MCenter.at<
double>(3, 3) = 1;
801 MCenter.at<
double>(0, 3) = -xBar;
802 MCenter.at<
double>(1, 3) = -yBar;
803 MCenter.at<
double>(2, 3) = -zBar;
808 MCenter.copyTo(_MmodelPoints2Canonical);
809 for (
size_t i = 0; i < n; i++)
811 canonicalObjPoints.at<Vec2d>(i)[0] = UZero.at<
double>(0, i);
812 canonicalObjPoints.at<Vec2d>(i)[1] = UZero.at<
double>(1, i);
817 cv::Mat UZeroAligned(3, n, CV_64FC1);
820 if (!computeObjextSpaceR3Pts(objectPoints, R))
824 computeObjextSpaceRSvD(UZero, R);
827 UZeroAligned = R * UZero;
829 for (
size_t i = 0; i < n; i++)
831 canonicalObjPoints.at<Vec2d>(i)[0] = UZeroAligned.at<
double>(0, i);
832 canonicalObjPoints.at<Vec2d>(i)[1] = UZeroAligned.at<
double>(1, i);
833 assert(abs(UZeroAligned.at<
double>(2, i)) <=
IPPE_SMALL);
836 cv::Mat MRot(4, 4, CV_64FC1);
838 MRot.at<
double>(3, 3) = 1;
840 R.copyTo(MRot.colRange(0, 3).rowRange(0, 3));
841 cv::Mat Mb = MRot * MCenter;
842 Mb.copyTo(_MmodelPoints2Canonical);
847 cv::InputArray _cameraMatrix, cv::InputArray _distCoeffs,
848 cv::InputArray _M,
float& err)
850 cv::Mat projectedPoints;
851 cv::Mat imagePoints = _imagePoints.getMat();
853 rot2vec(_M.getMat().colRange(0, 3).rowRange(0, 3), r);
855 if (_cameraMatrix.empty())
858 cv::Mat K(3, 3, CV_64FC1);
860 K.at<
double>(0, 0) = 1;
861 K.at<
double>(1, 1) = 1;
862 K.at<
double>(2, 2) = 1;
864 cv::projectPoints(_objectPoints, r, _M.getMat().colRange(3, 4).rowRange(0, 3), K, kc,
869 cv::projectPoints(_objectPoints, r, _M.getMat().colRange(3, 4).rowRange(0, 3),
870 _cameraMatrix, _distCoeffs, projectedPoints);
874 size_t n = _objectPoints.rows() * _objectPoints.cols();
877 for (
size_t i = 0; i < n; i++)
879 if (projectedPoints.depth() == CV_32FC1)
881 dx = projectedPoints.at<Vec2f>(i)[0] - imagePoints.at<Vec2f>(i)[0];
882 dy = projectedPoints.at<Vec2f>(i)[1] - imagePoints.at<Vec2f>(i)[1];
886 dx = projectedPoints.at<Vec2d>(i)[0] - imagePoints.at<Vec2d>(i)[0];
887 dy = projectedPoints.at<Vec2d>(i)[1] - imagePoints.at<Vec2d>(i)[1];
890 err += dx * dx + dy * dy;
892 err = sqrt(err / (2.0
f * n));
896 cv::InputArray _imagePoints,
897 cv::InputArray _cameraMatrix,
898 cv::InputArray _distCoeffs, cv::InputArray _Ma,
899 cv::InputArray _Mb, cv::OutputArray _M1,
900 cv::OutputArray _M2,
float& err1,
float& err2)
903 evalReprojError(_objectPoints, _imagePoints, _cameraMatrix, _distCoeffs, _Ma, erra);
904 evalReprojError(_objectPoints, _imagePoints, _cameraMatrix, _distCoeffs, _Mb, errb);
924 cv::OutputArray _T, cv::OutputArray _Ti)
926 cv::Mat Data = _Data.getMat();
927 int numPoints = Data.rows * Data.cols;
928 assert((Data.rows == 1) | (Data.cols == 1));
929 assert((Data.channels() == 2) | (Data.channels() == 3));
930 assert(numPoints >= 4);
932 int dataType = _Data.type();
933 assert((dataType == CV_64FC2) | (dataType == CV_64FC3) | (dataType == CV_32FC2) |
934 (dataType == CV_32FC3));
936 _DataN.create(2, numPoints, CV_64FC1);
938 _T.create(3, 3, CV_64FC1);
939 _Ti.create(3, 3, CV_64FC1);
941 cv::Mat DataN = _DataN.getMat();
942 cv::Mat T = _T.getMat();
943 cv::Mat Ti = _Ti.getMat();
949 int numChannels = Data.channels();
953 for (
int i = 0; i < numPoints; i++)
955 if (numChannels == 2)
957 if (dataType == CV_32FC2)
959 xm = xm + Data.at<Vec2f>(i)[0];
960 ym = ym + Data.at<Vec2f>(i)[1];
964 xm = xm + Data.at<Vec2d>(i)[0];
965 ym = ym + Data.at<Vec2d>(i)[1];
970 if (dataType == CV_32FC3)
972 xm = xm + Data.at<Vec3f>(i)[0];
973 ym = ym + Data.at<Vec3f>(i)[1];
977 xm = xm + Data.at<Vec3d>(i)[0];
978 ym = ym + Data.at<Vec3d>(i)[1];
982 xm = xm / (double)numPoints;
983 ym = ym / (double)numPoints;
988 for (
int i = 0; i < numPoints; i++)
990 if (numChannels == 2)
992 if (dataType == CV_32FC2)
994 xh = Data.at<Vec2f>(i)[0] - xm;
995 yh = Data.at<Vec2f>(i)[1] - ym;
999 xh = Data.at<Vec2d>(i)[0] - xm;
1000 yh = Data.at<Vec2d>(i)[1] - ym;
1005 if (dataType == CV_32FC3)
1007 xh = Data.at<Vec3f>(i)[0] - xm;
1008 yh = Data.at<Vec3f>(i)[1] - ym;
1012 xh = Data.at<Vec3d>(i)[0] - xm;
1013 yh = Data.at<Vec3d>(i)[1] - ym;
1017 DataN.at<
double>(0, i) = xh;
1018 DataN.at<
double>(1, i) = yh;
1019 kappa = kappa + xh * xh + yh * yh;
1021 double beta = sqrt(2 * numPoints / kappa);
1022 DataN = DataN * beta;
1024 T.at<
double>(0, 0) = 1.0 / beta;
1025 T.at<
double>(1, 1) = 1.0 / beta;
1027 T.at<
double>(0, 2) = xm;
1028 T.at<
double>(1, 2) = ym;
1030 T.at<
double>(2, 2) = 1;
1032 Ti.at<
double>(0, 0) = beta;
1033 Ti.at<
double>(1, 1) = beta;
1035 Ti.at<
double>(0, 2) = -beta * xm;
1036 Ti.at<
double>(1, 2) = -beta * ym;
1038 Ti.at<
double>(2, 2) = 1;
1044 _H.create(3, 3, CV_64FC1);
1045 cv::Mat H = _H.getMat();
1047 cv::Mat DataA, DataB, TA, TAi, TB, TBi;
1053 assert(n == DataB.cols);
1055 cv::Mat C1(1, n, CV_64FC1);
1056 cv::Mat C2(1, n, CV_64FC1);
1057 cv::Mat C3(1, n, CV_64FC1);
1058 cv::Mat C4(1, n, CV_64FC1);
1060 cv::Mat Mx(n, 3, CV_64FC1);
1061 cv::Mat My(n, 3, CV_64FC1);
1063 double mC1, mC2, mC3, mC4;
1069 for (
int i = 0; i < n; i++)
1071 C1.at<
double>(0, i) = -DataB.at<
double>(0, i) * DataA.at<
double>(0, i);
1072 C2.at<
double>(0, i) = -DataB.at<
double>(0, i) * DataA.at<
double>(1, i);
1073 C3.at<
double>(0, i) = -DataB.at<
double>(1, i) * DataA.at<
double>(0, i);
1074 C4.at<
double>(0, i) = -DataB.at<
double>(1, i) * DataA.at<
double>(1, i);
1076 mC1 = mC1 + C1.at<
double>(0, i);
1077 mC2 = mC2 + C2.at<
double>(0, i);
1078 mC3 = mC3 + C3.at<
double>(0, i);
1079 mC4 = mC4 + C4.at<
double>(0, i);
1087 for (
int i = 0; i < n; i++)
1089 Mx.at<
double>(i, 0) = C1.at<
double>(0, i) - mC1;
1090 Mx.at<
double>(i, 1) = C2.at<
double>(0, i) - mC2;
1091 Mx.at<
double>(i, 2) = -DataB.at<
double>(0, i);
1093 My.at<
double>(i, 0) = C3.at<
double>(0, i) - mC3;
1094 My.at<
double>(i, 1) = C4.at<
double>(0, i) - mC4;
1095 My.at<
double>(i, 2) = -DataB.at<
double>(1, i);
1098 cv::Mat DataAT, DataADataAT, DataADataATi, Pp, Bx, By, Ex, Ey, D;
1100 cv::transpose(DataA, DataAT);
1101 DataADataAT = DataA * DataAT;
1102 double dt = DataADataAT.at<
double>(0, 0) * DataADataAT.at<
double>(1, 1) -
1103 DataADataAT.at<
double>(0, 1) * DataADataAT.at<
double>(1, 0);
1105 DataADataATi = cv::Mat(2, 2, CV_64FC1);
1106 DataADataATi.at<
double>(0, 0) = DataADataAT.at<
double>(1, 1) / dt;
1107 DataADataATi.at<
double>(0, 1) = -DataADataAT.at<
double>(0, 1) / dt;
1108 DataADataATi.at<
double>(1, 0) = -DataADataAT.at<
double>(1, 0) / dt;
1109 DataADataATi.at<
double>(1, 1) = DataADataAT.at<
double>(0, 0) / dt;
1111 Pp = DataADataATi * DataA;
1119 D = cv::Mat(2 * n, 3, CV_64FC1);
1122 for (
int i = 0; i < n; i++)
1124 D.at<
double>(i, 0) = Mx.at<
double>(i, 0) - Ex.at<
double>(i, 0);
1125 D.at<
double>(i, 1) = Mx.at<
double>(i, 1) - Ex.at<
double>(i, 1);
1126 D.at<
double>(i, 2) = Mx.at<
double>(i, 2) - Ex.at<
double>(i, 2);
1128 D.at<
double>(i + n, 0) = My.at<
double>(i, 0) - Ey.at<
double>(i, 0);
1129 D.at<
double>(i + n, 1) = My.at<
double>(i, 1) - Ey.at<
double>(i, 1);
1130 D.at<
double>(i + n, 2) = My.at<
double>(i, 2) - Ey.at<
double>(i, 2);
1133 cv::transpose(D, DT);
1136 cv::Mat S, U, V, h12, h45;
1139 cv::eigen(DDT, S, U);
1141 cv::Mat h789(3, 1, CV_64FC1);
1142 h789.at<
double>(0, 0) = U.at<
double>(2, 0);
1143 h789.at<
double>(1, 0) = U.at<
double>(2, 1);
1144 h789.at<
double>(2, 0) = U.at<
double>(2, 2);
1149 h3 = -(mC1 * h789.at<
double>(0, 0) + mC2 * h789.at<
double>(1, 0));
1150 h6 = -(mC3 * h789.at<
double>(0, 0) + mC4 * h789.at<
double>(1, 0));
1152 H.at<
double>(0, 0) = h12.at<
double>(0, 0);
1153 H.at<
double>(0, 1) = h12.at<
double>(1, 0);
1154 H.at<
double>(0, 2) = h3;
1156 H.at<
double>(1, 0) = h45.at<
double>(0, 0);
1157 H.at<
double>(1, 1) = h45.at<
double>(1, 0);
1158 H.at<
double>(1, 2) = h6;
1160 H.at<
double>(2, 0) = h789.at<
double>(0, 0);
1161 H.at<
double>(2, 1) = h789.at<
double>(1, 0);
1162 H.at<
double>(2, 2) = h789.at<
double>(2, 0);
1165 H = H / H.at<
double>(2, 2);
1171 _Ra.create(3, 3, CV_64FC1);
1172 Mat Ra = _Ra.getMat();
1174 double ax = _a.getMat().at<
double>(0);
1175 double ay = _a.getMat().at<
double>(1);
1176 double az = _a.getMat().at<
double>(2);
1178 double nrm = sqrt(ax * ax + ay * ay + az * az);
1185 if (abs(1.0 + c) < std::numeric_limits<float>::epsilon())
1188 Ra.at<
double>(0, 0) = 1.0;
1189 Ra.at<
double>(1, 1) = 1.0;
1190 Ra.at<
double>(2, 2) = -1.0;
1194 double d = 1.0 / (1.0 + c);
1195 double ax2 = ax * ax;
1196 double ay2 = ay * ay;
1197 double axay = ax * ay;
1199 Ra.at<
double>(0, 0) = -ax2 *
d + 1.0;
1200 Ra.at<
double>(0, 1) = -axay *
d;
1201 Ra.at<
double>(0, 2) = -ax;
1203 Ra.at<
double>(1, 0) = -axay *
d;
1204 Ra.at<
double>(1, 1) = -ay2 *
d + 1.0;
1205 Ra.at<
double>(1, 2) = -ay;
1207 Ra.at<
double>(2, 0) = ax;
1208 Ra.at<
double>(2, 1) = ay;
1209 Ra.at<
double>(2, 2) = 1.0 - (ax2 + ay2) *
d;
1216 double p1x, p1y, p1z;
1217 double p2x, p2y, p2z;
1218 double p3x, p3y, p3z;
1220 cv::Mat objectPoints = _objectPoints.getMat();
1221 size_t n = objectPoints.rows * objectPoints.cols;
1222 if (objectPoints.type() == CV_32FC3)
1224 p1x = objectPoints.at<Vec3f>(0)[0];
1225 p1y = objectPoints.at<Vec3f>(0)[1];
1226 p1z = objectPoints.at<Vec3f>(0)[2];
1228 p2x = objectPoints.at<Vec3f>(1)[0];
1229 p2y = objectPoints.at<Vec3f>(1)[1];
1230 p2z = objectPoints.at<Vec3f>(1)[2];
1232 p3x = objectPoints.at<Vec3f>(2)[0];
1233 p3y = objectPoints.at<Vec3f>(2)[1];
1234 p3z = objectPoints.at<Vec3f>(2)[2];
1238 p1x = objectPoints.at<Vec3d>(0)[0];
1239 p1y = objectPoints.at<Vec3d>(0)[1];
1240 p1z = objectPoints.at<Vec3d>(0)[2];
1242 p2x = objectPoints.at<Vec3d>(1)[0];
1243 p2y = objectPoints.at<Vec3d>(1)[1];
1244 p2z = objectPoints.at<Vec3d>(1)[2];
1246 p3x = objectPoints.at<Vec3d>(2)[0];
1247 p3y = objectPoints.at<Vec3d>(2)[1];
1248 p3z = objectPoints.at<Vec3d>(2)[2];
1251 double nx = (p1y - p2y) * (p1z - p3z) - (p1y - p3y) * (p1z - p2z);
1252 double ny = (p1x - p3x) * (p1z - p2z) - (p1x - p2x) * (p1z - p3z);
1253 double nz = (p1x - p2x) * (p1y - p3y) - (p1x - p3x) * (p1y - p2y);
1255 double nrm = sqrt(nx * nx + ny * ny + nz * nz);
1261 cv::Mat v(3, 1, CV_64FC1);
1262 v.at<
double>(0) = nx;
1263 v.at<
double>(1) = ny;
1264 v.at<
double>(2) = nz;
1265 rotateVec2ZAxis(v, R);
1278 _R.create(3, 3, CV_64FC1);
1279 cv::Mat R = _R.getMat();
1284 s.compute(_objectPointsZeroMean.getMat() * _objectPointsZeroMean.getMat().t(), W, U, VT);
1285 double s3 = W.at<
double>(2);
1286 double s2 = W.at<
double>(1);
1292 if (cv::determinant(R) < 0)
1294 R.at<
double>(2, 0) = -R.at<
double>(2, 0);
1295 R.at<
double>(2, 1) = -R.at<
double>(2, 1);
1296 R.at<
double>(2, 2) = -R.at<
double>(2, 2);