2 #include "../../lib/common.h" 3 #include "../../lib/misc.h" 21 assert(corners_.size() ==
cols*
rows);
30 int min_x = INT_MAX, min_y = INT_MAX, max_x = 0, max_y = 0;
31 for(
const vec2& pt : outer_corners) {
32 int x = pt[0], y = pt[1];
33 if(x > max_x) max_x = x;
34 if(x < min_x) min_x = x;
35 if(y > max_y) max_y = y;
36 if(y < min_y) min_y = y;
38 bounding_rect = cv::Rect(min_x, min_y, max_x-min_x, max_y-min_y);
47 std::vector<cv::Point2f>
corners;
49 int flags = cv::CALIB_CB_FAST_CHECK | cv::CALIB_CB_ADAPTIVE_THRESH;
50 bool found = cv::findChessboardCorners(img, cv::Size(cols, rows), corners, flags);
53 cv::TermCriteria term(cv::TermCriteria::COUNT | cv::TermCriteria::EPS, 100, DBL_EPSILON);
55 cv::cvtColor(img, img_mono, CV_BGR2GRAY);
56 cv::cornerSubPix(img_mono, corners, cv::Size(11, 11), cv::Size(-1, -1), term);
58 return checkerboard(cols, rows, square_width, point2f_to_vec2(corners));
63 static cv::Ptr<cv::CLAHE> clahe;
64 if(! clahe) clahe = cv::createCLAHE(1.5, cv::Size(32, 32));
66 cv::Mat_<uchar> larger_img;
68 cv::resize(img, larger_img, cv::Size(0,0), scale, scale, cv::INTER_CUBIC);
70 clahe->apply(larger_img, larger_img);
72 std::vector<cv::Point2f>
corners;
74 int flags = cv::CALIB_CB_ADAPTIVE_THRESH;
75 bool found = cv::findChessboardCorners(larger_img, cv::Size(cols, rows), corners, flags);
78 cv::TermCriteria term(cv::TermCriteria::EPS, 100, DBL_EPSILON);
79 cv::cornerSubPix(larger_img, corners, cv::Size(11, 11), cv::Size(-1, -1), term);
83 return checkerboard(cols, rows, square_width, point2f_to_vec2(corners));
88 ushort max_ir = 0xffff;
90 float alpha = 255.0f / (max_ir - min_ir);
91 float beta = -alpha * min_ir;
93 cv::convertScaleAbs(ir_orig, ir, alpha, beta);
96 ir.setTo(0, (ir_orig == 0));
102 std::vector<vec3> world_corners(cols * rows);
103 for(
int row = 0, idx = 0; row <
rows; ++row)
for(
int col = 0; col <
cols; ++col, ++idx)
104 world_corners[idx] =
vec3((col - cols/2)*square_width, (row - rows/2)*square_width, 0.0);
105 return world_corners;
115 cv::Mat_<cv::Vec3b> out_img;
117 if(! chk)
return out_img;
120 std::vector<std::vector<cv::Point>> polylines { chk.
outer_corners_i() };
125 cv::drawChessboardCorners(out_img, cv::Size(chk.
cols, chk.
rows), vec2_to_point2f(chk.
corners),
true);
133 cv::Mat_<cv::Vec3b> conv_img;
134 cv::cvtColor(img, conv_img, CV_GRAY2BGR);
138 cv::Mat_<uchar> img_8bit(img);
139 ushort max_ir = 0xffff;
141 float alpha = 255.0f / (max_ir - min_ir);
142 float beta = -alpha * min_ir;
144 cv::convertScaleAbs(img, img_8bit, alpha, beta);
150 cv::Mat_<cv::Vec3b> out_img;
152 for(
const auto& pix : pixels) {
153 int x = pix.coordinates[0], y = pix.coordinates[1];
154 if(x < 0 || x >= img.cols || y < 0 || y >= img.rows)
continue;
156 cv::Vec3b col(100, 100, 255);
157 if(rad == 1) out_img(y, x) = col;
158 else cv::circle(out_img, cv::Point(x, y), rad, cv::Scalar(col), 2);
165 cv::Mat_<cv::Vec3b> conv_img;
166 cv::cvtColor(img, conv_img, CV_GRAY2BGR);
177 for(
int i = 0; i < chk.
rows*chk.
cols; ++i) {
193 for(
int i = 0; i < chk1.
rows*chk1.
cols; ++i) {
208 vec3 rotation_vec, translation;
210 const bool use_ransac =
false;
215 object_points_[idx] = cv::Vec3f( object_points[idx][0], object_points[idx][1], object_points[idx][2] );
216 image_points_[idx] = cv::Vec2f( image_points[idx][0], image_points[idx][1] );
244 cv::Rodrigues(rotation_vec, rotation);
258 std::vector<vec2> reprojected_image_points;
265 reprojected_image_points
269 const vec2& i_orig = image_points[idx];
270 const vec2& i_reproj = reprojected_image_points[idx];
271 vec2 diff = i_reproj - i_orig;
272 err +=
sq(diff[0]) +
sq(diff[1]);
275 return std::sqrt(err);
280 auto direction_deviation = [](
const std::vector<vec2>& vecs) {
281 std::vector<vec2> nvecs;
282 for(
const vec2& vec : vecs)
283 nvecs.push_back(vec / std::sqrt(
sq(vec[0]) +
sq(vec[1])));
286 for(
const vec2& nvec : nvecs) mean += nvec;
287 mean *= 1.0/vecs.size();
290 for(
const vec2 nvec : nvecs) {
291 vec2 diff = nvec - mean;
292 rms +=
sq(diff[0]) +
sq(diff[1]);
295 return std::sqrt(rms);
298 std::vector<vec2> horizontal_vectors, vertical_vectors;
299 for(
int row = 0; row < chk.
rows; ++row)
300 horizontal_vectors.push_back(chk.
corner(chk.
cols-1, row) - chk.
corner(0, row));
302 for(
int col = 0; col < chk.
cols; ++col)
303 vertical_vectors.push_back(chk.
corner(col, chk.
rows-1) - chk.
corner(col, 0));
306 direction_deviation(horizontal_vectors),
307 direction_deviation(vertical_vectors)
315 real fx = intr.
K(0, 0), fy = intr.
K(1, 1);
321 for(
int row = 0; row < chk.
rows; ++row) {
323 iw +=
sq(diff[0]) +
sq(diff[1]);
325 iw = std::sqrt(iw / chk.
rows);
328 for(
int col = 0; col < chk.
cols; ++col) {
330 ih +=
sq(diff[0]) +
sq(diff[1]);
332 ih = std::sqrt(ih / chk.
cols);
334 real dx = fx * w / iw;
335 real dy = fy * h / ih;
339 return (dx + dy) / 2.0;
347 cv::Mat_<uchar> mask(depth_image.size());
349 std::vector<std::vector<cv::Point>> polylines { chk.
outer_corners_i() };
353 std::vector<checkerboard_pixel_depth_sample> depth_samples;
354 for(
int ry = 0; ry < bounding_rect.height; ry += granularity)
355 for(
int rx = 0; rx < bounding_rect.width; rx += granularity) {
356 int x = bounding_rect.x + rx, y = bounding_rect.y + ry;
358 if(! mask(y, x))
continue;
359 real d = depth_image(y, x);
360 if(d <= 100.0)
continue;
366 depth_samples.push_back(samp);
369 return depth_samples;
375 if(inout_samples.size() == 0)
return;
378 std::vector<vec2> image_points;
380 image_points.push_back(sample.coordinates);
383 vec3 normal(0.0, 0.0, 1.0);
388 std::vector<vec2> undistorted_normalized_points;
391 undistorted_normalized_points,
399 for(
int idx = 0; idx < image_points.size(); ++idx) {
401 v[0] = undistorted_normalized_points[idx][0];
402 v[1] = undistorted_normalized_points[idx][1];
405 real t = plane_distance / normal.dot(v);
408 inout_samples[idx].calculated_depth = v[2];
Numeric sq(Numeric n)
Compute square of a number.
std::array< vec3, Obj_count > object_coordinates
void calculate_checkerboard_pixel_depths(const intrinsics &intr, const checkerboard_extrinsics &ext, std::vector< checkerboard_pixel_depth_sample > &inout_samples)
obj_img_correspondences< 1, 1 > checkerboard_obj_img_correspondences(const checkerboard &chk)
std::vector< vec2 > checkerboard_image_corners(const checkerboard &chk)
checkerboard_extrinsics estimate_checkerboard_extrinsics(const checkerboard &chk, const intrinsics &intr)
cv::Mat_< cv::Vec3b > visualize_checkerboard(const cv::Mat_< cv::Vec3b > &img, const checkerboard &chk, const checkerboard_visualization_parameters ¶m)
std::vector< vec2 > outer_corners
checkerboard detect_color_checkerboard(cv::Mat_< cv::Vec3b > &img, int cols, int rows, real square_width)
std::vector< vec2 > corners
vec2 checkerboard_parallel_measures(const checkerboard &chk)
std::size_t corners_count() const
real calculate_parallel_checkerboard_depth(const checkerboard &chk, const intrinsics &intr)
cv::Mat_< cv::Vec3b > visualize_checkerboard_pixel_samples(const cv::Mat_< cv::Vec3b > &img, const std::vector< checkerboard_pixel_depth_sample > &pixels, int rad)
distortion_parameters distortion
cv::Matx< real, 3, 3 > mat33
std::vector< obj_img_correspondence< Obj_count, Img_count >> obj_img_correspondences
vec2 corner(int col, int row) const
std::array< vec2, Img_count > image_coordinates
std::vector< vec3 > checkerboard_world_corners(int cols, int rows, real square_width)
std::vector< real > cv_coeffs() const
real checkerboard_reprojection_error(const checkerboard &chk, const intrinsics &intr, const checkerboard_extrinsics &ext)
obj_img_correspondences< 1, 2 > checkerboard_obj_2img_correspondences(const checkerboard &chk1, const checkerboard &chk2)
checkerboard detect_ir_checkerboard(cv::Mat_< uchar > &img, int cols, int rows, real square_width)
std::vector< cv::Point > outer_corners_i() const
std::vector< checkerboard_pixel_depth_sample > checkerboard_pixel_depth_samples(const checkerboard &chk, const cv::Mat_< float > &depth_image, int granularity)