From 6a9aa0aba2d308f1a1fdf8ddc409811036d68a2a Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Wed, 17 Sep 2025 15:05:07 +0300 Subject: [PATCH] Added info logs with intermediate values to multiview calibration and related script option. --- modules/calib/src/multiview_calibration.cpp | 15 ++++++++++----- samples/python/multiview_calibration.py | 16 ++++++++++++++++ 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/modules/calib/src/multiview_calibration.cpp b/modules/calib/src/multiview_calibration.cpp index b862588afb..5804b10a2d 100644 --- a/modules/calib/src/multiview_calibration.cpp +++ b/modules/calib/src/multiview_calibration.cpp @@ -305,12 +305,12 @@ static void pairwiseRegistration (const std::vector> &pairs, } extrinsic_flags |= CALIB_FIX_INTRINSIC; - registerCameras(grid_points1, grid_points2, image_points1, image_points2, + double err = registerCameras(grid_points1, grid_points2, image_points1, image_points2, Ks[c1], distortions[c1], cv::CameraModel(models.at(c1)), Ks[c2], distortions[c2], cv::CameraModel(models.at(c2)), R, T, noArray(), noArray(), noArray(), noArray(), noArray(), extrinsic_flags, criteria); - + CV_LOG_INFO(NULL, "Pair " << c1 << "-" << c2 << " registration RMS " << err); // R_0 = I // R_ij = R_i R_j^T => R_i = R_ij R_j // t_ij = ti - R_ij tj => t_i = t_ij + R_ij t_j @@ -377,11 +377,12 @@ static void pairwiseStereoCalibration (const std::vector> &pa // image size does not matter since intrinsics are used if (are_fisheye_cams) { extrinsic_flags |= CALIB_FIX_INTRINSIC; - fisheye::stereoCalibrate(grid_points, image_points1, image_points2, + double err = fisheye::stereoCalibrate(grid_points, image_points1, image_points2, Ks[c1], dist1, Ks[c2], dist2, Size(), R, T, extrinsic_flags, criteria); + CV_LOG_INFO(NULL, "Stereo pair " << c1 << "-" << c2 << " registration RMS " << err); } else { extrinsic_flags |= CALIB_FIX_INTRINSIC; if ((intrinsic_flags.at(c1) & CALIB_RATIONAL_MODEL) || (intrinsic_flags.at(c2) & CALIB_RATIONAL_MODEL)) @@ -389,11 +390,12 @@ static void pairwiseStereoCalibration (const std::vector> &pa if ((intrinsic_flags.at(c1) & CALIB_THIN_PRISM_MODEL) || (intrinsic_flags.at(c2) & CALIB_THIN_PRISM_MODEL)) extrinsic_flags |= CALIB_THIN_PRISM_MODEL; - stereoCalibrate(grid_points, image_points1, image_points2, + double err = stereoCalibrate(grid_points, image_points1, image_points2, Ks[c1], dist1, Ks[c2], dist2, Size(), R, T, noArray(), noArray(), noArray(), extrinsic_flags, criteria); + CV_LOG_INFO(NULL, "Stereo pair " << c1 << "-" << c2 << " registration RMS " << err); } // R_0 = I @@ -535,7 +537,8 @@ static void optimizeLM (std::vector ¶m, const RobustFunction &robust .setStepNormTolerance(termCrit.epsilon) .setSmallEnergyTolerance(termCrit.epsilon * termCrit.epsilon), noArray()/*mask, all variables to optimize*/); - solver.optimize(); + cv::LevMarq::Report status = solver.optimize(); + CV_LOG_INFO(NULL, "LevMarq finished with status " << status.found << " energy " << status.energy << " after " << status.iters << " iterations"); } static void checkConnected (const std::vector> &detection_mask_mat) { @@ -719,6 +722,7 @@ double calibrateMultiview( if (models_mat.at(camera) == cv::CALIB_MODEL_FISHEYE) { repr_err = fisheye::calibrate(obj_points_, img_points_, imageSize[camera], K, dist, rvecs, tvecs, flagsForIntrinsics_mat.at(camera)); + CV_LOG_INFO(NULL, "Camera " << camera << " intrinsics calibration RMS " << repr_err); // calibrate does not compute error per view, so compute it manually errors_per_view = std::vector(obj_points_.size()); for (int f = 0; f < (int) obj_points_.size(); f++) { @@ -729,6 +733,7 @@ double calibrateMultiview( } else { repr_err = calibrateCamera(obj_points_, img_points_, imageSize[camera], K, dist, rvecs, tvecs, noArray(), noArray(), errors_per_view, flagsForIntrinsics_mat.at(camera)); + CV_LOG_INFO(NULL, "Camera " << camera << " intrinsics calibration RMS " << repr_err); } CV_LOG_IF_WARNING(NULL, repr_err > WARNING_RMSE, "Warning! Mean RMSE of intrinsics calibration is higher than "+std::to_string(WARNING_RMSE)+" pixels!"); int cnt_visible_frame = 0; diff --git a/samples/python/multiview_calibration.py b/samples/python/multiview_calibration.py index 20d301ff56..8849c707f5 100755 --- a/samples/python/multiview_calibration.py +++ b/samples/python/multiview_calibration.py @@ -991,6 +991,7 @@ def calibrateFromJSON(json_file, find_intrinsics_in_python): if __name__ == '__main__': parser = argparse.ArgumentParser() + parser.add_argument('--log_level', type=str, choices=('', 'verbose', 'debug', 'info', 'warning', 'error', 'fatal', 'silent'), help='OpenCV log level to print more calibration process details') parser.add_argument('--json_file', type=str, default=None, help="json file with all data. Must have keys: 'object_points', 'image_points', 'image_sizes', 'is_fisheye'") parser.add_argument('--filenames', type=str, default=None, help='Txt files containing image lists, e.g., cam_1.txt,cam_2.txt,...,cam_N.txt for N cameras') parser.add_argument('--pattern_size', type=str, default=None, help='pattern size: width,height') @@ -1013,6 +1014,21 @@ if __name__ == '__main__': params, _ = parser.parse_known_args() print("params.board_dict_path:", params.board_dict_path) + if params.log_level == "verbose": + cv.setLogLevel(6) + elif params.log_level == "debug": + cv.setLogLevel(5) + elif params.log_level == "info": + cv.setLogLevel(4) + elif params.log_level == "warning": + cv.setLogLevel(3) + elif params.log_level == "error": + cv.setLogLevel(2) + elif params.log_level == "fatal": + cv.setLogLevel(1) + elif params.log_level == "silent": + cv.setLogLevel(0) + if params.visualize: assert os.path.exists(params.path_to_visualize), f'Path to result file does not exist: {params.path_to_visualize}' visualizeFromFile(params.path_to_visualize)