From e9170935cee9408ac31782ac7d64035a2c540faa Mon Sep 17 00:00:00 2001 From: Sebastian Hahta <joseha@utu.fi> Date: Tue, 28 Jul 2020 10:08:36 +0300 Subject: [PATCH] quaternion parametrization --- .../include/ftl/calibration/optimize.hpp | 72 +++++ .../include/ftl/calibration/parameters.hpp | 66 ----- components/calibration/src/optimize.cpp | 270 +++++++++++++++--- components/calibration/src/parameters.cpp | 165 +---------- 4 files changed, 304 insertions(+), 269 deletions(-) diff --git a/components/calibration/include/ftl/calibration/optimize.hpp b/components/calibration/include/ftl/calibration/optimize.hpp index dff01ffb9..eeaf6d9de 100644 --- a/components/calibration/include/ftl/calibration/optimize.hpp +++ b/components/calibration/include/ftl/calibration/optimize.hpp @@ -24,6 +24,73 @@ static_assert(std::is_standard_layout<cv::Point3d>()); namespace ftl { namespace calibration { +/** + * Camera paramters (Ceres) + */ +struct Camera { + Camera() {} + Camera(const cv::Mat& K, const cv::Mat& D, const cv::Mat& R, const cv::Mat& tvec, cv::Size size); + Camera(const CalibrationData::Calibration& calib); + + CalibrationData::Intrinsic intrinsic() const; + CalibrationData::Extrinsic extrinsic() const; + + void setRotation(const cv::Mat& R); + void setTranslation(const cv::Mat& tvec); + void setExtrinsic(const cv::Mat& R, const cv::Mat& t) { + setRotation(R); + setTranslation(t); + } + + void setIntrinsic(const cv::Mat& K, cv::Size sz); + void setDistortion(const cv::Mat &D); + void setIntrinsic(const cv::Mat& K, const cv::Mat& D, cv::Size sz) { + setIntrinsic(K, sz); + setDistortion(D); + } + + cv::Mat intrinsicMatrix() const; + cv::Mat distortionCoefficients() const; + + cv::Mat rvec() const; + cv::Mat tvec() const; + cv::Mat rmat() const; + + cv::Mat extrinsicMatrix() const; + cv::Mat extrinsicMatrixInverse() const; + + cv::Size size; + + const static int n_parameters = 18; + const static int n_distortion_parameters = 8; + + double data[n_parameters] = {0.0}; + + enum Parameter { + ROTATION = 0, + Q1 = 0, + Q2 = 1, + Q3 = 2, + Q4 = 3, + TRANSLATION = 4, + TX = 4, + TY = 5, + TZ = 6, + F = 7, + CX = 8, + CY = 9, + DISTORTION = 10, + K1 = 10, + K2 = 11, + P1 = 12, + P2 = 13, + K3 = 14, + K4 = 15, + K5 = 16, + K6 = 17 + }; +}; + #ifdef HAVE_CERES /** Project point using camera model implemented for Ceres */ @@ -79,7 +146,12 @@ public: * @todo Radial distortion must be monotonic. This constraint is not * included in the model. */ + /// fix all distortion coefficients to constant (initial values) bool fix_distortion = true; + /// use distortion coefficients k4, k5, and k6; if false, set to zero + bool rational_model = true; + /// assume zero distortion during optimization + bool zero_distortion = false; bool optimize_intrinsic = true; bool optimize_motion = true; diff --git a/components/calibration/include/ftl/calibration/parameters.hpp b/components/calibration/include/ftl/calibration/parameters.hpp index 12ece270e..d0ed5ec4a 100644 --- a/components/calibration/include/ftl/calibration/parameters.hpp +++ b/components/calibration/include/ftl/calibration/parameters.hpp @@ -9,72 +9,6 @@ namespace ftl { namespace calibration { -/** - * Camera paramters (Ceres); TODO: move to optimize.hpp? - */ -struct Camera { - Camera() {} - Camera(const cv::Mat& K, const cv::Mat& D, const cv::Mat& R, const cv::Mat& tvec, cv::Size size); - Camera(const CalibrationData::Calibration& calib); - - CalibrationData::Intrinsic intrinsic() const; - CalibrationData::Extrinsic extrinsic() const; - - void setRotation(const cv::Mat& R); - void setTranslation(const cv::Mat& tvec); - void setExtrinsic(const cv::Mat& R, const cv::Mat& t) { - setRotation(R); - setTranslation(t); - } - - void setIntrinsic(const cv::Mat& K, cv::Size sz); - void setDistortion(const cv::Mat &D); - void setIntrinsic(const cv::Mat& K, const cv::Mat& D, cv::Size sz) { - setIntrinsic(K, sz); - setDistortion(D); - } - - cv::Mat intrinsicMatrix() const; - cv::Mat distortionCoefficients() const; - - cv::Mat rvec() const; - cv::Mat tvec() const; - cv::Mat rmat() const; - - cv::Mat extrinsicMatrix() const; - cv::Mat extrinsicMatrixInverse() const; - - cv::Size size; - - const static int n_parameters = 17; - const static int n_distortion_parameters = 8; - - double data[n_parameters] = {0.0}; - - enum Parameter { - ROTATION = 0, - RX = 0, - RY = 1, - RZ = 2, - TRANSLATION = 3, - TX = 3, - TY = 4, - TZ = 5, - F = 6, - CX = 7, - CY = 8, - DISTORTION = 9, - K1 = 9, - K2 = 10, - P1 = 11, - P2 = 12, - K3 = 13, - K4 = 14, - K5 = 15, - K6 = 16 - }; -}; - namespace validate { /** diff --git a/components/calibration/src/optimize.cpp b/components/calibration/src/optimize.cpp index e683e570f..04722774d 100644 --- a/components/calibration/src/optimize.cpp +++ b/components/calibration/src/optimize.cpp @@ -17,7 +17,8 @@ using cv::Mat; using cv::Point3d; using cv::Point2d; - +using cv::Vec3d; +using cv::Size; using cv::Rect; using ftl::calibration::BundleAdjustment; @@ -25,16 +26,172 @@ using ftl::calibration::Camera; //////////////////////////////////////////////////////////////////////////////// +void Camera::setRotation(const Mat& R) { + if (((R.size() != Size(3, 3)) && + (R.size() != Size(3, 1)) && + (R.size() != Size(1, 3))) || + (R.type() != CV_64FC1)) { + + throw ftl::exception("bad rotation matrix size/type"); + } + + Mat rvec; + if (R.size() == cv::Size(3, 3)) { cv::Rodrigues(R, rvec); } + else { rvec = R; } + + ceres::AngleAxisToQuaternion<double>((double*)(rvec.data), data + Parameter::ROTATION); +} + +void Camera::setTranslation(const Mat& t) { + if ((t.type() != CV_64FC1) || + (t.size() != cv::Size(1, 3))) { + + throw ftl::exception("bad translation vector"); + } + + data[Parameter::TX] = t.at<double>(0); + data[Parameter::TY] = t.at<double>(1); + data[Parameter::TZ] = t.at<double>(2); +} + + +void Camera::setIntrinsic(const Mat& K, cv::Size sz) { + size = sz; + if ((K.type() != CV_64FC1) || (K.size() != cv::Size(3, 3))) { + throw ftl::exception("bad intrinsic matrix"); + } + + data[Parameter::F] = K.at<double>(0, 0); + data[Parameter::CX] = K.at<double>(0, 2); + data[Parameter::CY] = K.at<double>(1, 2); +} + +void Camera::setDistortion(const Mat& D) { + if ((D.type() != CV_64FC1)) { + throw ftl::exception("distortion coefficients must be CV_64FC1"); + } + switch(D.total()) { + case 12: + /* + data[Parameter::S1] = D.at<double>(8); + data[Parameter::S2] = D.at<double>(9); + data[Parameter::S3] = D.at<double>(10); + data[Parameter::S4] = D.at<double>(11); + */ + [[fallthrough]]; + + case 8: + data[Parameter::K4] = D.at<double>(5); + data[Parameter::K5] = D.at<double>(6); + data[Parameter::K6] = D.at<double>(7); + [[fallthrough]]; + + case 5: + data[Parameter::K3] = D.at<double>(4); + [[fallthrough]]; + + default: + data[Parameter::K1] = D.at<double>(0); + data[Parameter::K2] = D.at<double>(1); + data[Parameter::P1] = D.at<double>(2); + data[Parameter::P2] = D.at<double>(3); + } +} + +Camera::Camera(const Mat &K, const Mat &D, const Mat &R, const Mat &tvec, cv::Size sz) { + setIntrinsic(K, D, sz); + if (!R.empty()) { setRotation(R); } + if (!tvec.empty()) { setTranslation(tvec); } +} + +Camera::Camera(const ftl::calibration::CalibrationData::Calibration& calib) { + setIntrinsic(calib.intrinsic.matrix(), calib.intrinsic.distCoeffs.Mat(), calib.intrinsic.resolution); + setExtrinsic(calib.extrinsic.matrix()(cv::Rect(0, 0, 3, 3)), cv::Mat(calib.extrinsic.tvec)); +} + +ftl::calibration::CalibrationData::Intrinsic Camera::intrinsic() const { + return ftl::calibration::CalibrationData::Intrinsic(intrinsicMatrix(), distortionCoefficients(), size); +} +ftl::calibration::CalibrationData::Extrinsic Camera::extrinsic() const { + return ftl::calibration::CalibrationData::Extrinsic(rvec(), tvec()); +} + +Mat Camera::intrinsicMatrix() const { + Mat K = Mat::eye(3, 3, CV_64FC1); + K.at<double>(0, 0) = data[Parameter::F]; + K.at<double>(1, 1) = data[Parameter::F]; + K.at<double>(0, 2) = data[Parameter::CX]; + K.at<double>(1, 2) = data[Parameter::CY]; + return K; +} + +Mat Camera::distortionCoefficients() const { + Mat D; + if (Camera::n_distortion_parameters <= 4) { D = Mat::zeros(1, 4, CV_64FC1); } + else if (Camera::n_distortion_parameters <= 5) { D = Mat::zeros(1, 5, CV_64FC1); } + else if (Camera::n_distortion_parameters <= 8) { D = Mat::zeros(1, 8, CV_64FC1); } + else if (Camera::n_distortion_parameters <= 12) { D = Mat::zeros(1, 12, CV_64FC1); } + else if (Camera::n_distortion_parameters <= 14) { D = Mat::zeros(1, 14, CV_64FC1); } + + switch(Camera::n_distortion_parameters) { + case 14: // not used in OpenCV? + case 12: + case 8: + D.at<double>(5) = data[Parameter::K4]; + D.at<double>(6) = data[Parameter::K5]; + D.at<double>(7) = data[Parameter::K6]; + case 5: + D.at<double>(4) = data[Parameter::K3]; + case 4: + D.at<double>(0) = data[Parameter::K1]; + D.at<double>(1) = data[Parameter::K2]; + D.at<double>(2) = data[Parameter::P1]; + D.at<double>(3) = data[Parameter::P2]; + } + + return D; +} + +Mat Camera::rvec() const { + cv::Mat rvec(cv::Size(3, 1), CV_64FC1); + ceres::QuaternionToAngleAxis(data + Parameter::ROTATION, + (double*)(rvec.data)); + return rvec; +} + +Mat Camera::tvec() const { + return Mat(Vec3d(data[Parameter::TX], data[Parameter::TY], data[Parameter::TZ])); +} + +Mat Camera::rmat() const { + Mat R; + cv::Rodrigues(rvec(), R); + return R; +} + +Mat Camera::extrinsicMatrix() const { + Mat T = Mat::eye(4, 4, CV_64FC1); + rmat().copyTo(T(Rect(0, 0, 3, 3))); + tvec().copyTo(T(Rect(3, 0, 1, 3))); + return T; +} + +Mat Camera::extrinsicMatrixInverse() const { + return transform::inverse(extrinsicMatrix()); +} + +//////////////////////////////////////////////////////////////////////////////// + struct ReprojectionError { /** * Reprojection error. * * Camera model has _CAMERA_PARAMETERS parameters: * - * - rotation and translation: rx, ry, rz, tx, ty, tx + * - rotation and translation: q1, q2, q3, q4, tx, ty, tx * - focal length: f (fx == fy assumed) * - pricipal point: cx, cy - * - distortion coefficients: k1, k2, k3, p1, p2 + * - distortion coefficients: k1, k2, k3, k4, k5, k6, p1, p2 * * Camera model documented in * https://docs.opencv.org/master/d9/d0c/group__calib3d.html @@ -49,9 +206,8 @@ struct ReprojectionError { T* residuals) const { T p[3]; + ceres::QuaternionRotatePoint(camera + Camera::Parameter::ROTATION, point, p); - // Apply rotation and translation - ceres::AngleAxisRotatePoint(camera + Camera::Parameter::ROTATION, point, p); p[0] += camera[Camera::Parameter::TX]; p[1] += camera[Camera::Parameter::TY]; @@ -123,25 +279,7 @@ cv::Point2d ftl::calibration::projectPoint(const Camera& camera, const cv::Point return out; } -struct LengthError { - explicit LengthError(const double d) : d(d) {} - - template <typename T> - bool operator()(const T* const p1, const T* const p2, T* residual) const { - auto x = p1[0] - p2[0]; - auto y = p1[1] - p2[1]; - auto z = p1[2] - p2[2]; - residual[0] = T(d) - sqrt(x*x + y*y + z*z); - - return true; - } - - static ceres::CostFunction* Create(const double d) { - return (new ceres::AutoDiffCostFunction<LengthError, 1, 3, 3>(new LengthError(d))); - } - - double d; -}; +//////////////////////////////////////////////////////////////////////////////// struct ScaleError { ScaleError(const double d, const Point3d& p) : d(d), p(p) {} @@ -287,15 +425,37 @@ void BundleAdjustment::_setCameraParametrization(ceres::Problem &problem, const vector<int> constant_camera_parameters; - // extrinsic paramters - if (!options.optimize_motion) { - for (int i = 0; i < 3; i++) { - constant_camera_parameters.push_back(Camera::Parameter::ROTATION + i); - constant_camera_parameters.push_back(Camera::Parameter::TRANSLATION + i); + // apply options + for (size_t i = 0; i < cameras_.size(); i++) { + if (!options.rational_model) { + cameras_[i]->data[Camera::Parameter::K4] = 0.0; + cameras_[i]->data[Camera::Parameter::K5] = 0.0; + cameras_[i]->data[Camera::Parameter::K6] = 0.0; } + if (options.zero_distortion) { + cameras_[i]->data[Camera::Parameter::K1] = 0.0; + cameras_[i]->data[Camera::Parameter::K2] = 0.0; + cameras_[i]->data[Camera::Parameter::K3] = 0.0; + cameras_[i]->data[Camera::Parameter::K4] = 0.0; + cameras_[i]->data[Camera::Parameter::K5] = 0.0; + cameras_[i]->data[Camera::Parameter::K6] = 0.0; + cameras_[i]->data[Camera::Parameter::P1] = 0.0; + cameras_[i]->data[Camera::Parameter::P2] = 0.0; + } + } + + // set extrinsic paramters constant for all cameras + if (!options.optimize_motion) { + constant_camera_parameters.push_back(Camera::Parameter::Q1); + constant_camera_parameters.push_back(Camera::Parameter::Q2); + constant_camera_parameters.push_back(Camera::Parameter::Q3); + constant_camera_parameters.push_back(Camera::Parameter::Q4); + constant_camera_parameters.push_back(Camera::Parameter::TX); + constant_camera_parameters.push_back(Camera::Parameter::TY); + constant_camera_parameters.push_back(Camera::Parameter::TZ); } - // intrinsic parameters + // set intrinsic parameters constant for all cameras if (!options.optimize_intrinsic || options.fix_focal) { constant_camera_parameters.push_back(Camera::Parameter::F); } @@ -329,37 +489,61 @@ void BundleAdjustment::_setCameraParametrization(ceres::Problem &problem, const options.fix_camera_extrinsic.begin(), options.fix_camera_extrinsic.end()); for (size_t i = 0; i < cameras_.size(); i++) { - std::unordered_set<int> fixed_parameters( + std::unordered_set<int> constant_parameters( constant_camera_parameters.begin(), constant_camera_parameters.end()); if (fix_extrinsic.find(i) != fix_extrinsic.end()) { - fixed_parameters.insert({ - Camera::Parameter::RX, Camera::Parameter::RY, - Camera::Parameter::RZ, Camera::Parameter::TX, - Camera::Parameter::TY, Camera::Parameter::TZ + constant_parameters.insert({ + Camera::Parameter::Q1, Camera::Parameter::Q2, + Camera::Parameter::Q3, Camera::Parameter::Q4, + Camera::Parameter::TX, Camera::Parameter::TY, + Camera::Parameter::TZ }); } if (fix_intrinsic.find(i) != fix_intrinsic.end()) { - fixed_parameters.insert({ + constant_parameters.insert({ Camera::Parameter::F, Camera::Parameter::CX, Camera::Parameter::CY }); } - vector<int> params(fixed_parameters.begin(), fixed_parameters.end()); + vector<int> params(constant_parameters.begin(), constant_parameters.end()); if (params.size() == Camera::n_parameters) { - // Ceres crashes if all parameters are set constant using + // Ceres crashes if all parameters are set constant with // SubsetParameterization() // https://github.com/ceres-solver/ceres-solver/issues/347 // https://github.com/ceres-solver/ceres-solver/commit/27183d661ecae246dbce6d03cacf84f39fba1f1e problem.SetParameterBlockConstant(getCameraPtr(i)); } else if (params.size() > 0) { - problem.SetParameterization(getCameraPtr(i), - new ceres::SubsetParameterization(Camera::n_parameters, params)); + ceres::LocalParameterization* camera_parameterization = nullptr; + + if (constant_parameters.count(Camera::Parameter::ROTATION) == 0) { + // quaternion parametrization + for (auto& v : params) { v -= 4; } + camera_parameterization = + new ceres::ProductParameterization( + new ceres::QuaternionParameterization(), + new ceres::SubsetParameterization(Camera::n_parameters - 4, params)); + } + else { + // extrinsic parameters constant + CHECK(constant_parameters.count(Camera::Parameter::Q1)); + CHECK(constant_parameters.count(Camera::Parameter::Q2)); + CHECK(constant_parameters.count(Camera::Parameter::Q3)); + CHECK(constant_parameters.count(Camera::Parameter::Q4)); + CHECK(constant_parameters.count(Camera::Parameter::TX)); + CHECK(constant_parameters.count(Camera::Parameter::TY)); + CHECK(constant_parameters.count(Camera::Parameter::TZ)); + + camera_parameterization = + new ceres::SubsetParameterization(Camera::n_parameters, params); + } + + problem.SetParameterization(getCameraPtr(i), camera_parameterization); } } } @@ -367,7 +551,7 @@ void BundleAdjustment::_setCameraParametrization(ceres::Problem &problem, const void BundleAdjustment::_buildBundleAdjustmentProblem(ceres::Problem &problem, const BundleAdjustment::Options &options) { - ceres::LossFunction *loss_function = nullptr; + ceres::LossFunction *loss_function = nullptr; // squared if (options.loss == Options::Loss::HUBER) { loss_function = new ceres::HuberLoss(1.0); @@ -390,8 +574,6 @@ void BundleAdjustment::_buildBundleAdjustmentProblem(ceres::Problem &problem, co } } - // apply options - _setCameraParametrization(problem, options); if (!options.optmize_structure) { @@ -412,7 +594,7 @@ void BundleAdjustment::run(const BundleAdjustment::Options &bundle_adjustment_op _buildProblem(problem, bundle_adjustment_options); ceres::Solver::Options options; - options.linear_solver_type = ceres::SPARSE_NORMAL_CHOLESKY; + options.linear_solver_type = ceres::DENSE_SCHUR; options.minimizer_progress_to_stdout = bundle_adjustment_options.verbose; if (bundle_adjustment_options.max_iter > 0) { diff --git a/components/calibration/src/parameters.cpp b/components/calibration/src/parameters.cpp index 2c9c2f1a3..fae57d07d 100644 --- a/components/calibration/src/parameters.cpp +++ b/components/calibration/src/parameters.cpp @@ -1,9 +1,13 @@ -#include "ftl/calibration/parameters.hpp" -#include <ftl/exception.hpp> #include <loguru.hpp> + +#include <ftl/calibration/parameters.hpp> +#include <ftl/exception.hpp> + #include <opencv2/calib3d/calib3d.hpp> +#include <ceres/rotation.h> + using cv::Mat; using cv::Size; using cv::Point2d; @@ -15,163 +19,6 @@ using std::vector; using namespace ftl::calibration; -using ftl::calibration::Camera; - -//////////////////////////////////////////////////////////////////////////////// - -void Camera::setRotation(const Mat& R) { - if (((R.size() != Size(3, 3)) && - (R.size() != Size(3, 1)) && - (R.size() != Size(1, 3))) || - (R.type() != CV_64FC1)) { - - throw ftl::exception("bad rotation matrix size/type"); - } - - Mat rvec; - if (R.size() == cv::Size(3, 3)) { cv::Rodrigues(R, rvec); } - else { rvec = R; } - - data[Parameter::RX] = rvec.at<double>(0); - data[Parameter::RY] = rvec.at<double>(1); - data[Parameter::RZ] = rvec.at<double>(2); -} - -void Camera::setTranslation(const Mat& t) { - if ((t.type() != CV_64FC1) || - (t.size() != cv::Size(1, 3))) { - - throw ftl::exception("bad translation vector"); - } - - data[Parameter::TX] = t.at<double>(0); - data[Parameter::TY] = t.at<double>(1); - data[Parameter::TZ] = t.at<double>(2); -} - - -void Camera::setIntrinsic(const Mat& K, cv::Size sz) { - size = sz; - if ((K.type() != CV_64FC1) || (K.size() != cv::Size(3, 3))) { - throw ftl::exception("bad intrinsic matrix"); - } - - data[Parameter::F] = K.at<double>(0, 0); - data[Parameter::CX] = K.at<double>(0, 2); - data[Parameter::CY] = K.at<double>(1, 2); -} - -void Camera::setDistortion(const Mat& D) { - if ((D.type() != CV_64FC1)) { - throw ftl::exception("distortion coefficients must be CV_64FC1"); - } - switch(D.total()) { - case 12: - /* - data[Parameter::S1] = D.at<double>(8); - data[Parameter::S2] = D.at<double>(9); - data[Parameter::S3] = D.at<double>(10); - data[Parameter::S4] = D.at<double>(11); - */ - [[fallthrough]]; - - case 8: - data[Parameter::K4] = D.at<double>(5); - data[Parameter::K5] = D.at<double>(6); - data[Parameter::K6] = D.at<double>(7); - [[fallthrough]]; - - case 5: - data[Parameter::K3] = D.at<double>(4); - [[fallthrough]]; - - default: - data[Parameter::K1] = D.at<double>(0); - data[Parameter::K2] = D.at<double>(1); - data[Parameter::P1] = D.at<double>(2); - data[Parameter::P2] = D.at<double>(3); - } -} - -Camera::Camera(const Mat &K, const Mat &D, const Mat &R, const Mat &tvec, cv::Size sz) { - setIntrinsic(K, D, sz); - if (!R.empty()) { setRotation(R); } - if (!tvec.empty()) { setTranslation(tvec); } -} - -Camera::Camera(const ftl::calibration::CalibrationData::Calibration& calib) { - setIntrinsic(calib.intrinsic.matrix(), calib.intrinsic.distCoeffs.Mat(), calib.intrinsic.resolution); - setExtrinsic(calib.extrinsic.matrix()(cv::Rect(0, 0, 3, 3)), cv::Mat(calib.extrinsic.tvec)); -} - -ftl::calibration::CalibrationData::Intrinsic Camera::intrinsic() const { - return ftl::calibration::CalibrationData::Intrinsic(intrinsicMatrix(), distortionCoefficients(), size); -} -ftl::calibration::CalibrationData::Extrinsic Camera::extrinsic() const { - return ftl::calibration::CalibrationData::Extrinsic(rvec(), tvec()); -} - -Mat Camera::intrinsicMatrix() const { - Mat K = Mat::eye(3, 3, CV_64FC1); - K.at<double>(0, 0) = data[Parameter::F]; - K.at<double>(1, 1) = data[Parameter::F]; - K.at<double>(0, 2) = data[Parameter::CX]; - K.at<double>(1, 2) = data[Parameter::CY]; - return K; -} - -Mat Camera::distortionCoefficients() const { - Mat D; - if (Camera::n_distortion_parameters <= 4) { D = Mat::zeros(1, 4, CV_64FC1); } - else if (Camera::n_distortion_parameters <= 5) { D = Mat::zeros(1, 5, CV_64FC1); } - else if (Camera::n_distortion_parameters <= 8) { D = Mat::zeros(1, 8, CV_64FC1); } - else if (Camera::n_distortion_parameters <= 12) { D = Mat::zeros(1, 12, CV_64FC1); } - else if (Camera::n_distortion_parameters <= 14) { D = Mat::zeros(1, 14, CV_64FC1); } - - switch(Camera::n_distortion_parameters) { - case 14: // not used in OpenCV? - case 12: - case 8: - D.at<double>(5) = data[Parameter::K4]; - D.at<double>(6) = data[Parameter::K5]; - D.at<double>(7) = data[Parameter::K6]; - case 5: - D.at<double>(4) = data[Parameter::K3]; - case 4: - D.at<double>(0) = data[Parameter::K1]; - D.at<double>(1) = data[Parameter::K2]; - D.at<double>(2) = data[Parameter::P1]; - D.at<double>(3) = data[Parameter::P2]; - } - - return D; -} - -Mat Camera::rvec() const { - return Mat(Vec3d(data[Parameter::RX], data[Parameter::RY], data[Parameter::RZ])); -} - -Mat Camera::tvec() const { - return Mat(Vec3d(data[Parameter::TX], data[Parameter::TY], data[Parameter::TZ])); -} - -Mat Camera::rmat() const { - Mat R; - cv::Rodrigues(rvec(), R); - return R; -} - -Mat Camera::extrinsicMatrix() const { - Mat T = Mat::eye(4, 4, CV_64FC1); - rmat().copyTo(T(Rect(0, 0, 3, 3))); - tvec().copyTo(T(Rect(3, 0, 1, 3))); - return T; -} - -Mat Camera::extrinsicMatrixInverse() const { - return transform::inverse(extrinsicMatrix()); -} - //////////////////////////////////////////////////////////////////////////////// bool validate::translationStereo(const Mat &t) { -- GitLab