licornea_tools
cg_rotation_from_depths.cc
Go to the documentation of this file.
1 #include <string>
2 #include <vector>
3 #include <cmath>
4 #include <iostream>
5 #include <fstream>
6 #include <cassert>
8 #include "lib/feature_point.h"
9 #include "../lib/args.h"
10 #include "../lib/rotation.h"
11 #include "../lib/misc.h"
12 #include "../lib/json.h"
13 #include "../lib/intrinsics.h"
14 #include "../lib/assert.h"
15 #include "../lib/opencv.h"
16 #include "../lib/eigen.h"
17 
18 using namespace tlz;
19 
20 constexpr bool verbose = true;
21 
22 constexpr int depth_min_views = 100;
23 constexpr int hslope_min_views = 10;
24 constexpr int vslope_min_views = 10;
25 
26 const vec3 null_vec3(0.0,0.0,0.0);
27 
28 // rotation which puts normal onto (0,0,1)
29 using xy_rotation = vec3;
30 
32  // get points v in camera's view spaces
33  std::vector<Eigen_vec3> v_points;
34  v_points.reserve(feature.points.size());
35  Eigen_vec3 v_mean(0.0, 0.0, 0.0);
36  for(const auto& kv : feature.points) {
37  const feature_point& fpoint = kv.second;
38  if(fpoint.depth == 0.0) continue;
39 
40  Eigen_vec3 i_h = Eigen_vec3(fpoint.position[0], fpoint.position[1], 1.0) * fpoint.depth;
41  Eigen_vec3 v = to_eigen_mat(K_inv) * i_h;
42  v_points.push_back(v);
43  v_mean += v;
44  }
45  std::size_t n = v_points.size();
46  if(n < depth_min_views) return null_vec3;
47 
48  v_mean = v_mean / real(n);
49 
50  // fit plane to these points
51  Eigen_matnX<3> A(3, n);
52  for(std::ptrdiff_t i = 0; i < n; ++i) {
53  const Eigen_vec3& v = v_points[i];
54  A(0, i) = v[0] - v_mean[0];
55  A(1, i) = v[1] - v_mean[1];
56  A(2, i) = v[2] - v_mean[2];
57  }
58 
59  Eigen::JacobiSVD<decltype(A)> svd(A, Eigen::ComputeThinU);
60  auto U = svd.matrixU();
61  Eigen_vec3 normal(U(0,2), U(1,2), U(2,2));
62  if(normal[2] < 0.0) normal = -normal;
63 
64  return from_eigen<3>(normal);
65 }
66 
67 
69  vec3 z(0.0, 0.0, 1.0);
70  vec3 v = normal.cross(z);
71  mat33 v_mat(
72  0.0, -v[2], v[1],
73  v[2], 0.0, -v[0],
74  -v[1], v[0], 0.0
75  );
76  real c = normal.dot(z);
77  real f = 1.0 / (1.0 + c);
78  mat33 R = mat33::eye() + v_mat + f*v_mat*v_mat;
79  return R;
80 }
81 
82 
83 real additional_z_rotation(const mat33& K_inv, const mat33& R_xy, const image_correspondence_feature& feature) {
84  // get points v in camera's unrotated view spaces, without depth
85  std::vector<cv::Vec2f> horizontal_v_points, vertical_v_points;
86  for(const auto& kv : feature.points) {
87  const view_index& idx = kv.first;
88  const feature_point& fpoint = kv.second;
89  if(fpoint.depth == 0.0) continue;
90 
91  vec3 i_h = vec3(fpoint.position[0], fpoint.position[1], 1.0) * fpoint.depth;
92  vec3 v = R_xy * K_inv * i_h;
93 
94  if(idx.y == feature.reference_view.y) horizontal_v_points.emplace_back(v[0], v[1]);
95  if(idx.x == feature.reference_view.x) vertical_v_points.emplace_back(v[0], v[1]);
96  }
97 
98  real horizontal_tan = NAN, vertical_tan = NAN;
99 
100 
101  if(horizontal_v_points.size() >= hslope_min_views) {
102  cv::Vec4f line_parameters;
103  cv::fitLine(horizontal_v_points, line_parameters, CV_DIST_L2, 0.0, 0.01, 0.01);
104  horizontal_tan = line_parameters[1] / line_parameters[0];
105  }
106 
107  if(vertical_v_points.size() >= vslope_min_views) {
108  cv::Vec4f line_parameters;
109  cv::fitLine(vertical_v_points, line_parameters, CV_DIST_L2, 0.0, 0.01, 0.01);
110  vertical_tan = -line_parameters[0] / line_parameters[1];
111  }
112 
113  if(std::isfinite(horizontal_tan) && std::isfinite(vertical_tan)) {
114  return (horizontal_tan + vertical_tan) / 2.0;
115  } else if(std::isfinite(horizontal_tan))
116  return horizontal_tan;
117  else if(std::isfinite(vertical_tan))
118  return vertical_tan;
119  else
120  return NAN;
121 }
122 
123 
124 int main(int argc, const char* argv[]) {
125  get_args(argc, argv, "cors.json intrinsics.json out_rotation.json");
127  intrinsics intr = intrinsics_arg();
128  std::string out_rotation_filename = out_filename_arg();
129 
130  vec3 xy_normal_sum = 0.0;
131  for(const auto& kv : cors.features) {
132  const image_correspondence_feature& feature = kv.second;
133  xy_rotation xy = estimate_xy_rotation(intr.K_inv, feature);
134  if(xy == null_vec3) continue;
135 
136  xy_normal_sum += xy;
137  }
138  vec3 xy_normal = xy_normal_sum / cv::norm(xy_normal_sum);
139 
140  mat33 R_xy = xy_rotation_matrix(xy_normal);
141 
142  real angle_mean = 0.0;
143  int angle_count = 0;
144  for(const auto& kv : cors.features) {
145  const image_correspondence_feature& feature = kv.second;
146  real tan = additional_z_rotation(intr.K_inv, R_xy, feature);
147  if(std::isnan(tan)) continue;
148  angle_mean += std::atan(tan);
149  angle_count++;
150  }
151  real angle = angle_mean / angle_count;
152 
153  mat33 R_z(
154  std::cos(angle), -std::sin(angle), 0.0,
155  std::sin(angle), std::cos(angle), 0.0,
156  0.0, 0.0, 1.0
157  );
158 
159  mat33 R = R_xy.t() * R_z;
160 
161 
162  std::cout << R << std::endl;
163  vec3 euler = to_euler(R);
164  std::cout << "x = " << euler[0] * deg_per_rad << "\n";
165  std::cout << "y = " << euler[1] * deg_per_rad << "\n";
166  std::cout << "z = " << euler[2] * deg_per_rad << std::endl;
167 
168  std::cout << "saving rotation matrix" << std::endl;
169  export_json_file(encode_mat(R), out_rotation_filename);
170 }
real additional_z_rotation(const mat33 &K_inv, const mat33 &R_xy, const image_correspondence_feature &feature)
constexpr real deg_per_rad
Definition: common.h:78
int main(int argc, const char *argv[])
constexpr int depth_min_views
Set of features, each on set of views.
constexpr bool verbose
constexpr int vslope_min_views
Eigen_vec< 3 > Eigen_vec3
Definition: eigen.h:20
Eigen_mat< Rows, Cols > to_eigen_mat(const cv::Matx< real, Rows, Cols > &cv_mat)
Definition: eigen.h:24
Eigen::Matrix< real, Rows, Eigen::Dynamic > Eigen_matnX
Definition: eigen.h:13
std::map< std::string, image_correspondence_feature > features
intrinsics intrinsics_arg()
Definition: intrinsics.cc:119
mat33 xy_rotation_matrix(const xy_rotation &normal)
cv::Matx< real, 3, 3 > mat33
Definition: common.h:26
json encode_mat(const Mat &mat)
Definition: json.h:19
double real
Definition: common.h:16
void export_json_file(const json &j, const std::string &filename, bool compact)
Definition: json.cc:9
cv::Vec< real, 3 > vec3
Definition: common.h:23
image_correspondences image_correspondences_arg()
constexpr int hslope_min_views
std::string out_filename_arg()
Definition: args.cc:104
vec3 to_euler(const mat33 &R_)
Definition: rotation.cc:39
Feature on set of views. Optionally one view is "reference".
vec3 xy_rotation
std::map< view_index, feature_point > points
xy_rotation estimate_xy_rotation(const mat33 &K_inv, const image_correspondence_feature &feature)
const vec3 null_vec3(0.0, 0.0, 0.0)
void get_args(int argc, const char *argv[], const std::string &usage)
Definition: args.cc:49