18 #ifndef CALIBRATION_CAMERA_TARGET_BASED_INTRINSICS_CALIBRATOR_H_
19 #define CALIBRATION_CAMERA_TARGET_BASED_INTRINSICS_CALIBRATOR_H_
34 #include <Eigen/Geometry>
36 #include <ceres/ceres.h>
37 #include <ceres/solver.h>
43 template <
typename DISTORTER>
50 const std::vector<localization_common::ImageCorrespondences>& correspondences_set,
61 boost::optional<StateParametersCovariances> Covariances();
63 double RadialScaleFactor(
const Eigen::Vector2d& image_point,
const Eigen::Vector2i& image_size)
const;
64 void SaveResults(
const StateParameters& calibrated_state_parameters,
const std::vector<MatchSet>& match_sets)
const;
66 const std::vector<int>& inliers)
const;
70 ceres::Problem problem_;
72 std::vector<localization_common::ImageCorrespondences> valid_correspondences_set_;
75 template <
typename DISTORTER>
77 const std::vector<localization_common::ImageCorrespondences>& correspondences_set,
80 std::vector<MatchSet> match_sets;
81 const Eigen::Matrix3d initial_intrinsics =
83 for (
const auto& correspondences : correspondences_set) {
84 const auto camera_T_target = vision_common::ReprojectionPoseEstimate<DISTORTER>(
85 correspondences.image_points, correspondences.points_3d, initial_state_parameters.
focal_lengths,
87 params_.reprojection_pose_estimate);
89 if (!camera_T_target) {
90 LogError(
"Failed to get camera_T_target with " << correspondences.size() <<
" matches.");
94 match_sets.emplace_back(correspondences, camera_T_target->pose, camera_T_target->inliers);
95 if (params_.save_individual_initial_reprojection_images) {
96 static int image_count = 0;
97 const auto& match_set = match_sets.back();
98 SaveReprojectionImage<DISTORTER>(match_set.correspondences.image_points, match_set.correspondences.points_3d,
99 match_set.inliers, initial_intrinsics, initial_state_parameters.
distortion,
100 match_set.pose_estimate, params_.individual_max_visualization_error_norm,
101 "reprojection_image_" + std::to_string(image_count++) +
".png");
105 return Calibrate(match_sets, initial_state_parameters, calibrated_state_parameters, covariances);
108 template <
typename DISTORTER>
113 Initialize(initial_state_parameters);
116 state_parameters_.camera_T_targets.reserve(match_sets.size());
118 for (
const auto& match_set : match_sets) {
119 AddCameraTTargetParameter(match_set.pose_estimate);
121 params_.only_use_inliers ? InlierMatches(match_set.correspondences, match_set.inliers)
122 : match_set.correspondences;
123 valid_correspondences_set_.emplace_back(valid_correspondences);
124 for (
int i = 0; i < static_cast<int>(valid_correspondences.
size()) && i < params_.max_num_match_sets; ++i) {
125 const double radial_scale_factor = RadialScaleFactor(valid_correspondences.
image_points[i], params_.image_size);
128 state_parameters_.camera_T_targets.back(), state_parameters_.focal_lengths, state_parameters_.principal_points,
129 state_parameters_.distortion, problem_, radial_scale_factor, params_.optimization.huber_loss);
133 ceres::Solver::Summary summary;
134 ceres::Solve(params_.optimization.solver_options, &problem_, &summary);
135 if (params_.optimization.verbose) std::cout << summary.FullReport() << std::endl;
136 if (!summary.IsSolutionUsable()) {
137 LogError(
"Calibrate: Calibration failed.");
141 calibrated_state_parameters = state_parameters_.OptimizedStateParameters();
142 SaveResults(calibrated_state_parameters, match_sets);
144 const auto state_covariances = Covariances();
145 if (!state_covariances) {
146 LogError(
"Calibrate: Failed to get covariances");
149 covariances = *state_covariances;
154 template <
typename DISTORTER>
156 state_parameters_.SetInitialStateParameters(initial_state_parameters);
158 !params_.calibrate_focal_lengths);
160 !params_.calibrate_principal_points);
162 !params_.calibrate_distortion);
163 if (params_.optimization.verbose) {
164 if (params_.calibrate_focal_lengths)
LogInfo(
"Calibrating focal lengths.");
165 if (params_.calibrate_principal_points)
LogInfo(
"Calibrating principal points.");
166 if (params_.calibrate_distortion)
LogInfo(
"Calibrating distortion.");
167 if (params_.calibrate_target_poses)
LogInfo(
"Calibrating target poses.");
171 template <
typename DISTORTER>
172 boost::optional<StateParametersCovariances> CameraTargetBasedIntrinsicsCalibrator<DISTORTER>::Covariances() {
173 ceres::Covariance::Options options;
176 std::vector<std::pair<const double*, const double*> > covariance_blocks;
177 covariance_blocks.push_back(
178 std::make_pair(state_parameters_.focal_lengths.data(), state_parameters_.focal_lengths.data()));
179 covariance_blocks.push_back(
180 std::make_pair(state_parameters_.principal_points.data(), state_parameters_.principal_points.data()));
181 covariance_blocks.push_back(std::make_pair(state_parameters_.distortion.data(), state_parameters_.distortion.data()));
183 if (!covariance.Compute(covariance_blocks, &problem_)) {
184 LogError(
"Covariances: Failed to compute covariances.");
188 StateParametersCovariances covariances;
189 covariance.GetCovarianceBlock(state_parameters_.focal_lengths.data(), state_parameters_.focal_lengths.data(),
190 covariances.focal_lengths.data());
191 covariance.GetCovarianceBlock(state_parameters_.principal_points.data(), state_parameters_.principal_points.data(),
192 covariances.principal_points.data());
193 covariances.distortion = Eigen::MatrixXd(state_parameters_.distortion.size(), state_parameters_.distortion.size());
194 covariance.GetCovarianceBlock(state_parameters_.distortion.data(), state_parameters_.distortion.data(),
195 covariances.distortion.data());
199 template <
typename DISTORTER>
200 void CameraTargetBasedIntrinsicsCalibrator<DISTORTER>::AddCameraTTargetParameter(
202 state_parameters_.AddCameraTTarget(camera_T_target);
204 !params_.calibrate_target_poses);
206 problem_.SetParameterization(state_parameters_.camera_T_targets.back().data(), se3_local_parameterization);
209 template <
typename DISTORTER>
210 double CameraTargetBasedIntrinsicsCalibrator<DISTORTER>::RadialScaleFactor(
const Eigen::Vector2d& image_point,
211 const Eigen::Vector2i& image_size)
const {
212 if (!params_.scale_loss_radially)
return 1.0;
213 const Eigen::Vector2d centered_image_point = image_point - image_size.cast<
double>() / 2.0;
214 const double radius = centered_image_point.norm();
215 return std::pow(radius, params_.radial_scale_power);
218 template <
typename DISTORTER>
221 std::vector<Eigen::Vector2d> inlier_image_points;
222 std::vector<Eigen::Vector3d> inlier_points_3d;
223 for (
const int inlier_index : inliers) {
224 inlier_image_points.emplace_back(match_set.
image_points[inlier_index]);
225 inlier_points_3d.emplace_back(match_set.
points_3d[inlier_index]);
230 template <
typename DISTORTER>
231 void CameraTargetBasedIntrinsicsCalibrator<DISTORTER>::SaveResults(
const StateParameters& calibrated_state_parameters,
232 const std::vector<MatchSet>& match_sets)
const {
233 if (!(params_.calibrate_target_poses && params_.optimization.verbose) && !params_.save_final_reprojection_image)
236 const auto calibrated_camera_T_targets = state_parameters_.OptimizedCameraTTargets();
237 if (params_.calibrate_target_poses && params_.optimization.verbose)
240 if (params_.save_final_reprojection_image) {
242 calibrated_state_parameters.focal_lengths, calibrated_state_parameters.principal_points);
243 SaveReprojectionFromAllTargetsImage<DISTORTER>(calibrated_camera_T_targets, valid_correspondences_set_,
244 calibrated_intrinsics, calibrated_state_parameters.distortion,
245 params_.image_size, params_.max_visualization_error_norm);
250 #endif // CALIBRATION_CAMERA_TARGET_BASED_INTRINSICS_CALIBRATOR_H_