39 #include <visp3/core/vpConfig.h>
41 #if VISP_HAVE_OPENCV_VERSION >= 0x020300
43 #include <opencv2/core/core.hpp>
44 #include <opencv2/imgproc/imgproc.hpp>
45 #include <opencv2/calib3d/calib3d.hpp>
46 #include <opencv2/highgui/highgui.hpp>
48 #include <visp3/vision/vpCalibration.h>
50 #include <visp3/gui/vpDisplayX.h>
51 #include <visp3/gui/vpDisplayGDI.h>
52 #include <visp3/gui/vpDisplayOpenCV.h>
53 #include <visp3/gui/vpDisplayD3D.h>
54 #include <visp3/gui/vpDisplayGTK.h>
55 #include <visp3/core/vpIoTools.h>
56 #include <visp3/core/vpPoint.h>
57 #include <visp3/io/vpVideoReader.h>
58 #include <visp3/core/vpXmlParserCamera.h>
60 #ifndef DOXYGEN_SHOULD_SKIP_THIS
66 : boardSize(), calibrationPattern(UNDEFINED), squareSize(0.), input(), tempo(0.), goodInput(false), patternToUse()
68 boardSize = cv::Size(0, 0);
69 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) calibrationPattern = CHESSBOARD;
115 else if (patternToUse.compare(
"CIRCLES_GRID") == 0) calibrationPattern = CIRCLES_GRID;
116 if (calibrationPattern == UNDEFINED) {
117 std::cerr <<
" Inexistent camera calibration mode: " << patternToUse << std::endl;
124 Pattern calibrationPattern;
131 std::string patternToUse;
135 int main(
int argc,
const char ** argv)
138 std::string outputFileName =
"camera.xml";
141 const std::string inputSettingsFile = argc > 1 ? argv[1] :
"default.cfg";
142 if (! s.read(inputSettingsFile) ) {
143 std::cout <<
"Could not open the configuration file: \"" << inputSettingsFile <<
"\"" << std::endl;
144 std::cout << std::endl <<
"Usage: " << argv[0] <<
" <configuration file>.cfg" << std::endl;
150 std::cout <<
"Invalid input detected. Application stopping. " << std::endl;
162 #elif defined VISP_HAVE_GDI
164 #elif defined VISP_HAVE_GTK
166 #elif defined VISP_HAVE_OPENCV
170 std::vector<vpPoint> model;
171 std::vector<vpCalibration> calibrator;
173 for (
int i=0; i< s.boardSize.height; i++) {
174 for (
int j=0; j< s.boardSize.width; j++) {
175 model.push_back(
vpPoint(j*s.squareSize, i*s.squareSize, 0) );
180 while(! reader.
end()) {
186 std::vector<cv::Point2f> pointBuf;
190 switch( s.calibrationPattern )
192 case Settings::CHESSBOARD:
194 found = findChessboardCorners( cvI, s.boardSize, pointBuf,
195 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
196 cv::CALIB_CB_ADAPTIVE_THRESH | cv::CALIB_CB_FAST_CHECK | cv::CALIB_CB_NORMALIZE_IMAGE);
198 CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FAST_CHECK | CV_CALIB_CB_NORMALIZE_IMAGE);
201 case Settings::CIRCLES_GRID:
203 found = findCirclesGrid( cvI, s.boardSize, pointBuf, cv::CALIB_CB_SYMMETRIC_GRID );
205 case Settings::UNDEFINED:
207 std::cout <<
"Unkown calibration grid " << std::endl;
211 std::cout <<
"frame: " << frame_index <<
", status: " << found;
213 std::cout <<
", image rejected" << std::endl;
215 std::cout <<
", image used as input data" << std::endl;
219 std::vector<vpImagePoint> data;
221 if (s.calibrationPattern == Settings::CHESSBOARD) {
223 cornerSubPix( cvI, pointBuf, cv::Size(11,11),
225 #
if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
226 cv::TermCriteria( cv::TermCriteria::EPS+cv::TermCriteria::COUNT, 30, 0.1 ));
228 cv::TermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1 ));
231 char title[20]; sprintf(title,
"image %ld", frame_index);
233 for (
unsigned int i=0; i < pointBuf.size(); i++) {
243 for (
unsigned int i=0; i<model.size(); i++) {
244 calib.
addPoint(model[i].get_oX(), model[i].get_oY(), model[i].get_oZ(), data[i]);
258 calibrator.push_back(calib);
267 if (s.tempo > 10.f) {
280 if (calibrator.empty()) {
281 std::cerr <<
"Unable to calibrate. Image processing failed !" << std::endl;
285 std::stringstream ss_additional_info;
287 ss_additional_info <<
"<nb_calibration_images>" << calibrator.size() <<
"</nb_calibration_images>";
288 ss_additional_info <<
"<calibration_pattern_type>";
290 switch(s.calibrationPattern) {
291 case Settings::CHESSBOARD:
292 ss_additional_info <<
"Chessboard";
295 case Settings::CIRCLES_GRID:
296 ss_additional_info <<
"Circles grid";
299 case Settings::UNDEFINED:
301 ss_additional_info <<
"Undefined";
304 ss_additional_info <<
"</calibration_pattern_type>";
305 ss_additional_info <<
"<board_size>" << s.boardSize.width <<
"x" << s.boardSize.height <<
"</board_size>";
306 ss_additional_info <<
"<square_size>" << s.squareSize <<
"</square_size>";
308 std::cout <<
"\nCalibration without distortion in progress on " << calibrator.size() <<
" images..." << std::endl;
312 std::cout << cam << std::endl;
313 std::cout <<
"Global reprojection error: " << error << std::endl;
314 ss_additional_info <<
"<global_reprojection_error><without_distortion>" << error <<
"</without_distortion>";
316 #ifdef VISP_HAVE_XML2
320 std::cout <<
"Camera parameters without distortion successfully saved in \"" << outputFileName <<
"\"" << std::endl;
322 std::cout <<
"Failed to save the camera parameters without distortion in \"" << outputFileName <<
"\"" << std::endl;
323 std::cout <<
"A file with the same name exists. Remove it to be able to save the parameters..." << std::endl;
328 std::cout <<
"Calibration without distortion failed." << std::endl;
330 std::cout <<
"\nCalibration with distortion in progress on " << calibrator.size() <<
" images..." << std::endl;
332 std::cout << cam << std::endl;
333 std::cout <<
"Global reprojection error: " << error << std::endl;
334 ss_additional_info <<
"<with_distortion>" << error <<
"</with_distortion></global_reprojection_error>";
336 #ifdef VISP_HAVE_XML2
340 std::cout <<
"Camera parameters without distortion successfully saved in \"" << outputFileName <<
"\"" << std::endl;
342 std::cout <<
"Failed to save the camera parameters without distortion in \"" << outputFileName <<
"\"" << std::endl;
343 std::cout <<
"A file with the same name exists. Remove it to be able to save the parameters..." << std::endl;
346 std::cout << std::endl;
347 for (
unsigned int i=0; i<calibrator.size(); i++)
348 std::cout <<
"Estimated pose on input data " << i <<
": " <<
vpPoseVector(calibrator[i].cMo_dist).
t() << std::endl;
352 std::cout <<
"Calibration with distortion failed." << std::endl;
357 std::cout <<
"Catch an exception: " << e << std::endl;
364 std::cout <<
"OpenCV 2.3.0 or higher is requested to run the calibration." << std::endl;
VISP_EXPORT int wait(double t0, double t)
long getFrameIndex() const
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
unsigned int getWidth() const
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)
Implementation of a pose vector and operations on poses.
unsigned int getHeight() const
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)