licornea_tools
checkerboard_depth_stat.cc
Go to the documentation of this file.
1 #include "../lib/common.h"
2 #include "../lib/args.h"
3 #include "../lib/opencv.h"
4 #include "../lib/intrinsics.h"
5 #include "../lib/misc.h"
6 #include "../lib/obj_img_correspondence.h"
8 #include <string>
9 #include <cassert>
10 #include <fstream>
11 #include <iostream>
12 
13 using namespace tlz;
14 
15 
16 int main(int argc, const char* argv[]) {
17  get_args(argc, argv, "chk_samples.json cols rows square_width ir_intr.json out_stat.txt");
18  std::string chk_samples_filename = in_filename_arg();
19  int cols = int_arg();
20  int rows = int_arg();
22  intrinsics ir_intr = intrinsics_arg();
23  std::string out_stat_filename = out_filename_arg();
24 
25  struct checkerboard_sample {
26  std::vector<vec2> corners;
27  std::vector<checkerboard_pixel_depth_sample> pixel_samples;
28  };
29  std::vector<checkerboard_sample> chk_samples;
30 
31  std::cout << "loading checkerboard samples" << std::endl;
32  {
33  json j_chk_samples = import_json_file(chk_samples_filename);
34  for(const auto& j_chk_sample : j_chk_samples) {
35  checkerboard_sample chk_samp;
36 
37  const json& j_corners = j_chk_sample["corners"];
38  if(j_corners.size() != cols*rows) throw std::runtime_error("wrong checkerboard sample corner count");
39  for(const auto& j_corner : j_corners) {
40  chk_samp.corners.emplace_back(j_corner["x"], j_corner["y"]);
41  }
42  const json& j_pixels = j_chk_sample["pixels"];
43  for(const auto& j_pixel : j_pixels) {
45  pix.coordinates = vec2(j_pixel["x"], j_pixel["y"]);
46  pix.measured_depth = j_pixel["d"];
47  chk_samp.pixel_samples.push_back(pix);
48  }
49 
50  chk_samples.push_back(chk_samp);
51  }
52  }
53 
54 
55  struct point_sample {
56  real x;
57  real y;
58  real measured_depth;
59  real calculated_depth;
60 
61  real chk_reprojection_error;
62 
63  real dist_x;
64  real dist_y;
65 
66  vec3 chk_rotation;
67  vec3 chk_translation;
68  };
69  std::vector<point_sample> point_samples;
70 
71 
72  std::vector<vec2> all_distorted_coordinates;
73  std::vector<vec2> all_undistorted_coordinates;
74 
75 
76  std::cout << "processing checkerboards (calculate projected distances, reprojection errors)" << std::endl;
77  std::vector<vec3> object_points = checkerboard_world_corners(cols, rows, square_width);
78  for(checkerboard_sample& chk_samp : chk_samples) {
79  checkerboard ir_chk(cols, rows, square_width, chk_samp.corners);
80 
82  calculate_checkerboard_pixel_depths(ir_intr, ext, chk_samp.pixel_samples);
83  real reprojection_error = checkerboard_reprojection_error(ir_chk, ir_intr, ext);
84 
85  // store point samples for corners
86  for(const auto& pix : chk_samp.pixel_samples) {
87  point_sample s;
88  s.dist_x = pix.coordinates[0];
89  s.dist_y = pix.coordinates[1];
90  s.measured_depth = pix.measured_depth;
91  s.calculated_depth = pix.calculated_depth;
92  s.chk_reprojection_error = reprojection_error;
93  s.chk_rotation = ext.rotation_vec;
94  s.chk_translation = ext.translation;
95  point_samples.push_back(s);
96 
97  all_distorted_coordinates.push_back(pix.coordinates);
98  }
99  }
100 
101 
102  std::cout << "calculating undistorted points" << std::endl;
103  all_undistorted_coordinates.reserve(all_distorted_coordinates.size());
104  cv::undistortPoints(
105  all_distorted_coordinates,
106  all_undistorted_coordinates,
107  ir_intr.K,
108  ir_intr.distortion.cv_coeffs(),
109  cv::noArray(),
110  ir_intr.K
111  );
112  auto samp_it = point_samples.begin();
113  for(const vec2& undist : all_undistorted_coordinates) {
114  point_sample& s = *(samp_it++);
115  s.x = undist[0];
116  s.y = undist[1];
117  }
118 
119 
120  std::cout << "saving collected pixel depth samples" << std::endl;
121  {
122  std::ofstream stream(out_stat_filename);
123  stream << "x y measured calculated difference chk_reprojection_err dist_x dist_y chk_rot_x chk_rot_y chk_rot_z chk_t_x chk_t_y chk_t_z\n";
124  stream << std::setprecision(10);
125  for(const point_sample& samp : point_samples)
126  stream
127  << samp.x << " "
128  << samp.y << " "
129  << samp.measured_depth << " "
130  << samp.calculated_depth << " "
131  << samp.measured_depth-samp.calculated_depth << " "
132  << samp.chk_reprojection_error << " "
133  << samp.dist_x << " "
134  << samp.dist_y << " "
135  << samp.chk_rotation[0] << " "
136  << samp.chk_rotation[1] << " "
137  << samp.chk_rotation[2] << " "
138  << samp.chk_translation[0] << " "
139  << samp.chk_translation[1] << " "
140  << samp.chk_translation[2] << "\n";
141  }
142 
143  std::cout << "done" << std::endl;
144 }
145 
146 
147 
148 
149 
150 
151 
152  /*
153  *
154  * conv from old format:
155  *
156  *
157  *
158 
159 
160 
161  std::ifstream old_stream(argv[1]);
162  std::ofstream new_stream(argv[2]);
163  intrinsics ir_intr = decode_intrinsics(import_json_file(argv[3]));
164 
165  std::string line;
166  std::getline(old_stream, line);
167  using sample = std::array<real, 12>;
168  std::vector<vec2> all_distorted_coordinates;
169  std::vector<sample> samples;
170 
171  while(! old_stream.eof()) {
172  sample s;
173  for(int i = 0; i < 12; ++i) old_stream >> s[i];
174  all_distorted_coordinates.emplace_back(s[0], s[1]);
175  samples.push_back(s);
176  }
177 
178  std::vector<vec2> all_undistorted_coordinates;
179  all_undistorted_coordinates.reserve(all_distorted_coordinates.size());
180  cv::undistortPoints(
181  all_distorted_coordinates,
182  all_undistorted_coordinates,
183  ir_intr.K,
184  ir_intr.distortion.cv_coeffs(),
185  cv::noArray(),
186  ir_intr.K
187  );
188 
189  std::ptrdiff_t idx = 0;
190  new_stream << "x y measured calculated difference chk_reprojection_err dist_x dist_y chk_rot_x chk_rot_y chk_rot_z chk_t_x chk_t_y chk_t_z\n";
191  for(const sample& s : samples) {
192  new_stream
193  << all_undistorted_coordinates[idx][0] << " "
194  << all_undistorted_coordinates[idx][1] << " "
195  << s[2] << " "
196  << s[3] << " "
197  << s[4] << " "
198  << s[5] << " "
199  << s[0] << " "
200  << s[1] << " "
201  << s[6] << " "
202  << s[7] << " "
203  << s[8] << " "
204  << s[9] << " "
205  << s[10] << " "
206  << s[11] << "\n";
207  ++idx;
208  }
209 
210 
211  return 0;
212  */
void calculate_checkerboard_pixel_depths(const intrinsics &intr, const checkerboard_extrinsics &ext, std::vector< checkerboard_pixel_depth_sample > &inout_samples)
std::string in_filename_arg()
Definition: args.cc:98
int rows
int main(int argc, const char *argv[])
checkerboard_extrinsics estimate_checkerboard_extrinsics(const checkerboard &chk, const intrinsics &intr)
cv::Vec< real, 2 > vec2
Definition: common.h:22
intrinsics intrinsics_arg()
Definition: intrinsics.cc:119
distortion_parameters distortion
Definition: intrinsics.h:30
double real
Definition: common.h:16
long int_arg()
Definition: args.cc:138
cv::Vec< real, 3 > vec3
Definition: common.h:23
double real_arg()
Definition: args.cc:146
real square_width
std::vector< vec3 > checkerboard_world_corners(int cols, int rows, real square_width)
int cols
std::string out_filename_arg()
Definition: args.cc:104
std::vector< real > cv_coeffs() const
Definition: intrinsics.h:17
real checkerboard_reprojection_error(const checkerboard &chk, const intrinsics &intr, const checkerboard_extrinsics &ext)
nlohmann::json json
Definition: json.h:11
json import_json_file(const std::string &filename)
Definition: json.cc:24
void get_args(int argc, const char *argv[], const std::string &usage)
Definition: args.cc:49