40 #include <visp3/core/vpConfig.h> 42 #if VISP_HAVE_OPENCV_VERSION >= 0x020300 44 #include <opencv2/calib3d/calib3d.hpp> 45 #include <opencv2/core/core.hpp> 46 #include <opencv2/highgui/highgui.hpp> 47 #include <opencv2/imgproc/imgproc.hpp> 49 #include <visp3/vision/vpCalibration.h> 51 #include <visp3/core/vpIoTools.h> 52 #include <visp3/core/vpPoint.h> 53 #include <visp3/core/vpXmlParserCamera.h> 54 #include <visp3/gui/vpDisplayD3D.h> 55 #include <visp3/gui/vpDisplayGDI.h> 56 #include <visp3/gui/vpDisplayGTK.h> 57 #include <visp3/gui/vpDisplayOpenCV.h> 58 #include <visp3/gui/vpDisplayX.h> 59 #include <visp3/io/vpVideoReader.h> 61 #ifndef DOXYGEN_SHOULD_SKIP_THIS 67 : boardSize(), calibrationPattern(UNDEFINED), squareSize(0.), input(), tempo(0.), goodInput(false), patternToUse()
69 boardSize = cv::Size(0, 0);
70 calibrationPattern = UNDEFINED;
75 enum Pattern { UNDEFINED, CHESSBOARD, CIRCLES_GRID };
77 bool read(
const std::string &filename)
89 std::cout <<
"grid width : " << boardSize.width << std::endl;
90 std::cout <<
"grid height: " << boardSize.height << std::endl;
91 std::cout <<
"square size: " << squareSize << std::endl;
92 std::cout <<
"pattern : " << patternToUse << std::endl;
93 std::cout <<
"input seq : " << input << std::endl;
94 std::cout <<
"tempo : " << tempo << std::endl;
101 if (boardSize.width <= 0 || boardSize.height <= 0) {
102 std::cerr <<
"Invalid Board size: " << boardSize.width <<
" " << boardSize.height << std::endl;
105 if (squareSize <= 10e-6) {
106 std::cerr <<
"Invalid square size " << squareSize << std::endl;
113 calibrationPattern = UNDEFINED;
114 if (patternToUse.compare(
"CHESSBOARD") == 0)
115 calibrationPattern = CHESSBOARD;
116 else if (patternToUse.compare(
"CIRCLES_GRID") == 0)
117 calibrationPattern = CIRCLES_GRID;
118 if (calibrationPattern == UNDEFINED) {
119 std::cerr <<
" Inexistent camera calibration mode: " << patternToUse << std::endl;
127 Pattern calibrationPattern;
137 std::string patternToUse;
141 int main(
int argc,
const char **argv)
144 std::string outputFileName =
"camera.xml";
147 const std::string inputSettingsFile = argc > 1 ? argv[1] :
"default.cfg";
148 if (!s.read(inputSettingsFile)) {
149 std::cout <<
"Could not open the configuration file: \"" << inputSettingsFile <<
"\"" << std::endl;
150 std::cout << std::endl <<
"Usage: " << argv[0] <<
" <configuration file>.cfg" << std::endl;
155 std::cout <<
"Invalid input detected. Application stopping. " << std::endl;
167 #elif defined VISP_HAVE_GDI 169 #elif defined VISP_HAVE_GTK 171 #elif defined VISP_HAVE_OPENCV 175 std::vector<vpPoint> model;
176 std::vector<vpCalibration> calibrator;
178 for (
int i = 0; i < s.boardSize.height; i++) {
179 for (
int j = 0; j < s.boardSize.width; j++) {
180 model.push_back(
vpPoint(j * s.squareSize, i * s.squareSize, 0));
184 while (!reader.
end()) {
190 std::vector<cv::Point2f> pointBuf;
194 switch (s.calibrationPattern)
196 case Settings::CHESSBOARD:
198 found = findChessboardCorners(cvI, s.boardSize, pointBuf,
199 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
200 cv::CALIB_CB_ADAPTIVE_THRESH | cv::CALIB_CB_FAST_CHECK |
201 cv::CALIB_CB_NORMALIZE_IMAGE);
203 CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FAST_CHECK |
204 CV_CALIB_CB_NORMALIZE_IMAGE);
207 case Settings::CIRCLES_GRID:
209 found = findCirclesGrid(cvI, s.boardSize, pointBuf, cv::CALIB_CB_SYMMETRIC_GRID);
211 case Settings::UNDEFINED:
213 std::cout <<
"Unkown calibration grid " << std::endl;
217 std::cout <<
"frame: " << frame_index <<
", status: " << found;
219 std::cout <<
", image rejected" << std::endl;
221 std::cout <<
", image used as input data" << std::endl;
225 std::vector<vpImagePoint> data;
227 if (s.calibrationPattern == Settings::CHESSBOARD) {
229 cornerSubPix(cvI, pointBuf, cv::Size(11, 11), cv::Size(-1, -1),
230 #
if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
231 cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 30, 0.1));
233 cv::TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));
236 std::stringstream ss;
237 ss <<
"image " << frame_index;
239 for (
unsigned int i = 0; i < pointBuf.size(); i++) {
249 for (
unsigned int i = 0; i < model.size(); i++) {
250 calib.
addPoint(model[i].get_oX(), model[i].get_oY(), model[i].get_oZ(), data[i]);
264 calibrator.push_back(calib);
273 if (s.tempo > 10.f) {
285 if (calibrator.empty()) {
286 std::cerr <<
"Unable to calibrate. Image processing failed !" << std::endl;
290 std::stringstream ss_additional_info;
292 ss_additional_info <<
"<nb_calibration_images>" << calibrator.size() <<
"</nb_calibration_images>";
293 ss_additional_info <<
"<calibration_pattern_type>";
295 switch (s.calibrationPattern) {
296 case Settings::CHESSBOARD:
297 ss_additional_info <<
"Chessboard";
300 case Settings::CIRCLES_GRID:
301 ss_additional_info <<
"Circles grid";
304 case Settings::UNDEFINED:
306 ss_additional_info <<
"Undefined";
309 ss_additional_info <<
"</calibration_pattern_type>";
310 ss_additional_info <<
"<board_size>" << s.boardSize.width <<
"x" << s.boardSize.height <<
"</board_size>";
311 ss_additional_info <<
"<square_size>" << s.squareSize <<
"</square_size>";
313 std::cout <<
"\nCalibration without distortion in progress on " << calibrator.size() <<
" images..." << std::endl;
317 std::cout << cam << std::endl;
318 std::cout <<
"Global reprojection error: " << error << std::endl;
319 ss_additional_info <<
"<global_reprojection_error><without_distortion>" << error <<
"</without_distortion>";
321 #ifdef VISP_HAVE_XML2 326 std::cout <<
"Camera parameters without distortion successfully saved in \"" << outputFileName <<
"\"" 329 std::cout <<
"Failed to save the camera parameters without distortion in \"" << outputFileName <<
"\"" 331 std::cout <<
"A file with the same name exists. Remove it to be able " 332 "to save the parameters..." 337 std::cout <<
"Calibration without distortion failed." << std::endl;
339 std::cout <<
"\nCalibration with distortion in progress on " << calibrator.size() <<
" images..." << std::endl;
342 std::cout << cam << std::endl;
343 std::cout <<
"Global reprojection error: " << error << std::endl;
344 ss_additional_info <<
"<with_distortion>" << error <<
"</with_distortion></global_reprojection_error>";
346 #ifdef VISP_HAVE_XML2 349 if (xml.
save(cam, outputFileName.c_str(),
"Camera", I.
getWidth(), I.
getHeight(), ss_additional_info.str()) ==
351 std::cout <<
"Camera parameters without distortion successfully saved in \"" << outputFileName <<
"\"" 354 std::cout <<
"Failed to save the camera parameters without distortion in \"" << outputFileName <<
"\"" 356 std::cout <<
"A file with the same name exists. Remove it to be able " 357 "to save the parameters..." 361 std::cout << std::endl;
362 for (
unsigned int i = 0; i < calibrator.size(); i++)
363 std::cout <<
"Estimated pose on input data " << i <<
": " <<
vpPoseVector(calibrator[i].cMo_dist).
t()
367 std::cout <<
"Calibration with distortion failed." << std::endl;
371 std::cout <<
"Catch an exception: " << e << std::endl;
376 int main() { std::cout <<
"OpenCV 2.3.0 or higher is requested to run the calibration." << std::endl; }
VISP_EXPORT int wait(double t0, double t)
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
int computeCalibration(vpCalibrationMethodType method, vpHomogeneousMatrix &cMo_est, vpCameraParameters &cam_est, bool verbose=false)
Implementation of an homogeneous matrix and operations on such kind of matrices.
Display for windows using GDI (available on any windows 32 platform).
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Class that enables to manipulate easily a video file or a sequence of images. As it inherits from the...
error that can be emited by ViSP classes.
int addPoint(double X, double Y, double Z, vpImagePoint &ip)
Tools for perspective camera calibration.
XML parser to load and save intrinsic camera parameters.
static const vpColor green
static void flush(const vpImage< unsigned char > &I)
VISP_EXPORT std::string getDateTime(const std::string &format="%Y/%m/%d %H:%M:%S")
Class that defines what is a point.
static void setLambda(const double &lambda)
set the gain for the virtual visual servoing algorithm
void initPersProjWithoutDistortion(const double px, const double py, const double u0, const double v0)
void open(vpImage< vpRGBa > &I)
int clearPoint()
Suppress all the point in the array of point.
static void display(const vpImage< unsigned char > &I)
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
Generic class defining intrinsic camera parameters.
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
void acquire(vpImage< vpRGBa > &I)
void setFileName(const char *filename)
static void displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
long getFrameIndex() const
unsigned int getHeight() const
Implementation of a pose vector and operations on poses.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
int save(const vpCameraParameters &cam, const std::string &filename, const std::string &camera_name, const unsigned int image_width=0, const unsigned int image_height=0, const std::string &additionalInfo="")
static int computeCalibrationMulti(vpCalibrationMethodType method, std::vector< vpCalibration > &table_cal, vpCameraParameters &cam, double &globalReprojectionError, bool verbose=false)
static void setTitle(const vpImage< unsigned char > &I, const std::string &windowtitle)
unsigned int getWidth() const