licornea_tools
cg_stitch_cameras.cc
Go to the documentation of this file.
1 #include "../lib/common.h"
2 #include "../lib/args.h"
3 #include "../lib/json.h"
4 #include "../lib/camera.h"
5 #include "../lib/dataset.h"
6 #include "../lib/intrinsics.h"
7 #include "../lib/misc.h"
8 #include "../lib/assert.h"
11 #include <map>
12 #include <iostream>
13 #include <vector>
14 #include <cmath>
15 #include <utility>
16 #include <set>
17 #include <fstream>
18 
19 using namespace tlz;
20 
21 const bool verbose = false;
22 
23 
24 int main(int argc, const char* argv[]) {
25  get_args(argc, argv, "dataset_parameters.json refgrid.json rcpos.json intr.json R.json out_cameras.json [out_camera_centers.txt]");
26  dataset datas = dataset_arg();
29  intrinsics intr = intrinsics_arg();
30  mat33 R = decode_mat(json_arg());
31  std::string out_cameras_filename = out_filename_arg();
32  std::string out_camera_centers_filename = out_filename_opt_arg();
33 
34  Assert(intr.distortion.is_none(), "input cors + intrinsics must be without distortion");
35 
36  auto reference_target_camera_positions = rcpos.to_reference_target_positions();
37  auto all_target_vws = get_target_views(rcpos);
38 
39  std::cout << "computing relative positions of reference views" << std::endl;
40  auto reference_camera_displacement = [&](view_index ref_a, view_index ref_b) {
41  vec2 displacements_sum = 0.0;
42  real displacements_weights_sum = 0.0;
43  std::map<view_index, vec2> ref_a_target_camera_positions;
44 
45  if(reference_target_camera_positions.find(ref_a) != reference_target_camera_positions.end())
46  for(const auto& p : reference_target_camera_positions.at(ref_a)) {
47  const view_index& target = p.first;
48  const vec2& camera_position = p.second;
49  ref_a_target_camera_positions[target] = camera_position;
50  }
51 
52  if(reference_target_camera_positions.find(ref_b) != reference_target_camera_positions.end())
53  for(const auto& p : reference_target_camera_positions.at(ref_b)) {
54  const view_index& target = p.first;
55  auto ref_a_pos_it = ref_a_target_camera_positions.find(target);
56  if(ref_a_pos_it != ref_a_target_camera_positions.end()) {
57  vec2 ref_a_pos = ref_a_pos_it->second;
58  vec2 ref_b_pos = p.second;
59 
60  displacements_sum += (ref_a_pos - ref_b_pos);
61  displacements_weights_sum += 1.0;
62  }
63  }
64 
65  if(displacements_weights_sum == 0.0)
66  throw std::runtime_error("could not compute displacement from ref " + encode_view_index(ref_a) + " to ref " + encode_view_index(ref_b));
67 
68  return displacements_sum / displacements_weights_sum;
69  };
70 
71 
72  std::map<view_index, vec2> absolute_reference_camera_positions;
73  auto add_reference_camera_position = [&](const view_index& ref_a, const view_index& ref_b) {
74  std::cout << " stitching position of reference view " << ref_b << " onto " << ref_a << std::endl;
75  vec2 displacement = reference_camera_displacement(ref_a, ref_b);
76  std::cout << " ref" << ref_b << " = " << displacement << " + ref" << ref_a << std::endl;
77  absolute_reference_camera_positions[ref_b] = absolute_reference_camera_positions.at(ref_a) + displacement;
78  };
79 
80  int mid_col = rgrid.cols() / 2, mid_row = rgrid.rows()/2;
81  absolute_reference_camera_positions[rgrid.view(mid_col, mid_row)] = vec2(0.0, 0.0);
82  for(int col = mid_col-1; col >= 0; col--) {
83  add_reference_camera_position(rgrid.view(col+1, mid_row), rgrid.view(col, mid_row));
84  for(int row = mid_row-1; row >= 0; row--) add_reference_camera_position(rgrid.view(col, row+1), rgrid.view(col, row));
85  for(int row = mid_row+1; row < rgrid.rows(); row++) add_reference_camera_position(rgrid.view(col, row-1), rgrid.view(col, row));
86  }
87  for(int col = mid_col+1; col < rgrid.cols(); col++) {
88  add_reference_camera_position(rgrid.view(col-1, mid_row), rgrid.view(col, mid_row));
89  for(int row = mid_row-1; row >= 0; row--) add_reference_camera_position(rgrid.view(col, row+1), rgrid.view(col, row));
90  for(int row = mid_row+1; row < rgrid.rows(); row++) add_reference_camera_position(rgrid.view(col, row-1), rgrid.view(col, row));
91  }
92 
93 
94  std::ofstream out_camera_centers_stream;
95  if(! out_camera_centers_filename.empty()) {
96  out_camera_centers_stream.open(out_camera_centers_filename);
97  out_camera_centers_stream << "x y idx_x idx_y chosen\n";
98  out_camera_centers_stream << std::setprecision(10);
99  }
100 
101  std::map<view_index, vec2> absolute_target_camera_positions;
102  if(absolute_reference_camera_positions.size() == 1) {
103  for(const auto& p : reference_target_camera_positions.begin()->second) {
104  const view_index& target_idx = p.first;
105  const vec2& pos = p.second;
106  absolute_target_camera_positions[p.first] = pos;
107  if(out_camera_centers_stream.is_open())
108  out_camera_centers_stream << pos[0] << ' ' << pos[1] << ' ' << target_idx.x << ' ' << target_idx.y << " 1\n";
109  }
110 
111  } else {
112  reference_target_camera_positions.clear();
113  auto target_reference_camera_positions = rcpos.to_target_reference_positions();
114 
115  std::vector<real> overlap_radii;
116 
117  std::cout << "stitching camera positions from different reference views" << std::endl;
118  for(const view_index& target_idx : all_target_vws) {
119  auto target_positions_it = target_reference_camera_positions.find(target_idx);
120  if(target_positions_it == target_reference_camera_positions.end()) continue;
121 
122  struct sample {
123  vec2 position;
124  view_index target_idx;
125  view_index ref_idx;
126 
127  sample(const vec2& pos, const view_index& tg, const view_index& rf) :
128  position(pos), target_idx(tg), ref_idx(rf) { }
129 
130  int idx_dist() const {
131  return sq(ref_idx.x - target_idx.x) + sq(ref_idx.y - target_idx.y);
132  }
133  };
134  std::ptrdiff_t chosen_sample_i = -1;
135  std::vector<sample> samples;
136 
137  for(const auto& p : target_positions_it->second) {
138  const view_index& ref_idx = p.first;
139 
140  const vec2& pos = p.second;
141  if(absolute_reference_camera_positions.find(ref_idx) == absolute_reference_camera_positions.end()) continue;
142  const vec2& absolute_reference_pos = absolute_reference_camera_positions.at(ref_idx);
143 
144  vec2 abs_pos = absolute_reference_pos + pos;
145 
146  samples.emplace_back(abs_pos, target_idx, ref_idx);
147 
148  if(chosen_sample_i == -1) chosen_sample_i = samples.size()-1;
149  else if(samples.back().idx_dist() < samples.at(chosen_sample_i).idx_dist()) chosen_sample_i = samples.size()-1;
150  }
151 
152  for(const sample& samp : samples) {
153  bool chosen = (&samp == &samples.at(chosen_sample_i));
154  if(chosen)
155  absolute_target_camera_positions[samp.target_idx] = samp.position;
156 
157  if(out_camera_centers_stream.is_open())
158  out_camera_centers_stream << samp.position[0] << ' ' << samp.position[1] << ' ' << samp.target_idx.x << ' ' << samp.target_idx.y << ' ' << (chosen ? '1' : '0') << '\n';
159  }
160 
161  if(samples.size() > 1) {
162  vec2 mean(0.0, 0.0);
163  for(const sample& samp : samples) mean += samp.position;
164  mean /= real(samples.size());
165  real max_dist = 0;
166  for(const sample& samp : samples) max_dist = std::max(max_dist, cv::norm(samp.position, mean));
167  overlap_radii.push_back(max_dist);
168  }
169  }
170 
171  real overlap_radii_avg = 0.0;
172  for(real overlap_radius : overlap_radii) overlap_radii_avg += overlap_radius;
173  overlap_radii_avg /= overlap_radii.size();
174  std::sort(overlap_radii.begin(), overlap_radii.end());
175  std::cout << " overlapping positions (more = better): " << overlap_radii.size() << std::endl;
176  std::cout << " average radius (smaller = better): " << overlap_radii_avg << std::endl;
177  std::cout << " median radius: " << overlap_radii[overlap_radii.size()/2] << std::endl;
178  std::cout << " maximum radius: " << overlap_radii.back() << std::endl;
179  }
180 
181 
182  std::cout << "computing camera array" << std::endl;
183  camera_array cameras;
184  auto really_all_target_views = datas.indices();
185  for(const view_index& target_idx : really_all_target_views) {
186  auto it = absolute_target_camera_positions.find(target_idx);
187  if(it == absolute_target_camera_positions.end()) {
188  std::cout << "no camera position for " << target_idx << std::endl;
189  }
190  const vec2& camera_position = it->second;
191 
192  camera cam;
193  cam.name = datas.view(target_idx).camera_name();
194  cam.intrinsic = intr.K;
195  cam.rotation = R;
196  cam.translation = R * vec3(camera_position[0], camera_position[1], 0.0);
197  cameras.push_back(cam);
198  }
199 
200 
201  std::cout << "saving cameras" << std::endl;
202  export_cameras_file(cameras, out_cameras_filename);
203 
204  std::cout << "done" << std::endl;
205 }
206 
void export_cameras_file(const camera_array &cameras, const std::string &filename)
Definition: camera.cc:79
Numeric sq(Numeric n)
Compute square of a number.
Definition: misc.h:17
target_reference_positions_type to_target_reference_positions() const
std::vector< view_index > get_target_views(const relative_camera_positions &rcpos)
mat33 intrinsic
Definition: camera.h:15
std::string encode_view_index(view_index idx)
Definition: dataset.cc:275
std::string name
Definition: camera.h:14
mat33 rotation
Definition: camera.h:16
cv::Vec< real, 2 > vec2
Definition: common.h:22
dataset_view view(int x) const
Definition: dataset.cc:243
cv::Mat_< real > decode_mat(const json &j)
Definition: json.cc:32
std::string out_filename_opt_arg(const std::string &def)
Definition: args.cc:110
intrinsics intrinsics_arg()
Definition: intrinsics.cc:119
references_grid references_grid_arg()
json json_arg()
Definition: json.h:34
relative_camera_positions relative_camera_positions_arg()
distortion_parameters distortion
Definition: intrinsics.h:30
dataset dataset_arg()
Definition: dataset.cc:297
cv::Matx< real, 3, 3 > mat33
Definition: common.h:26
double real
Definition: common.h:16
cv::Vec< real, 3 > vec3
Definition: common.h:23
view_index view(std::ptrdiff_t col, std::ptrdiff_t row) const
std::string camera_name() const
Definition: dataset.cc:60
#define Assert
Definition: assert.h:40
const bool verbose
std::string out_filename_arg()
Definition: args.cc:104
std::size_t cols() const
std::vector< camera > camera_array
Definition: camera.h:26
reference_target_positions_type to_reference_target_positions() const
int main(int argc, const char *argv[])
std::vector< view_index > indices() const
Definition: dataset.cc:235
vec3 translation
Definition: camera.h:17
std::size_t rows() const
void get_args(int argc, const char *argv[], const std::string &usage)
Definition: args.cc:49