licornea_tools
cameras_from_checkerboards.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/assert.h"
8 #include "../lib/opencv.h"
9 #include "../lib/image_io.h"
10 #include "../lib/filesystem.h"
11 
12 using namespace tlz;
13 
14 const bool verbose = false;
15 
16 
17 std::vector<vec3> checkerboard_world_corners(int cols, int rows, real square_width) {
18  std::vector<vec3> world_corners(cols * rows);
19  for(int row = 0, idx = 0; row < rows; ++row) for(int col = 0; col < cols; ++col, ++idx)
20  world_corners[idx] = vec3((col - cols/2)*square_width, (row - rows/2)*square_width, 0.0);
21  return world_corners;
22 }
23 
24 
25 int main(int argc, const char* argv[]) {
26  get_args(argc, argv, "dataset_parameters.json cols rows square_width intr.json out_cameras.json [dataset_group]");
27  dataset datas = dataset_arg();
28  int cols = int_arg();
29  int rows = int_arg();
31  intrinsics intr = intrinsics_arg();
32  std::string out_cameras_filename = out_filename_arg();
33  std::string dataset_group_name = string_opt_arg("");
34 
35  dataset_group datag = datas.group(dataset_group_name);
36 
37  camera_array cameras;
38 
39  auto indices = datas.indices();
40 
41  #pragma omp parallel for
42  for(std::ptrdiff_t i = 0; i < indices.size(); ++i) {
43  if(i % 100 == 0) {
44  #pragma omp critical
45  std::cout << i << " of " << datas.indices().size() << std::endl;
46  } else {
47  std::cout << '.' << std::flush;
48  }
49  const view_index& idx = indices[i];
50 
51  // if(idx.y != datas.y_min() && idx.x != datas.x_min()) continue;
52 
53  // load image
54  dataset_view view = datag.view(idx);
55  std::string image_filename = view.image_filename();
56  std::string camera_name = view.camera_name();
57  if(! file_exists(image_filename)) {
58  std::cout << idx << ": no image file" << std::endl;
59  continue;
60  }
61 
62  cv::Mat_<cv::Vec3b> img;
63  try {
64  img = load_texture(image_filename);
65  } catch(...) {
66  std::cout << idx << ": could not load image" << std::endl;
67  continue;
68  }
69 
70 
71  // find checkerboard
72  std::vector<cv::Point2f> corners;
73  int flags = cv::CALIB_CB_FAST_CHECK | cv::CALIB_CB_ADAPTIVE_THRESH;
74  bool found = cv::findChessboardCorners(img, cv::Size(cols, rows), corners, flags);
75  if(!found || corners.size() != cols*rows) {
76  std::cout << idx << ": no checkerboard detected" << std::endl;
77  continue;
78  }
79 
80 
81  // improve corners
82  cv::TermCriteria term(cv::TermCriteria::COUNT | cv::TermCriteria::EPS, 100, DBL_EPSILON);
83  cv::Mat img_mono;
84  cv::cvtColor(img, img_mono, CV_BGR2GRAY);
85  cv::cornerSubPix(img_mono, corners, cv::Size(11, 11), cv::Size(-1, -1), term);
86 
87 
88  // estimate camera pose
89  std::vector<vec2> image_points = point2f_to_vec2(corners);
90  std::vector<vec3> object_points = checkerboard_world_corners(cols, rows, square_width);
91 
92  vec3 rotation_vec, translation;
93  mat33 rotation;
94  bool ret = cv::solvePnP(
95  object_points,
96  image_points,
97  intr.K,
98  intr.distortion.cv_coeffs(),
99  rotation_vec,
100  translation,
101  false
102  );
103  if(! ret) {
104  std::cout << idx << ": solvePnP failed" << std::endl;
105  continue;
106  }
107  cv::Rodrigues(rotation_vec, rotation);
108 
109 
110  // add camera
111  camera cam;
112  cam.name = camera_name;
113  cam.intrinsic = intr.K;
114  cam.rotation = rotation;
115  cam.translation = translation;
116 
117  #pragma omp critical
118  cameras.push_back(cam);
119  }
120  std::cout << std::endl;
121 
122 
123  // sort cameras
124  std::sort(cameras.begin(), cameras.end(), [](const camera& a, const camera& b) {
125  return (a.name < b.name);
126  });
127 
128 
129  std::cout << "saving cameras" << std::endl;
130  export_cameras_file(cameras, out_cameras_filename);
131 }
void export_cameras_file(const camera_array &cameras, const std::string &filename)
Definition: camera.cc:79
bool file_exists(const std::string &filename)
mat33 intrinsic
Definition: camera.h:15
std::string image_filename() const
Definition: dataset.cc:64
int rows
std::string name
Definition: camera.h:14
const bool verbose
dataset_view view(int x) const
Definition: dataset.cc:105
mat33 rotation
Definition: camera.h:16
cv::Mat_< cv::Vec3b > load_texture(const std::string &filename)
Definition: image_io.cc:6
intrinsics intrinsics_arg()
Definition: intrinsics.cc:119
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
int main(int argc, const char *argv[])
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 camera_name() const
Definition: dataset.cc:60
std::string out_filename_arg()
Definition: args.cc:104
std::vector< real > cv_coeffs() const
Definition: intrinsics.h:17
std::vector< camera > camera_array
Definition: camera.h:26
dataset_group group(const std::string &grp) const
Definition: dataset.cc:265
std::vector< view_index > indices() const
Definition: dataset.cc:235
vec3 translation
Definition: camera.h:17
std::string string_opt_arg(const std::string &def="")
Definition: args.h:36
void get_args(int argc, const char *argv[], const std::string &usage)
Definition: args.cc:49