13 #include <mrpt/otherlibs/do_opencv_includes.h> 18 #include <Eigen/Dense> 33 unsigned int check_size_y,
double check_squares_length_X_meters,
35 std::vector<double>& distortionParams,
bool normalize_image,
36 double* out_MSE,
bool skipDrawDetectedImgs,
37 bool useScaramuzzaAlternativeDetector)
42 images, check_size_x, check_size_y, check_squares_length_X_meters,
43 check_squares_length_Y_meters, cam, normalize_image, out_MSE,
44 skipDrawDetectedImgs, useScaramuzzaAlternativeDetector);
52 #include <opencv2/core/eigen.hpp> 60 unsigned int check_size_y,
double check_squares_length_X_meters,
62 bool normalize_image,
double* out_MSE,
bool skipDrawDetectedImgs,
63 bool useScaramuzzaAlternativeDetector)
71 ASSERT_(check_squares_length_X_meters > 0);
72 ASSERT_(check_squares_length_Y_meters > 0);
74 if (images.size() < 1)
76 std::cout <<
"ERROR: No input images." << std::endl;
80 const unsigned CORNERS_COUNT = check_size_x * check_size_y;
81 const CvSize check_size = cvSize(check_size_x, check_size_y);
85 vector<cv::Point3f> pattern_obj_points(CORNERS_COUNT);
88 for (
y = 0, k = 0;
y < check_size_y;
y++)
90 for (
unsigned int x = 0;
x < check_size_x;
x++, k++)
92 pattern_obj_points[k].x = -check_squares_length_X_meters *
96 pattern_obj_points[k].y = check_squares_length_Y_meters *
y;
97 pattern_obj_points[k].z = 0;
104 TCalibrationImageList::iterator it;
105 for (it = images.begin(); it != images.end(); ++it)
118 "Error reading image: %s", it->first.c_str());
127 vector<vector<cv::Point3f>>
129 vector<vector<cv::Point2f>>
132 unsigned int valid_detected_imgs = 0;
133 vector<string> pointsIdx2imageFile;
134 cv::Size imgSize(0, 0);
137 for (i = 0, it = images.begin(); it != images.end(); it++, i++)
148 out_camera_params.
ncols = imgSize.width;
149 out_camera_params.
nrows = imgSize.height;
153 if (imgSize.height != (
int)img_gray.
getHeight() ||
154 imgSize.width != (int)img_gray.
getWidth())
156 std::cout <<
"ERROR: All the images must have the same size" 164 unsigned corners_count;
165 bool corners_found =
false;
167 corners_count = CORNERS_COUNT;
169 vector<cv::Point2f> this_img_pts(
177 vector<TPixelCoordf> detectedCoords;
179 img_gray, detectedCoords, check_size_x, check_size_y,
181 useScaramuzzaAlternativeDetector);
183 corners_count = detectedCoords.size();
186 ASSERT_(detectedCoords.size() <= CORNERS_COUNT);
187 for (
size_t p = 0;
p < detectedCoords.size();
p++)
189 this_img_pts[
p].x = detectedCoords[
p].x;
190 this_img_pts[
p].y = detectedCoords[
p].y;
193 if (corners_found && corners_count != CORNERS_COUNT)
194 corners_found =
false;
199 corners_found ?
"DETECTED" :
"NOT DETECTED");
206 for (
y = 0, k = 0;
y < check_size.height;
y++)
207 for (
x = 0;
x < check_size.width;
x++, k++)
209 this_img_pts[k].x, this_img_pts[k].y);
216 CvPoint prev_pt = cvPoint(0, 0);
217 const int line_max = 8;
218 CvScalar line_colors[8];
220 line_colors[0] = CV_RGB(255, 0, 0);
221 line_colors[1] = CV_RGB(255, 128, 0);
222 line_colors[2] = CV_RGB(255, 128, 0);
223 line_colors[3] = CV_RGB(200, 200, 0);
224 line_colors[4] = CV_RGB(0, 255, 0);
225 line_colors[5] = CV_RGB(0, 200, 200);
226 line_colors[6] = CV_RGB(0, 0, 255);
227 line_colors[7] = CV_RGB(255, 0, 255);
235 for (
y = 0, k = 0;
y < check_size.height;
y++)
238 for (
x = 0;
x < check_size.width;
x++, k++)
240 cv::Point pt{cvRound(this_img_pts[k].
x),
241 cvRound(this_img_pts[k].
y)};
243 if (k != 0) cv::line(rgb_img, prev_pt, pt,
color);
246 rgb_img, cv::Point(pt.x -
r, pt.y -
r),
247 cv::Point(pt.x +
r, pt.y +
r),
color);
249 rgb_img, cv::Point(pt.x -
r, pt.y +
r),
250 cv::Point(pt.x +
r, pt.y -
r),
color);
251 cv::circle(rgb_img, pt,
r + 1,
color);
258 pointsIdx2imageFile.push_back(it->first);
259 imagePoints.push_back(this_img_pts);
260 objectPoints.push_back(pattern_obj_points);
262 valid_detected_imgs++;
267 std::cout << valid_detected_imgs <<
" valid images." << std::endl;
268 if (!valid_detected_imgs)
270 std::cout <<
"ERROR: No valid images. Perhaps the checkerboard " 280 cv::Mat cameraMatrix, distCoeffs(1, 5, CV_64F, cv::Scalar::all(0));
281 vector<cv::Mat> rvecs, tvecs;
283 const double cv_calib_err = cv::calibrateCamera(
284 objectPoints, imagePoints, imgSize, cameraMatrix, distCoeffs, rvecs,
290 cv::cv2eigen(cameraMatrix, M);
294 out_camera_params.
dist.fill(0);
295 for (
int k = 0; k < 5; k++)
296 out_camera_params.
dist[k] = distCoeffs.ptr<
double>()[k];
299 for (i = 0; i < valid_detected_imgs; i++)
308 cv::Rodrigues(rvecs[i], cv_rot);
311 cv::cv2eigen(cv_rot, rot);
312 HM.
block<3, 3>(0, 0) = rot;
317 cv::cv2eigen(tvecs[i], trans);
318 HM.
block<3, 1>(0, 3) = trans;
323 images[pointsIdx2imageFile[i]].reconstructed_camera_pose =
p;
327 <<
": " <<
p << std::endl;
339 for (it = images.begin(); it != images.end(); ++it)
352 for (i = 0; i < valid_detected_imgs; i++)
359 vector<TPoint3D> lstPatternPoints(
361 for (
unsigned int p = 0;
p < CORNERS_COUNT;
p++)
363 pattern_obj_points[
p].
x, pattern_obj_points[
p].
y,
364 pattern_obj_points[
p].
z);
366 vector<TPixelCoordf>& projectedPoints =
368 vector<TPixelCoordf>& projectedPoints_distorted =
383 projectedPoints_distorted
386 ASSERT_(projectedPoints.size() == CORNERS_COUNT);
387 ASSERT_(projectedPoints_distorted.size() == CORNERS_COUNT);
389 for (
unsigned int p = 0;
p < CORNERS_COUNT;
p++)
391 const double px = projectedPoints[
p].x;
392 const double py = projectedPoints[
p].y;
394 const double px_d = projectedPoints_distorted[
p].x;
395 const double py_d = projectedPoints_distorted[
p].y;
400 if (px >= 0 && px < imgSize.width && py >= 0 &&
404 4, CV_RGB(0, 0, 255));
418 if (valid_detected_imgs)
420 sqrErr /= CORNERS_COUNT * valid_detected_imgs;
421 std::cout <<
"Average err. of reprojection: " << sqrt(sqrErr)
422 <<
" pixels (OpenCV error=" << cv_calib_err <<
")\n";
424 if (out_MSE) *out_MSE = sqrt(sqrErr);
428 catch (
const std::exception& e)
430 std::cout << e.what() << std::endl;
434 THROW_EXCEPTION(
"Function not available: MRPT was compiled without OpenCV");
This class implements a config file-like interface over a memory-stored string list.
Shallow copy: the copied object is a reference to the original one.
#define THROW_EXCEPTION(msg)
std::map< std::string, TImageCalibData > TCalibrationImageList
A list of images, used in checkerBoardCameraCalibration.
cv::Mat & asCvMatRef()
Get a reference to the internal cv::Mat, which can be resized, etc.
size_t getHeight() const override
Returns the height of the image in pixels.
bool isExternallyStored() const noexcept
See setExternalStorage().
bool checkerBoardCameraCalibration(TCalibrationImageList &images, unsigned int check_size_x, unsigned int check_size_y, double check_squares_length_X_meters, double check_squares_length_Y_meters, mrpt::img::TCamera &out_camera_params, bool normalize_image=true, double *out_MSE=nullptr, bool skipDrawDetectedImgs=false, bool useScaramuzzaAlternativeDetector=false)
Performs a camera calibration (computation of projection and distortion parameters) from a sequence o...
void asCvMat(cv::Mat &out_img, copy_type_t copy_type) const
Makes a shallow or deep copy of this image into the provided cv::Mat.
T square(const T x)
Inline function for the square of a number.
CImage colorImage() const
Returns a color (RGB) version of the grayscale image, or a shallow copy of itself if it is already a ...
mrpt::math::CMatrixDouble33 intrinsicParams
Matrix of intrinsic parameters (containing the focal length and principal point coordinates) ...
#define ASSERT_(f)
Defines an assertion mechanism.
bool loadFromFile(const std::string &fileName, int isColor=-1)
Load image from a file, whose format is determined from the extension (internally uses OpenCV)...
mrpt::img::CImage img_checkboard
At output, this will contain the detected checkerboard overprinted to the image.
Data associated to each image in the calibration process mrpt::vision::checkerBoardCameraCalibration ...
This base provides a set of functions for maths stuff.
size_t getWidth() const override
Returns the width of the image in pixels.
auto block(int start_row, int start_col)
non-const block(): Returns an Eigen::Block reference to the block
bool findChessboardCorners(const mrpt::img::CImage &img, std::vector< mrpt::img::TPixelCoordf > &cornerCoords, unsigned int check_size_x, unsigned int check_size_y, bool normalize_image=true, bool useScaramuzzaMethod=false)
Look for the corners of a chessboard in the image using one of two different methods.
std::vector< mrpt::img::TPixelCoordf > detected_corners
At output, the detected corners (x,y) in pixel units.
Classes for computer vision, detectors, features, etc.
Structure to hold the parameters of a pinhole camera model.
std::string extractFileExtension(const std::string &filePath, bool ignore_gz=false)
Extract the extension of a filename.
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
void projectPoints_with_distortion(const std::vector< mrpt::math::TPoint3D > &in_points_3D, const mrpt::poses::CPose3D &cameraPose, const mrpt::math::CMatrixDouble33 &intrinsicParams, const std::vector< double > &distortionParams, std::vector< mrpt::img::TPixelCoordf > &projectedPoints, bool accept_points_behind=false)
Project a set of 3D points into a camera at an arbitrary 6D pose using its calibration matrix and dis...
std::array< double, 5 > dist
[k1 k2 t1 t2 k3] -> k_i: parameters of radial distortion, t_i: parameters of tangential distortion (d...
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
std::vector< mrpt::img::TPixelCoordf > projectedPoints_undistorted
At output, like projectedPoints_distorted but for the undistorted image.
GLdouble GLdouble GLdouble r
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
void saveToConfigFile(const std::string §ion, mrpt::config::CConfigFileBase &cfg) const
Save as a config block:
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
void getContent(std::string &str) const
Return the current contents of the virtual "config file".
void projectPoints_no_distortion(const std::vector< mrpt::math::TPoint3D > &in_points_3D, const mrpt::poses::CPose3D &cameraPose, const mrpt::math::CMatrixDouble33 &intrinsicParams, std::vector< mrpt::img::TPixelCoordf > &projectedPoints, bool accept_points_behind=false)
Project a set of 3D points into a camera at an arbitrary 6D pose using its calibration matrix (undist...
std::string extractFileName(const std::string &filePath)
Extract just the name (without extension) of a filename from a complete path plus name plus extension...
void undistort(CImage &out_img, const mrpt::img::TCamera &cameraParams) const
Undistort the image according to some camera parameters, and returns an output undistorted image...
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
mrpt::poses::CPose3D reconstructed_camera_pose
At output, the reconstructed pose of the camera.
std::vector< mrpt::img::TPixelCoordf > projectedPoints_distorted
At output, only will have an empty vector if the checkerboard was not found in this image...
uint32_t ncols
Camera resolution.
mrpt::img::CImage img_original
This image will be automatically loaded from the file name passed to checkerBoardCameraCalibration.
mrpt::img::CImage img_rectified
At output, this will be the rectified image.
A class for storing images as grayscale or RGB bitmaps.
std::vector< double > getDistortionParamsAsVector() const
Get a vector with the distortion params of the camera.
#define MRPT_UNUSED_PARAM(a)
Determines whether this is an X86 or AMD64 platform.