From 0be3156b36bb8051c2b9f026e3fbcbff43a3c5a3 Mon Sep 17 00:00:00 2001 From: Sebastian Hahta <joseha@utu.fi> Date: Tue, 28 Jul 2020 19:01:29 +0300 Subject: [PATCH] working rectification in calibration visualizatio --- .../src/modules/calibration/calibration.hpp | 1 + .../src/modules/calibration/extrinsic.cpp | 32 +++++++++---------- .../src/views/calibration/extrinsicview.cpp | 21 +++++++++--- .../include/ftl/calibration/optimize.hpp | 5 +-- components/calibration/src/extrinsic.cpp | 5 ++- components/calibration/src/optimize.cpp | 14 +++++--- components/calibration/src/structures.cpp | 4 +-- 7 files changed, 51 insertions(+), 31 deletions(-) diff --git a/applications/gui2/src/modules/calibration/calibration.hpp b/applications/gui2/src/modules/calibration/calibration.hpp index a30a67e4d..4986689b1 100644 --- a/applications/gui2/src/modules/calibration/calibration.hpp +++ b/applications/gui2/src/modules/calibration/calibration.hpp @@ -323,6 +323,7 @@ public: FIX_PRINCIPAL_POINT = 16, FIX_DISTORTION = 32, LOSS_CAUCHY = 64, + NONMONOTONIC_STEP = 128, }; void setFlags(int flags); diff --git a/applications/gui2/src/modules/calibration/extrinsic.cpp b/applications/gui2/src/modules/calibration/extrinsic.cpp index d7847b4a2..d9f60cc13 100644 --- a/applications/gui2/src/modules/calibration/extrinsic.cpp +++ b/applications/gui2/src/modules/calibration/extrinsic.cpp @@ -94,8 +94,15 @@ void ExtrinsicCalibration::start(unsigned int fsid, std::vector<FrameID> sources running_ = false; filter->remove(); if (fs_current_ == nullptr) { return; } + + // change mode only once per frame (cameras contain same frame twice) + std::unordered_set<uint32_t> fids; for (const auto camera : state_.cameras) { - setCalibrationMode((*fs_current_)[camera.id.source()], true); + fids.insert(camera.id.source()); + } + + for (const auto i : fids) { + setCalibrationMode((*fs_current_)[i], true); } }); state_.capture = true; @@ -272,7 +279,7 @@ void ExtrinsicCalibration::stereoRectify(int cl, int cr, CHECK(l.intrinsic.resolution == r.intrinsic.resolution); auto size = l.intrinsic.resolution; - cv::Mat T = l.extrinsic.matrix() * inverse(r.extrinsic.matrix()); + cv::Mat T = r.extrinsic.matrix() * inverse(l.extrinsic.matrix()); cv::Mat R, t, R1, R2, P1, P2, Q, map1, map2; getRotationAndTranslation(T, R, t); @@ -280,7 +287,7 @@ void ExtrinsicCalibration::stereoRectify(int cl, int cr, cv::stereoRectify( l.intrinsic.matrix(), l.intrinsic.distCoeffs.Mat(), r.intrinsic.matrix(), r.intrinsic.distCoeffs.Mat(), size, - R, t, R1, R2, P1, P2, Q, 0, 1.0); + R, t, R1, R2, P1, P2, Q, cv::CALIB_ZERO_DISPARITY, 1.0); cv::initUndistortRectifyMap(l.intrinsic.matrix(), l.intrinsic.distCoeffs.Mat(), R1, P1, size, CV_32FC1, map1, map2); @@ -288,7 +295,7 @@ void ExtrinsicCalibration::stereoRectify(int cl, int cr, state_.maps2[cl].upload(map2); cv::initUndistortRectifyMap(r.intrinsic.matrix(), r.intrinsic.distCoeffs.Mat(), - R1, P1, size, CV_32FC1, map1, map2); + R2, P2, size, CV_32FC1, map1, map2); state_.maps1[cr].upload(map1); state_.maps2[cr].upload(map2); } @@ -298,14 +305,6 @@ void ExtrinsicCalibration::run() { future_ = ftl::pool.push([this](int id) { try { - for (int c = 0; c < cameraCount(); c += 2) { - auto t1 = state_.calib.calibration(c).extrinsic.tvec; - auto t2 = state_.calib.calibration(c + 1).extrinsic.tvec; - - LOG(INFO) << "baseline (" << c << ", " << c + 1 << "): " - << cv::norm(t1, t2); - } - auto opt = state_.calib.options(); opt.optimize_intrinsic = !(state_.flags & Flags::FIX_INTRINSIC); opt.rational_model = state_.flags & Flags::RATIONAL_MODEL; @@ -316,15 +315,11 @@ void ExtrinsicCalibration::run() { opt.loss = (state_.flags & Flags::LOSS_CAUCHY) ? ftl::calibration::BundleAdjustment::Options::Loss::CAUCHY : ftl::calibration::BundleAdjustment::Options::Loss::SQUARED; + opt.use_nonmonotonic_steps = state_.flags & Flags::NONMONOTONIC_STEP; state_.calib.setOptions(opt); state_.calib.run(); - for (int c = 0; c < cameraCount(); c += 2) { - auto t1 = state_.calib.calibrationOptimized(c).extrinsic.tvec; - auto t2 = state_.calib.calibrationOptimized(c + 1).extrinsic.tvec; - } - // Rectification maps for visualization; stereo cameras assumed // if non-stereo cameras added visualization/grouping (by index) // has to be different. @@ -336,6 +331,9 @@ void ExtrinsicCalibration::run() { auto l = state_.calib.calibrationOptimized(c); auto r = state_.calib.calibrationOptimized(c + 1); stereoRectify(c, c + 1, l, r); + + LOG(INFO) << "baseline (" << c << ", " << c + 1 << "): " + << cv::norm(l.extrinsic.tvec, r.extrinsic.tvec); } } catch (ftl::exception &ex) { diff --git a/applications/gui2/src/views/calibration/extrinsicview.cpp b/applications/gui2/src/views/calibration/extrinsicview.cpp index 91b3b946d..00a3713a7 100644 --- a/applications/gui2/src/views/calibration/extrinsicview.cpp +++ b/applications/gui2/src/views/calibration/extrinsicview.cpp @@ -303,9 +303,19 @@ void ExtrinsicCalibrationView::CalibrationWindow::build() { else { flags &= ~ExtrinsicCalibration::Flags::LOSS_CAUCHY; } }); + auto* nstep = new nanogui::CheckBox(wfreeze, "Non-monotonic step"); + nstep->setChecked(flags_ & ExtrinsicCalibration::Flags::NONMONOTONIC_STEP); + nstep->setCallback([&flags = flags_](bool v) { + if (v) { flags |= ExtrinsicCalibration::Flags::NONMONOTONIC_STEP; } + else { flags &= ~ExtrinsicCalibration::Flags::NONMONOTONIC_STEP; } + }); + auto* fall = new nanogui::CheckBox(wfreeze, "Freeze all intrinsic paramters"); fall->setChecked(flags_ & ExtrinsicCalibration::Flags::FIX_INTRINSIC); - fall->setCallback([&flags = flags_](bool v) { + fall->setCallback([&flags = flags_, wfreeze](bool v) { + for (int i = 3; i < wfreeze->childCount(); i++) { + wfreeze->childAt(i)->setEnabled(!v); + } if (v) { flags |= ExtrinsicCalibration::Flags::FIX_INTRINSIC; } else { flags &= ~ExtrinsicCalibration::Flags::FIX_INTRINSIC; } }); @@ -338,10 +348,11 @@ void ExtrinsicCalibrationView::CalibrationWindow::build() { else { flags &= ~ExtrinsicCalibration::Flags::ZERO_DISTORTION; } }); - fall->setCallback([wfreeze](bool value){ - for (int i = 2; i < wfreeze->childCount(); i++) { - wfreeze->childAt(i)->setEnabled(!value); - } + auto* rdist = new nanogui::CheckBox(wfreeze, "Rational distortion model"); + rdist->setChecked(flags_ & ExtrinsicCalibration::Flags::RATIONAL_MODEL); + rdist->setCallback([&flags = flags_](bool v) { + if (v) { flags |= ExtrinsicCalibration::Flags::RATIONAL_MODEL; } + else { flags &= ~ExtrinsicCalibration::Flags::RATIONAL_MODEL; } }); /* Needs thinking: visualize visibility graph? Use earlier alignment (if diff --git a/components/calibration/include/ftl/calibration/optimize.hpp b/components/calibration/include/ftl/calibration/optimize.hpp index eeaf6d9de..17dd1b42c 100644 --- a/components/calibration/include/ftl/calibration/optimize.hpp +++ b/components/calibration/include/ftl/calibration/optimize.hpp @@ -129,6 +129,8 @@ public: Loss loss = Loss::SQUARED; + bool use_nonmonotonic_steps = false; + // fix_camera_extrinsic and fix_camera_intrinsic overlap with some of // the generic options. The more generic setting is always used, the // specific extrinsic/intrinsic options are applied on top of those. @@ -150,7 +152,7 @@ public: 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 + /// distortion set to zero bool zero_distortion = false; bool optimize_intrinsic = true; @@ -217,7 +219,6 @@ protected: void _buildProblem(ceres::Problem& problem, const BundleAdjustment::Options& options); void _buildBundleAdjustmentProblem(ceres::Problem& problem, const BundleAdjustment::Options& options); - void _buildLengthProblem(ceres::Problem& problem, const BundleAdjustment::Options& options); private: // point to be optimized and corresponding observations diff --git a/components/calibration/src/extrinsic.cpp b/components/calibration/src/extrinsic.cpp index 615b13034..4e59a5466 100644 --- a/components/calibration/src/extrinsic.cpp +++ b/components/calibration/src/extrinsic.cpp @@ -613,7 +613,7 @@ double ExtrinsicCalibration::optimize() { p = {px[m], py[m], pz[m]}; } - // TODO: desgin more meaningful check + // TODO: desgin better check if (cv::norm(absdiff(px, py, pz)) > threshold_bad_) { n_points_bad++; continue; @@ -641,6 +641,8 @@ double ExtrinsicCalibration::optimize() { updateStatus_("Bundle adjustment"); options_.verbose = true; + options_.max_iter = 250; // should converge much earlier + LOG(INFO) << "fix intrinsics: " << (options_.optimize_intrinsic ? "no" : "yes"); LOG(INFO) << "fix focal: " << (options_.fix_focal ? "yes" : "no"); LOG(INFO) << "fix principal point: " << (options_.fix_principal_point ? "yes" : "no"); @@ -661,6 +663,7 @@ double ExtrinsicCalibration::optimize() { } rmse_total_ = ba.reprojectionError(); + LOG(INFO) << "reprojection error (all cameras): " << rmse_total_; return rmse_total_; } diff --git a/components/calibration/src/optimize.cpp b/components/calibration/src/optimize.cpp index 04722774d..76db14c07 100644 --- a/components/calibration/src/optimize.cpp +++ b/components/calibration/src/optimize.cpp @@ -154,6 +154,7 @@ Mat Camera::distortionCoefficients() const { Mat Camera::rvec() const { cv::Mat rvec(cv::Size(3, 1), CV_64FC1); + CHECK(rvec.step1() == 3); ceres::QuaternionToAngleAxis(data + Parameter::ROTATION, (double*)(rvec.data)); return rvec; @@ -164,8 +165,11 @@ Mat Camera::tvec() const { } Mat Camera::rmat() const { - Mat R; - cv::Rodrigues(rvec(), R); + cv::Mat R(cv::Size(3, 3), CV_64FC1); + CHECK(R.step1() == 3); + ceres::QuaternionToRotation<double>(data + Parameter::ROTATION, + ceres::RowMajorAdapter3x3<double>((double*)(R.data))); + return R; } @@ -213,8 +217,8 @@ struct ReprojectionError { p[1] += camera[Camera::Parameter::TY]; p[2] += camera[Camera::Parameter::TZ]; - T x = T(p[0]) / p[2]; - T y = T(p[1]) / p[2]; + T x = p[0] / p[2]; + T y = p[1] / p[2]; // Intrinsic parameters const T& f = camera[Camera::Parameter::F]; @@ -605,6 +609,8 @@ void BundleAdjustment::run(const BundleAdjustment::Options &bundle_adjustment_op options.num_threads = bundle_adjustment_options.num_threads; } + options.use_nonmonotonic_steps = bundle_adjustment_options.use_nonmonotonic_steps; + ceres::Solver::Summary summary; ceres::Solve(options, &problem, &summary); diff --git a/components/calibration/src/structures.cpp b/components/calibration/src/structures.cpp index 2c44a6b02..c464e80b9 100644 --- a/components/calibration/src/structures.cpp +++ b/components/calibration/src/structures.cpp @@ -146,7 +146,7 @@ CalibrationData::Extrinsic::Extrinsic(cv::InputArray R, cv::InputArray t) { } cv::Mat CalibrationData::Extrinsic::matrix() const { - cv::Mat T(cv::Size(4, 4), CV_64FC1, cv::Scalar(0)); + cv::Mat T(cv::Size(4, 4), CV_64FC1, cv::Scalar(0.0)); cv::Rodrigues(rvec, T(cv::Rect(0, 0, 3, 3))); T.at<double>(0, 3) = tvec[0]; T.at<double>(1, 3) = tvec[1]; @@ -160,7 +160,7 @@ cv::Mat CalibrationData::Extrinsic::matrix() const { } cv::Mat CalibrationData::Extrinsic::rmat() const { - cv::Mat R(cv::Size(3, 3), CV_64FC1, cv::Scalar(0)); + cv::Mat R(cv::Size(3, 3), CV_64FC1, cv::Scalar(0.0)); cv::Rodrigues(rvec, R); return R; } -- GitLab