diff --git a/modules/calib/include/opencv2/calib.hpp b/modules/calib/include/opencv2/calib.hpp index b47120e274..b26d9c20c7 100644 --- a/modules/calib/include/opencv2/calib.hpp +++ b/modules/calib/include/opencv2/calib.hpp @@ -1341,6 +1341,7 @@ See @ref CALIB_USE_INTRINSIC_GUESS and other `CALIB_` constants. Expected shape: @param[out] distortions Distortion coefficients. Output size: NUM_CAMERAS x NUM_PARAMS. @param[out] perFrameErrors RMSE value for each visible frame, (-1 for non-visible). Output size: NUM_CAMERAS x NUM_FRAMES. @param[out] initializationPairs Pairs with camera indices that were used for initial pairwise stereo calibration. +@param[in] criteria Termination criteria for the iterative optimization algorithm. Output size: (NUM_CAMERAS-1) x 2. @@ -1382,7 +1383,8 @@ CV_EXPORTS_AS(calibrateMultiviewExtended) double calibrateMultiview ( InputOutputArrayOfArrays Rs, InputOutputArrayOfArrays Ts, OutputArray initializationPairs, OutputArrayOfArrays rvecs0, OutputArrayOfArrays tvecs0, OutputArray perFrameErrors, - InputArray flagsForIntrinsics=noArray(), int flags = 0); + InputArray flagsForIntrinsics=noArray(), int flags = 0, + TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, DBL_EPSILON)); /// @overload CV_EXPORTS_W double calibrateMultiview ( @@ -1390,7 +1392,8 @@ CV_EXPORTS_W double calibrateMultiview ( const std::vector& imageSize, InputArray detectionMask, InputArray models, InputOutputArrayOfArrays Ks, InputOutputArrayOfArrays distortions, InputOutputArrayOfArrays Rs, InputOutputArrayOfArrays Ts, - InputArray flagsForIntrinsics=noArray(), int flags = 0); + InputArray flagsForIntrinsics=noArray(), int flags = 0, + TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, DBL_EPSILON)); /** @brief Computes Hand-Eye calibration: \f$_{}^{g}\textrm{T}_c\f$ diff --git a/modules/calib/src/multiview_calibration.cpp b/modules/calib/src/multiview_calibration.cpp index 12c8b3caf8..5d528cb4dc 100644 --- a/modules/calib/src/multiview_calibration.cpp +++ b/modules/calib/src/multiview_calibration.cpp @@ -265,7 +265,7 @@ static void pairwiseRegistration (const std::vector> &pairs, const std::vector> &imagePoints, const std::vector> &overlaps, const std::vector> &detection_mask_mat, const std::vector &Ks, const std::vector &distortions, std::vector &Rs_vec, std::vector &Ts_vec, - Mat &intrinsic_flags, int extrinsic_flags = 0) { + Mat &intrinsic_flags, int extrinsic_flags, TermCriteria criteria) { CV_UNUSED(intrinsic_flags); const int NUM_FRAMES = (int)objPoints_norm.size(); const int NUM_CAMERAS = (int)detection_mask_mat.size(); @@ -308,7 +308,8 @@ static void pairwiseRegistration (const std::vector> &pairs, 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); + R, T, noArray(), noArray(), noArray(), noArray(), noArray(), + extrinsic_flags, criteria); // R_0 = I // R_ij = R_i R_j^T => R_i = R_ij R_j @@ -328,7 +329,7 @@ static void pairwiseStereoCalibration (const std::vector> &pa const std::vector> &imagePoints, const std::vector> &overlaps, const std::vector> &detection_mask_mat, const std::vector &Ks, const std::vector &distortions, std::vector &Rs_vec, std::vector &Ts_vec, - Mat &intrinsic_flags, int extrinsic_flags = 0) { + Mat &intrinsic_flags, int extrinsic_flags, TermCriteria criteria) { const int NUM_FRAMES = (int)objPoints_norm.size(); const int NUM_CAMERAS = (int)detection_mask_mat.size(); std::vector Rs_prior; @@ -375,7 +376,8 @@ static void pairwiseStereoCalibration (const std::vector> &pa fisheye::stereoCalibrate(grid_points, image_points1, image_points2, Ks[c1], distortions[c1], Ks[c2], distortions[c2], - Size(), R, T, extrinsic_flags); + Size(), R, T, + extrinsic_flags, criteria); } else { extrinsic_flags |= CALIB_FIX_INTRINSIC; if ((intrinsic_flags.at(c1) & CALIB_RATIONAL_MODEL) || (intrinsic_flags.at(c2) & CALIB_RATIONAL_MODEL)) @@ -386,7 +388,8 @@ static void pairwiseStereoCalibration (const std::vector> &pa stereoCalibrate(grid_points, image_points1, image_points2, Ks[c1], distortions[c1], Ks[c2], distortions[c2], - Size(), R, T, noArray(), noArray(), noArray(), extrinsic_flags); + Size(), R, T, noArray(), noArray(), noArray(), + extrinsic_flags, criteria); } // R_0 = I @@ -576,7 +579,7 @@ double calibrateMultiview( InputOutputArrayOfArrays Rs, InputOutputArrayOfArrays Ts, OutputArray initializationPairs, OutputArrayOfArrays rvecs0, OutputArrayOfArrays tvecs0, OutputArray perFrameErrors, - InputArray flagsForIntrinsics, int flags) { + InputArray flagsForIntrinsics, int flags, TermCriteria criteria) { CV_CheckFalse(objPoints.empty(), "Objects points must not be empty!"); CV_CheckFalse(imagePoints.empty(), "Image points must not be empty!"); CV_CheckFalse(imageSize.empty(), "Image size per camera must not be empty!"); @@ -801,10 +804,10 @@ double calibrateMultiview( if(flags & cv::CALIB_STEREO_REGISTRATION) { multiview::pairwiseStereoCalibration(pairs, models_mat, objPoints_norm, imagePoints, - overlaps, detection_mask_mat, Ks_vec, distortions_vec, Rs_vec, Ts_vec, flagsForIntrinsics_mat); + overlaps, detection_mask_mat, Ks_vec, distortions_vec, Rs_vec, Ts_vec, flagsForIntrinsics_mat, 0, criteria); } else { multiview::pairwiseRegistration(pairs, models_mat, objPoints_norm, imagePoints, - overlaps, detection_mask_mat, Ks_vec, distortions_vec, Rs_vec, Ts_vec, flagsForIntrinsics_mat); + overlaps, detection_mask_mat, Ks_vec, distortions_vec, Rs_vec, Ts_vec, flagsForIntrinsics_mat, 0, criteria); } const int NUM_VALID_FRAMES = countNonZero(valid_frames); @@ -853,10 +856,9 @@ double calibrateMultiview( cnt_valid_frame++; } - TermCriteria termCrit (TermCriteria::COUNT+TermCriteria::EPS, 100, 1e-6); const float RBS_FNC_SCALE = 30; multiview::RobustExpFunction robust_fnc(RBS_FNC_SCALE); - multiview::optimizeLM(param, robust_fnc, termCrit, valid_frames, detection_mask_mat, objPoints_norm, + multiview::optimizeLM(param, robust_fnc, criteria, valid_frames, detection_mask_mat, objPoints_norm, imagePoints, Ks_vec, distortions_vec, models_mat, NUM_PATTERN_PTS); const auto * const params = ¶m[0]; @@ -967,10 +969,10 @@ double calibrateMultiview( const std::vector& imageSize, InputArray detectionMask, InputArray models, InputOutputArrayOfArrays Ks, InputOutputArrayOfArrays distortions, InputOutputArrayOfArrays Rs, InputOutputArrayOfArrays Ts, - InputArray flagsForIntrinsics, int flags) { + InputArray flagsForIntrinsics, int flags, TermCriteria criteria) { return calibrateMultiview(objPoints, imagePoints, imageSize, detectionMask, models, Ks, distortions, - Rs, Ts, noArray(), noArray(), noArray(), noArray(), flagsForIntrinsics, flags); + Rs, Ts, noArray(), noArray(), noArray(), noArray(), flagsForIntrinsics, flags, criteria); } diff --git a/modules/calib/test/test_multiview_calib.cpp b/modules/calib/test/test_multiview_calib.cpp index e3c5b0e367..0df18e12f1 100644 --- a/modules/calib/test/test_multiview_calib.cpp +++ b/modules/calib/test/test_multiview_calib.cpp @@ -302,7 +302,8 @@ TEST_F(MultiViewTest, OneLine) std::vector> image_points_all; cv::Mat visibility; loadImagePoints(root, cam_names, num_frames, image_points_all, visibility); - EXPECT_EQ(cam_names.size(), image_points_all.size()); + ASSERT_EQ(cam_names.size(), image_points_all.size()); + ASSERT_TRUE(!image_points_all.empty()); for(size_t i = 0; i < cam_names.size(); i++) { EXPECT_TRUE(!image_points_all[i].empty()); @@ -475,7 +476,8 @@ TEST_F(MultiViewTest, CamsToFloor) std::vector> image_points_all; cv::Mat visibility; loadImagePoints(root, cam_names, num_frames, image_points_all, visibility); - EXPECT_EQ(cam_names.size(), image_points_all.size()); + ASSERT_EQ(cam_names.size(), image_points_all.size()); + ASSERT_TRUE(!image_points_all.empty()); for(size_t i = 0; i < cam_names.size(); i++) { EXPECT_TRUE(!image_points_all[i].empty()); @@ -542,7 +544,8 @@ TEST_F(MultiViewTest, Hetero) std::vector> image_points_all; cv::Mat visibility; loadImagePoints(root, cam_names, num_frames, image_points_all, visibility); - EXPECT_EQ(cam_names.size(), image_points_all.size()); + ASSERT_EQ(cam_names.size(), image_points_all.size()); + ASSERT_TRUE(!image_points_all.empty()); for(size_t i = 0; i < cam_names.size(); i++) { EXPECT_TRUE(!image_points_all[i].empty()); @@ -613,10 +616,11 @@ TEST_F(RegisterCamerasTest, hetero1) std::vector> image_points_all; cv::Mat visibility; loadImagePoints(root, cam_names, num_frames, image_points_all, visibility); - EXPECT_EQ(cam_names.size(), image_points_all.size()); + ASSERT_EQ(cam_names.size(), image_points_all.size()); + ASSERT_TRUE(!image_points_all.empty()); for(size_t i = 0; i < cam_names.size(); i++) { - EXPECT_TRUE(!image_points_all[i].empty()); + ASSERT_TRUE(!image_points_all[i].empty()); } cv::Mat K1, dist1; @@ -670,10 +674,11 @@ TEST_F(RegisterCamerasTest, hetero2) std::vector> image_points_all; cv::Mat visibility; loadImagePoints(root, cam_names, num_frames, image_points_all, visibility); - EXPECT_EQ(cam_names.size(), image_points_all.size()); + ASSERT_EQ(cam_names.size(), image_points_all.size()); + ASSERT_TRUE(!image_points_all.empty()); for(size_t i = 0; i < cam_names.size(); i++) { - EXPECT_TRUE(!image_points_all[i].empty()); + ASSERT_TRUE(!image_points_all[i].empty()); } cv::Mat K1, dist1;