diff --git a/applications/calibration-multi/src/main.cpp b/applications/calibration-multi/src/main.cpp index ebf72ab7893b8a0af9a02e79d187d1b5530347c8..bf301728e32efc26e22667f934327b5a2affd921 100644 --- a/applications/calibration-multi/src/main.cpp +++ b/applications/calibration-multi/src/main.cpp @@ -174,8 +174,8 @@ void visualizeCalibration( MultiCameraCalibrationNew &calib, Mat &out, vector<int> markers = {cv::MARKER_SQUARE, cv::MARKER_DIAMOND}; for (size_t c = 0; c < rgb.size(); c++) { - cv::rectangle(rgb[c], roi[c], Scalar(24, 224, 24), 2); cv::remap(rgb[c], rgb[c], map1[c], map2[c], cv::INTER_CUBIC); + cv::rectangle(rgb[c], roi[c], Scalar(24, 224, 24), 2); for (int r = 50; r < rgb[c].rows; r = r+50) { cv::line(rgb[c], cv::Point(0, r), cv::Point(rgb[c].cols-1, r), cv::Scalar(0,0,255), 1); @@ -241,7 +241,8 @@ void calibrate( MultiCameraCalibrationNew &calib, vector<string> &uri_cameras, size_t pos1 = uri_cameras[c/2].find("node"); size_t pos2 = uri_cameras[c/2].find("#", pos1); node_name = uri_cameras[c/2].substr(pos1, pos2 - pos1); - + //LOG(INFO) << c << ":" << calib.getCameraMatNormalized(c, 1280, 720); + //LOG(INFO) << c + 1 << ":" << calib.getCameraMatNormalized(c + 1, 1280, 720); if (params.save_extrinsic) { saveExtrinsics(params.output_path + node_name + "-extrinsic.yml", R_c1c2, T_c1c2, R1, R2, P1, P2, Q); LOG(INFO) << "Saved: " << params.output_path + node_name + "-extrinsic.yml"; @@ -295,7 +296,7 @@ void calibrateFromPath( const string &path, cv::FileStorage fs(path + filename, cv::FileStorage::READ); fs["uri"] >> uri_cameras; - //params.idx_cameras = {6, 7}; + //params.idx_cameras = {2, 3};//{0, 1, 4, 5, 6, 7, 8, 9, 10, 11}; params.idx_cameras.resize(uri_cameras.size() * 2); std::iota(params.idx_cameras.begin(), params.idx_cameras.end(), 0); diff --git a/applications/calibration-multi/src/multicalibrate.cpp b/applications/calibration-multi/src/multicalibrate.cpp index 1840e68275c24d9b6ac4538ba71d4713148da63c..074e778ed8323fed3f7a8625288b37f62e43f612 100644 --- a/applications/calibration-multi/src/multicalibrate.cpp +++ b/applications/calibration-multi/src/multicalibrate.cpp @@ -81,16 +81,18 @@ double CalibrationTarget::estimateScale(vector<Point3d> points) { } MultiCameraCalibrationNew::MultiCameraCalibrationNew( - size_t n_cameras, size_t reference_camera, CalibrationTarget target, int fix_intrinsics) : + size_t n_cameras, size_t reference_camera, Size resolution, + CalibrationTarget target, int fix_intrinsics) : target_(target), visibility_graph_(n_cameras), is_calibrated_(false), n_cameras_(n_cameras), reference_camera_(reference_camera), - min_visible_points_(25), + min_visible_points_(50), fix_intrinsics_(fix_intrinsics == 1 ? 5 : 0), + resolution_(resolution), K_(n_cameras), dist_coeffs_(n_cameras), R_(n_cameras), @@ -116,6 +118,23 @@ Mat MultiCameraCalibrationNew::getCameraMat(size_t idx) { return K; } + +Mat MultiCameraCalibrationNew::getCameraMatNormalized(size_t idx, double scale_x, double scale_y) +{ + Mat K = getCameraMat(idx); + CHECK((scale_x != 0.0 && scale_y != 0.0) || ((scale_x == 0.0) && scale_y == 0.0)); + + scale_x = scale_x / (double) resolution_.width; + scale_y = scale_y / (double) resolution_.height; + + Mat scale(Size(3, 3), CV_64F, 0.0); + scale.at<double>(0, 0) = scale_x; + scale.at<double>(1, 1) = scale_y; + scale.at<double>(2, 2) = 1.0; + + return (scale * K); +} + Mat MultiCameraCalibrationNew::getDistCoeffs(size_t idx) { DCHECK(idx < n_cameras_); Mat D; @@ -149,6 +168,7 @@ void MultiCameraCalibrationNew::addPoints(vector<vector<Point2d>> points, vector void MultiCameraCalibrationNew::reset() { is_calibrated_ = false; + weights_ = vector(n_cameras_, vector(points2d_[0].size(), 0.0)); inlier_ = vector(n_cameras_, vector(points2d_[0].size(), 0)); points3d_ = vector(n_cameras_, vector(points2d_[0].size(), Point3d())); points3d_optimized_ = vector(points2d_[0].size(), Point3d()); @@ -163,6 +183,7 @@ void MultiCameraCalibrationNew::saveInput(const string &filename) { } void MultiCameraCalibrationNew::saveInput(cv::FileStorage &fs) { + fs << "resolution" << resolution_; fs << "K" << K_; fs << "points2d" << points2d_; fs << "visible" << visible_; @@ -182,6 +203,7 @@ void MultiCameraCalibrationNew::loadInput(const std::string &filename, const vec fs["K"] >> K; fs["points2d"] >> points2d; fs["visible"] >> visible; + fs["resolution"] >> resolution_; fs.release(); vector<size_t> cameras; @@ -287,13 +309,13 @@ void MultiCameraCalibrationNew::updatePoints3D(size_t camera, Point3d new_point, // instead store all triangulations and handle outliers // (perhaps inverse variance weighted mean?) - if (euclideanDistance(point, new_point) > 1.0) { + if (euclideanDistance(point, new_point) > 10.0) { LOG(ERROR) << "bad value (skipping) " << "(" << point << " vs " << new_point << ")"; f = -1; } else { point = (point * f + new_point) / (double) (f + 1); - f = f + 1; + f++; } } else { @@ -365,8 +387,8 @@ double MultiCameraCalibrationNew::calibratePair(size_t camera_from, size_t camer // cameras possibly lack line of sight? DCHECK(points1.size() > 8); - Mat K1 = K_[camera_from]; - Mat K2 = K_[camera_to]; + Mat &K1 = K_[camera_from]; + Mat &K2 = K_[camera_to]; vector<uchar> inliers; Mat F, E; @@ -462,12 +484,12 @@ double MultiCameraCalibrationNew::calibratePair(size_t camera_from, size_t camer // Bundle Adjustment // vector<Point3d> points3d_triangulated; // points3d_triangulated.insert(points3d_triangulated.begin(), points3d.begin(), points3d.end()); - + LOG(INFO) << K1; double err; cvsba::Sba sba; { - sba.setParams(cvsba::Sba::Params(cvsba::Sba::TYPE::MOTION, 200, 1.0e-30, fix_intrinsics_, 5, false)); - + sba.setParams(cvsba::Sba::Params(cvsba::Sba::TYPE::MOTIONSTRUCTURE, 200, 1.0e-30, 5, 5, false)); + Mat rvec1, rvec2; cv::Rodrigues(R1, rvec1); cv::Rodrigues(R2, rvec2); @@ -488,16 +510,21 @@ double MultiCameraCalibrationNew::calibratePair(size_t camera_from, size_t camer cv::Rodrigues(r[1], R2); t1 = t[0]; t2 = t[1]; - err = sba.getFinalReprjError(); + // intrinsic parameters should only be optimized at final BA + //K1 = K[0]; + //K2 = K[1]; + + err = sba.getFinalReprjError(); LOG(INFO) << "SBA reprojection error before BA " << sba.getInitialReprjError(); LOG(INFO) << "SBA reprojection error after BA " << err; } calculateTransform(R2, t2, R1, t1, rmat, tvec); - + // Store and average 3D points for both cameras (skip garbage) if (err < 10.0) { + Mat rmat1, tvec1; updatePoints3D(camera_from, points3d, idx, R1, t1); updatePoints3D(camera_to, points3d, idx, R2, t2); } @@ -507,11 +534,8 @@ double MultiCameraCalibrationNew::calibratePair(size_t camera_from, size_t camer << "), not updating points!"; } - // LOG(INFO) << "Final error: " << reprojectionError(points3d, points2, K2, rmat, tvec); - //if (reprojectionError(points3d, points2, K2, rmat, tvec) > 10.0) { - // TODO: should ignore results - // LOG(ERROR) << "pairwise calibration failed! RMS: " << reprojectionError(points3d, points2, K2, rmat, tvec); - //}; + //LOG(INFO) << reprojectionError(points3d, points1, K1, R1, t1); + //LOG(INFO) << reprojectionError(points3d, points2, K2, R2, t2); return err; } @@ -598,16 +622,26 @@ double MultiCameraCalibrationNew::calibrateAll(int reference_camera) { ); continue; } - LOG(INFO) << "Running pairwise calibration for cameras " << c1 << " and " << c2; + size_t n_visible = getVisiblePointsCount({c1, c2}); - - if (n_visible < min_visible_points_) continue; + + if (n_visible < min_visible_points_) { + LOG(INFO) << "Not enough (" << min_visible_points_ << ") points between " + << "cameras " << c1 << " and " << c2 << " (" << n_visible << " points), " + << "skipping"; + continue; + } + LOG(INFO) << "Running pairwise calibration for cameras " + << c1 << " and " << c2 << "(" << n_visible << " points)"; + if (transformations.find(make_pair(c2, c1)) != transformations.end()) { continue; } Mat R, t, R_i, t_i; - if (calibratePair(c1, c2, R, t) > 10.0) { + // TODO: threshold parameter, 16.0 possibly too high + + if (calibratePair(c1, c2, R, t) > 16.0) { LOG(ERROR) << "Pairwise calibration failed, skipping cameras " << c1 << " and " << c2; continue; diff --git a/applications/calibration-multi/src/multicalibrate.hpp b/applications/calibration-multi/src/multicalibrate.hpp index e739bc0d9b60d42b6ded37f51dc0a0fa9742e8b5..0168e107d69730e72bcd60790e550c19ca16439a 100644 --- a/applications/calibration-multi/src/multicalibrate.hpp +++ b/applications/calibration-multi/src/multicalibrate.hpp @@ -34,7 +34,8 @@ private: class MultiCameraCalibrationNew { public: MultiCameraCalibrationNew( size_t n_cameras, size_t reference_camera, - CalibrationTarget target, int fix_intrinsics=1); + Size resolution, CalibrationTarget target, + int fix_intrinsics=1); void setCameraParameters(size_t idx, const Mat &K, const Mat &distCoeffs); void setCameraParameters(size_t idx, const Mat &K); @@ -56,6 +57,8 @@ public: void saveInput(const std::string &filename); Mat getCameraMat(size_t idx); + Mat getCameraMatNormalized(size_t idx, double scale_x = 1.0, double scale_y = 1.0); + Mat getDistCoeffs(size_t idx); double calibrateAll(int reference_camera = -1); @@ -133,6 +136,7 @@ private: size_t min_visible_points_; int fix_intrinsics_; + Size resolution_; vector<Mat> K_; vector<Mat> dist_coeffs_; vector<Mat> R_; @@ -143,6 +147,7 @@ private: vector<vector<Point2d>> points2d_; vector<vector<int>> visible_; vector<vector<int>> inlier_; // "inlier" + vector<vector<double>> weights_; int fm_method_; double fm_ransac_threshold_;