licornea_tools
cg_generate_artificial.cc
Go to the documentation of this file.
1 #include <string>
2 #include <map>
3 #include <cmath>
4 #include <random>
6 #include "../lib/args.h"
7 #include "../lib/misc.h"
8 #include "../lib/json.h"
9 #include "../lib/opencv.h"
10 #include "../lib/camera.h"
11 #include "../lib/image_io.h"
12 #include "../lib/random_color.h"
13 #include "../lib/intrinsics.h"
14 #include "../lib/filesystem.h"
15 #include "../lib/rotation.h"
16 
17 using namespace tlz;
18 
19 bool noisy_position = true;
20 bool noisy_rotation = false;
21 
22 int main(int argc, const char* argv[]) {
23  get_args(argc, argv, "R.json intr.json out_datas_dir/ [features_count=100] [num_x=30] [num_y=30] [step_x=3.0] [step_y=3.0]");
24  mat33 R = decode_mat(json_arg());
25  intrinsics intr = intrinsics_arg();
26  std::string out_datas_dir = out_dirname_arg();
27  int features_count = int_opt_arg(100);
28  int num_x = int_opt_arg(30);
29  int num_y = int_opt_arg(30);
30  real step_x = real_opt_arg(3.0);
31  real step_y = real_opt_arg(3.0);
32 
33  mat33 K = intr.K;
34  real fx = K(0, 0), fy = K(1, 1), cx = K(0, 2), cy = K(1, 2);
35 
36  std::mt19937 gen;
37 
38  int width = intr.width;
39  int height = intr.height;
40 
41  std::cout << "generating " << features_count << " random 3D features" << std::endl;
42  std::vector<vec3> features;
43  {
44  std::uniform_real_distribution<real> ix_dist(0, width);
45  std::uniform_real_distribution<real> iy_dist(0, height);
46  std::uniform_real_distribution<real> vz_dist(500.0, 3000.0);
47 
48  for(int i = 0; i < features_count; ++i) {
49  real ix = ix_dist(gen);
50  real iy = iy_dist(gen);
51  real vz = vz_dist(gen);
52 
53  real vx = (ix - cx)*vz/fx;
54  real vy = (iy - cy)*vz/fy;
55 
56  vec3 v(vx, vy, vz);
57  vec3 w = R.t() * v;
58 
59  features.push_back(w);
60  }
61  }
62 
63 
64  std::cout << "creating directories" << std::endl;
65  make_directory(out_datas_dir);
66  make_directory(out_datas_dir + "/image");
67  make_directory(out_datas_dir + "/depth");
68 
69 
70  std::cout << "generating dataset parameters" << std::endl;
71  {
72  json j_dataset = json::object();
73  j_dataset["x_index_range"] = json::array({0, num_x-1});
74  j_dataset["y_index_range"] = json::array({0, num_y-1});
75  j_dataset["width"] = width;
76  j_dataset["height"] = height;
77  j_dataset["image_filename_format"] = "image/y{y}_x{x}.png";
78  j_dataset["depth_filename_format"] = "depth/y{y}_x{x}.png";
79  j_dataset["cameras_filename"] = "cameras.json";
80  j_dataset["camera_name_format"] = "camera_y{y}_x{x}";
81  export_json_file(j_dataset, out_datas_dir + "/parameters.json");
82  }
83 
84 
85  std::cout << "generating correspondences by projecting features for each view" << std::endl;
87  view_index reference_view(num_x/2, num_y/2);
88  std::map<view_index, vec3> view_camera_centers;
89  std::map<view_index, mat33> view_camera_rotations;
90 
91  std::normal_distribution<real> pos_noise_dist(0.0, step_x/15.0), pos_outlier_noise_dist(0.0, step_x/6.0);
92  std::bernoulli_distribution pos_outlier_dist(0.01);
93  std::normal_distribution<real> rot_noise_dist(0.0, 0.007_deg), rot_roll_noise_dist(0.0, 0.004_deg);
94 
95  for(int y = 0; y < num_y; ++y) for(int x = 0; x < num_x; ++x) {
96  view_index idx(x, y);
97 
98  // camera center position
99  real px = step_x*(x - num_x/2);
100  real py = step_y*(y - num_y/2);
101  mat33 cam_R = R;
102 
103  if(noisy_position) {
104  if(pos_outlier_dist(gen)) {
105  px += pos_outlier_noise_dist(gen);
106  py += pos_outlier_noise_dist(gen);
107  } else {
108  px += pos_noise_dist(gen);
109  py += pos_noise_dist(gen);
110  }
111  }
112 
113  if(noisy_rotation) {
114  vec3 euler = to_euler(cam_R);
115  euler[0] += rot_noise_dist(gen);
116  euler[1] += rot_noise_dist(gen);
117  euler[2] += rot_roll_noise_dist(gen);
118  cam_R = to_rotation_matrix(euler);
119  }
120 
121 
122  vec3 p(px, py, 0.0);
123  view_camera_centers[idx] = p;
124  view_camera_rotations[idx] = cam_R;
125 
126 
127 
128  for(int feature = 0; feature < features_count; ++feature) {
129  // feature image position in this view
130  const vec3& w = features[feature];
131  vec3 v = cam_R*(w + p);
132  vec3 i_ = K*v;
133  vec2 i(i_[0]/i_[2], i_[1]/i_[2]);
134  vec2 dist_i = distort_point(intr, i);
135 
136  // add image correspondence
137  std::string feature_name = "feat" + std::to_string(feature);
138  feature_point fpoint;
139  fpoint.position = dist_i;
140  fpoint.depth = v[2];
141  fpoint.weight = 1.0;
142 
143  auto feature_it = cors.features.find(feature_name);
144  if(feature_it == cors.features.end()) {
146  feature.reference_view = reference_view;
147  auto res = cors.features.emplace(feature_name, std::move(feature));
148  feature_it = res.first;
149  }
150 
151  feature_it->second.points[idx] = fpoint;
152  }
153  }
154 
155 
156  std::cout << "saving correspondences" << std::endl;
157  export_image_corresponcences(cors, out_datas_dir + "/cors.json");
158 
159 
160  std::cout << "saving cameras" << std::endl;
161  camera_array cams;
162  for(const auto& kv : view_camera_centers) {
163  view_index idx = kv.first;
164  const vec3& p = kv.second;
165  vec3 t = R * p;
166 
167  camera cam;
168  cam.name = "camera_y" + std::to_string(idx.y) + "_x" + std::to_string(idx.x);
169  cam.intrinsic = K;
170  cam.rotation = view_camera_rotations.at(idx);
171  cam.translation = t;
172  cams.push_back(cam);
173  }
174  std::string cameras_filename = out_datas_dir + "/cameras.json";
175  export_cameras_file(cams, cameras_filename);
176 
177 
178  std::cout << "saving straight depths" << std::endl;
179  {
180  json j_straight_depths = json::object();
181  for(int feature = 0; feature < features_count; ++feature) {
182  std::string feature_name = "feat" + std::to_string(feature);
183  const vec3& wp = features.at(feature);
184 
185  j_straight_depths[feature_name] = wp[2];
186  }
187  export_json_file(j_straight_depths, out_datas_dir + "/straight_depths.json");
188  }
189 
190 
191  std::cout << "drawing images and depth maps" << std::endl;
192  const cv::Vec3b background_color(0, 0, 0);
193  const real small_radius = 4.0;
194  const real large_radius = 60.0;
195  const real focal = (intr.fx() + intr.fy()) / 2.0;
196 
197  auto draw_circle = [](cv::Mat& mat, real x, real y, real rad, cv::Scalar col, bool smooth) {
198  if(smooth) {
199  int shift = 8;
200  int x_int = x * (1<<shift), y_int = y * (1<<shift), rad_int = rad * (1<<shift);
201  cv::circle(mat, cv::Point(x_int, y_int), rad_int, cv::Scalar(col), -1, CV_AA, shift);
202  } else {
203  cv::circle(mat, cv::Point(x, y), rad, cv::Scalar(col), -1, 8);
204  }
205  };
206 
207  #pragma omp parallel for
208  for(int y = 0; y < num_y; ++y) for(int x = 0; x < num_x; ++x) {
209  view_index idx(x, y);
210  std::cout << '.' << std::flush;
211 
212  // images
213  cv::Mat_<cv::Vec3b> texture_image(height, width, background_color);
214  cv::Mat_<ushort> depth_image(height, width, ushort(0xffff));
215 
216  for(int feature = 0; feature < features_count; ++feature) {
217  std::string feature_name = "feat" + std::to_string(feature);
218  const feature_point& fpoint = cors.features.at(feature_name).points.at(idx);
219  real x = fpoint.position[0], y = fpoint.position[1];
220  real depth = fpoint.depth;
221 
222  cv::Mat_<cv::Vec3b> feature_texture_image(height, width, background_color);
223  cv::Mat_<uchar> feature_mask_image(height, width, uchar(0));
224 
225  int small_radius_pix = focal * small_radius / depth;
226  int large_radius_pix = focal * large_radius / depth;
227 
228  cv::Vec3b col = random_color(feature);
229  cv::Vec3b col_darker = 0.3 * col;
230 
231  draw_circle(feature_texture_image, x, y, large_radius_pix, cv::Scalar(col_darker), true);
232  draw_circle(feature_texture_image, x, y, small_radius_pix, cv::Scalar(col), true);
233  draw_circle(feature_mask_image, x, y, large_radius_pix-2, 255, true);
234 
235  cv::Mat_<uchar> mask = feature_mask_image & (depth < depth_image);
236  feature_texture_image.copyTo(texture_image, mask);
237  depth_image.setTo(depth, mask);
238  }
239  depth_image.setTo(ushort(0), (depth_image == 0xffff));
240 
241  // save images
242  std::string texture_image_filename = out_datas_dir + "/image/y" + std::to_string(y) + "_x" + std::to_string(x) + ".png";
243  std::string depth_image_filename = out_datas_dir + "/depth/y" + std::to_string(y) + "_x" + std::to_string(x) + ".png";
244  cv::resize(texture_image, texture_image, cv::Size(width, height), 0.0, 0.0, cv::INTER_CUBIC);
245  save_texture(texture_image_filename, texture_image);
246  cv::resize(depth_image, depth_image, cv::Size(width, height), 0.0, 0.0, cv::INTER_NEAREST);
247  save_depth(depth_image_filename, depth_image);
248  }
249  std::cout << std::endl;
250 
251 
252  std::cout << "done" << std::endl;
253 }
void save_depth(const std::string &filename, const cv::Mat_< ushort > &depth)
Definition: image_io.cc:43
void export_cameras_file(const camera_array &cameras, const std::string &filename)
Definition: camera.cc:79
long int_opt_arg(long def)
Definition: args.h:50
bool noisy_position
void save_texture(const std::string &filename, const cv::Mat_< cv::Vec3b > &texture)
Definition: image_io.cc:13
double real_opt_arg(double def)
Definition: args.h:54
mat33 intrinsic
Definition: camera.h:15
std::string name
Definition: camera.h:14
Set of features, each on set of views.
cv::Vec3b random_color(int i)
Definition: random_color.cc:8
mat33 rotation
Definition: camera.h:16
const cv::Vec3b background_color(0, 0, 0)
cv::Vec< real, 2 > vec2
Definition: common.h:22
int main(int argc, const char *argv[])
cv::Mat_< real > decode_mat(const json &j)
Definition: json.cc:32
std::map< std::string, image_correspondence_feature > features
intrinsics intrinsics_arg()
Definition: intrinsics.cc:119
real fx() const
Definition: intrinsics.h:34
json json_arg()
Definition: json.h:34
cv::Matx< real, 3, 3 > mat33
Definition: common.h:26
double real
Definition: common.h:16
vec2 distort_point(const intrinsics &intr, const vec2 &undistorted)
Definition: intrinsics.cc:82
std::string out_dirname_arg()
Definition: args.cc:121
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
mat33 to_rotation_matrix(const vec3 &euler)
Definition: rotation.cc:17
std::string to_string(const T &)
vec3 to_euler(const mat33 &R_)
Definition: rotation.cc:39
Feature on set of views. Optionally one view is "reference".
bool noisy_rotation
void make_directory(const std::string &dirname)
std::vector< camera > camera_array
Definition: camera.h:26
real fy() const
Definition: intrinsics.h:35
void export_image_corresponcences(const image_correspondences &cors, const std::string &filename)
nlohmann::json json
Definition: json.h:11
vec3 translation
Definition: camera.h:17
void get_args(int argc, const char *argv[], const std::string &usage)
Definition: args.cc:49