18 #ifndef CALIBRATION_UTILITIES_H_
19 #define CALIBRATION_UTILITIES_H_
27 #include <Eigen/Geometry>
29 #include <opencv2/imgcodecs.hpp>
30 #include <opencv2/imgproc.hpp>
31 #include <opencv2/opencv.hpp>
33 #include <boost/optional.hpp>
43 const std::vector<Eigen::Isometry3d>& optimized_camera_T_targets);
45 template <
typename DISTORTER>
47 const std::vector<Eigen::Vector3d>& points_3d,
const std::vector<int>& indices,
48 const Eigen::Matrix3d& intrinsics,
const Eigen::VectorXd& distortion,
50 const std::string&
name);
52 template <
typename DISTORTER>
54 const std::vector<localization_common::ImageCorrespondences>& valid_match_sets,
55 const Eigen::Matrix3d& intrinsics,
const Eigen::VectorXd& distortion,
56 const Eigen::Vector2i& image_size,
57 const double max_visualization_error_norm = 100);
59 int ErrorColor(
const double error,
const double max_error,
const double max_color_value);
63 template <
typename DISTORTER>
65 const std::vector<Eigen::Vector3d>& points_3d,
const std::vector<int>& indices,
66 const Eigen::Matrix3d& intrinsics,
const Eigen::VectorXd& distortion,
68 const std::string&
name) {
69 cv::Mat reprojection_image_grayscale(960, 1280, CV_8UC1, cv::Scalar(0));
70 std::unordered_set<int> inlier_indices(indices.begin(), indices.end());
71 for (
int i = 0; i < static_cast<int>(image_points.size()); ++i) {
72 const Eigen::Vector2d& image_point = image_points[i];
75 const Eigen::Vector2d projected_image_point =
76 vision_common::ProjectWithDistortion<DISTORTER>(camera_t_target_point, intrinsics, distortion);
77 const Eigen::Vector2d
error = (image_point - projected_image_point);
78 const double error_norm =
error.norm();
79 const cv::Point2i rounded_image_point(std::round(image_point.x()), std::round(image_point.y()));
84 constexpr
double max_color_value = 235.0;
85 const int error_color =
ErrorColor(error_norm, max_visualization_error_norm, max_color_value) + 1;
86 if (inlier_indices.count(i) > 0) {
87 cv::circle(reprojection_image_grayscale, rounded_image_point, 4, cv::Scalar(235), -1);
88 cv::circle(reprojection_image_grayscale,
89 cv::Point2i(std::round(projected_image_point.x()), std::round(projected_image_point.y())), 4,
90 cv::Scalar(error_color), -1);
92 cv::drawMarker(reprojection_image_grayscale, rounded_image_point, cv::Scalar(235), cv::MARKER_TRIANGLE_DOWN, 6,
94 cv::drawMarker(reprojection_image_grayscale,
95 cv::Point2i(std::round(projected_image_point.x()), std::round(projected_image_point.y())),
96 cv::Scalar(error_color), cv::MARKER_TRIANGLE_DOWN, 6, 2);
100 const cv::Mat reprojection_image_color =
MapImageColors(reprojection_image_grayscale);
101 cv::imwrite(
name, reprojection_image_color);
104 template <
typename DISTORTER>
106 const std::vector<localization_common::ImageCorrespondences>& valid_match_sets,
107 const Eigen::Matrix3d& intrinsics,
const Eigen::VectorXd& distortion,
108 const Eigen::Vector2i& image_size,
const double max_visualization_error_norm) {
109 double max_error_norm = 0;
111 cv::Mat absolute_reprojection_image_grayscale(image_size.y(), image_size.x(), CV_8UC1, cv::Scalar(0));
112 std::ofstream errors_file;
113 errors_file.open(
"errors_file.txt");
114 for (
int i = 0; i < static_cast<int>(valid_match_sets.size()); ++i) {
115 const auto& match_set = valid_match_sets[i];
117 for (
int j = 0; j < static_cast<int>(match_set.size()); ++j) {
118 const auto& image_point = match_set.image_points[j];
119 const auto& target_point = match_set.points_3d[j];
120 const Eigen::Vector3d camera_t_target_point = camera_T_target * target_point;
121 const Eigen::Vector2d projected_image_point =
122 vision_common::ProjectWithDistortion<DISTORTER>(camera_t_target_point, intrinsics, distortion);
123 const Eigen::Vector2d
error = (image_point - projected_image_point);
124 const double error_norm =
error.norm();
125 if (error_norm > max_error_norm) max_error_norm = error_norm;
126 errors_file <<
error.x() <<
" " <<
error.y() << std::endl;
127 const cv::Point2i rounded_image_point(std::round(image_point.x()), std::round(image_point.y()));
132 constexpr
double max_color_value = 235.0;
133 const int absolute_error_color =
ErrorColor(error_norm, max_visualization_error_norm, max_color_value) + 1;
134 cv::circle(absolute_reprojection_image_grayscale, rounded_image_point, 4, cv::Scalar(absolute_error_color), -1);
137 const cv::Mat absolute_reprojection_image_color =
MapImageColors(absolute_reprojection_image_grayscale);
138 cv::imwrite(
"calibrated_reprojection_from_all_targets_absolute_image.png", absolute_reprojection_image_color);
142 cv::Mat relative_reprojection_image_grayscale(image_size.y(), image_size.x(), CV_8UC1, cv::Scalar(0));
143 for (
int i = 0; i < static_cast<int>(valid_match_sets.size()); ++i) {
144 const auto& match_set = valid_match_sets[i];
146 for (
int j = 0; j < static_cast<int>(match_set.size()); ++j) {
147 const auto& image_point = match_set.image_points[j];
148 const auto& target_point = match_set.points_3d[j];
149 const Eigen::Vector3d camera_t_target_point = camera_T_target * target_point;
150 const Eigen::Vector2d projected_image_point =
151 vision_common::ProjectWithDistortion<DISTORTER>(camera_t_target_point, intrinsics, distortion);
152 const Eigen::Vector2d
error = (image_point - projected_image_point);
153 const double error_norm =
error.norm();
154 const cv::Point2i rounded_image_point(std::round(image_point.x()), std::round(image_point.y()));
159 constexpr
double max_color_value = 235.0;
160 const int relative_error_color =
ErrorColor(error_norm, max_error_norm, max_color_value) + 1;
161 cv::circle(relative_reprojection_image_grayscale, rounded_image_point, 4, cv::Scalar(relative_error_color), -1);
164 const cv::Mat relative_reprojection_image_color =
MapImageColors(relative_reprojection_image_grayscale);
165 cv::imwrite(
"calibrated_reprojection_from_all_targets_relative_image.png", relative_reprojection_image_color);
169 #endif // CALIBRATION_UTILITIES_H_