NASA Astrobee Robot Software  0.19.1
Flight software for the Astrobee robots operating inside the International Space Station.
utilities.h
Go to the documentation of this file.
1 /* Copyright (c) 2017, United States Government, as represented by the
2  * Administrator of the National Aeronautics and Space Administration.
3  *
4  * All rights reserved.
5  *
6  * The Astrobee platform is licensed under the Apache License, Version 2.0
7  * (the "License"); you may not use this file except in compliance with the
8  * License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15  * License for the specific language governing permissions and limitations
16  * under the License.
17  */
18 #ifndef CALIBRATION_UTILITIES_H_
19 #define CALIBRATION_UTILITIES_H_
20 
21 #include <calibration/match_set.h>
26 
27 #include <Eigen/Geometry>
28 
29 #include <opencv2/imgcodecs.hpp>
30 #include <opencv2/imgproc.hpp>
31 #include <opencv2/opencv.hpp>
32 
33 #include <boost/optional.hpp>
34 
35 #include <algorithm>
36 #include <fstream>
37 #include <iostream>
38 #include <string>
39 #include <vector>
40 
41 namespace calibration {
42 void PrintCameraTTargetsStats(const std::vector<MatchSet>& match_sets,
43  const std::vector<Eigen::Isometry3d>& optimized_camera_T_targets);
44 
45 template <typename DISTORTER>
46 void SaveReprojectionImage(const std::vector<Eigen::Vector2d>& image_points,
47  const std::vector<Eigen::Vector3d>& points_3d, const std::vector<int>& indices,
48  const Eigen::Matrix3d& intrinsics, const Eigen::VectorXd& distortion,
49  const Eigen::Isometry3d& pose, const double max_visualization_error_norm,
50  const std::string& name);
51 
52 template <typename DISTORTER>
53 void SaveReprojectionFromAllTargetsImage(const std::vector<Eigen::Isometry3d>& camera_T_targets,
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);
58 
59 int ErrorColor(const double error, const double max_error, const double max_color_value);
60 
61 cv::Mat MapImageColors(const cv::Mat& gray_image);
62 
63 template <typename DISTORTER>
64 void SaveReprojectionImage(const std::vector<Eigen::Vector2d>& image_points,
65  const std::vector<Eigen::Vector3d>& points_3d, const std::vector<int>& indices,
66  const Eigen::Matrix3d& intrinsics, const Eigen::VectorXd& distortion,
67  const Eigen::Isometry3d& pose, const double max_visualization_error_norm,
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];
73  const Eigen::Vector3d& point_3d = points_3d[i];
74  const Eigen::Vector3d camera_t_target_point = pose * point_3d;
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()));
80  // Add 1 to each value so background pixels stay white and we can map these back to white
81  // after applying colormap.
82  // Only map up to 235 since darker reds that occur from 235-255 are hard to differentiate from
83  // darker blues from 0 to 20 or so.
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);
91  } else { // Draw outlier with a triangle
92  cv::drawMarker(reprojection_image_grayscale, rounded_image_point, cv::Scalar(235), cv::MARKER_TRIANGLE_DOWN, 6,
93  2);
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);
97  }
98  }
99 
100  const cv::Mat reprojection_image_color = MapImageColors(reprojection_image_grayscale);
101  cv::imwrite(name, reprojection_image_color);
102 }
103 
104 template <typename DISTORTER>
105 void SaveReprojectionFromAllTargetsImage(const std::vector<Eigen::Isometry3d>& camera_T_targets,
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;
110  // Absolute Image
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];
116  const Eigen::Isometry3d camera_T_target = camera_T_targets[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()));
128  // Add 1 to each value so background pixels stay white and we can map these back to white
129  // after applying colormap.
130  // Only map up to 235 since darker reds that occur from 235-255 are hard to differentiate from
131  // darker blues from 0 to 20 or so.
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);
135  }
136  }
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);
139  errors_file.close();
140 
141  // Relative Image
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];
145  const Eigen::Isometry3d camera_T_target = camera_T_targets[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()));
155  // Add 1 to each value so background pixels stay white and we can map these back to white
156  // after applying colormap.
157  // Only map up to 235 since darker reds that occur from 235-255 are hard to differentiate from
158  // darker blues from 0 to 20 or so.
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);
162  }
163  }
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);
166 }
167 } // namespace calibration
168 
169 #endif // CALIBRATION_UTILITIES_H_
vision_common::Isometry3d
Eigen::Isometry3d Isometry3d(const cv::Mat &rodrigues_rotation_cv, const cv::Mat &translation_cv)
Definition: utilities.cc:58
pose_estimation.h
name
std::string name
Definition: eps_simulator.cc:48
point_cloud_common::Vector3d
Eigen::Vector3d Vector3d(const PointType &point)
Definition: utilities.h:328
calibration::ErrorColor
int ErrorColor(const double error, const double max_error, const double max_color_value)
Definition: utilities.cc:49
calibration::MapImageColors
cv::Mat MapImageColors(const cv::Mat &gray_image)
Definition: utilities.cc:53
utilities.h
calibration::SaveReprojectionFromAllTargetsImage
void SaveReprojectionFromAllTargetsImage(const std::vector< Eigen::Isometry3d > &camera_T_targets, const std::vector< localization_common::ImageCorrespondences > &valid_match_sets, const Eigen::Matrix3d &intrinsics, const Eigen::VectorXd &distortion, const Eigen::Vector2i &image_size, const double max_visualization_error_norm=100)
Definition: utilities.h:105
eigen_vectors.h
calibration::SaveReprojectionImage
void SaveReprojectionImage(const std::vector< Eigen::Vector2d > &image_points, const std::vector< Eigen::Vector3d > &points_3d, const std::vector< int > &indices, const Eigen::Matrix3d &intrinsics, const Eigen::VectorXd &distortion, const Eigen::Isometry3d &pose, const double max_visualization_error_norm, const std::string &name)
Definition: utilities.h:64
error
uint8_t error
Definition: signal_lights.h:89
calibration
Definition: camera_target_based_intrinsics_calibrator.h:42
image_correspondences.h
match_set.h
calibration::PrintCameraTTargetsStats
void PrintCameraTTargetsStats(const std::vector< MatchSet > &match_sets, const std::vector< Eigen::Isometry3d > &optimized_camera_T_targets)
Definition: utilities.cc:30