![]() |
University of Murcia, Spain ![]() |
examples/OpenCV/cameraCalibrator/cameraCalibrator.cppGo to the documentation of this file.00001 /* 00002 * Copyright (C) 2007, 2008, 2009. PARP Research Group. 00003 * <http://perception.inf.um.es> 00004 * University of Murcia, Spain. 00005 * 00006 * This file is part of the QVision library. 00007 * 00008 * QVision is free software: you can redistribute it and/or modify 00009 * it under the terms of the GNU Lesser General Public License as 00010 * published by the Free Software Foundation, version 3 of the License. 00011 * 00012 * QVision is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with QVision. If not, see <http://www.gnu.org/licenses/>. 00019 */ 00020 00048 #include <iostream> 00049 #include <QVMatrix> 00050 #include <QVApplication> 00051 #include <QVImageCanvas> 00052 #include <QVMPlayerReaderBlock> 00053 #include <QVDefaultGUI> 00054 00055 #ifndef DOXYGEN_IGNORE_THIS 00056 #ifdef OPENCV 00057 #include <cv.h> 00058 #include <highgui.h> 00059 00060 /* *************** License:************************** 00061 Oct. 3, 2008 00062 Right to use this code in any way you want without warrenty, support or any guarentee of it working. 00063 00064 BOOK: It would be nice if you cited it: 00065 Learning OpenCV: Computer Vision with the OpenCV Library 00066 by Gary Bradski and Adrian Kaehler 00067 Published by O'Reilly Media, October 3, 2008 00068 00069 AVAILABLE AT: 00070 http://www.amazon.com/Learning-OpenCV-Computer-Vision-Library/dp/0596516134 00071 Or: http://oreilly.com/catalog/9780596516130/ 00072 ISBN-10: 0596516134 or: ISBN-13: 978-0596516130 00073 00074 OTHER OPENCV SITES: 00075 * The source code is on sourceforge at: 00076 http://sourceforge.net/projects/opencvlibrary/ 00077 * The OpenCV wiki page (As of Oct 1, 2008 this is down for changing over servers, but should come back): 00078 http://opencvlibrary.sourceforge.net/ 00079 * An active user group is at: 00080 http://tech.groups.yahoo.com/group/OpenCV/ 00081 * The minutes of weekly OpenCV development meetings are at: 00082 http://pr.willowgarage.com/wiki/OpenCV 00083 ************************************************** */ 00084 00085 /*void help() 00086 { 00087 std::cout << "\n\n" 00088 " Calling convention:\n" 00089 " ./cameraCalibratorOpenCV <board_w> <board_h> <number_of_boards> <skip_frames>\n" 00090 "\n" 00091 " WHERE:\n" 00092 " board_w, board_h -- are the number of corners along the row and columns respectively\n" 00093 " number_of_boards -- are the number of chessboard views to collect before calibration\n" 00094 " skip_frames -- are the number of frames to skip before trying to collect another\n" 00095 " good chessboard. This allows you time to move the chessboard. \n" 00096 " Move it to many different locations and angles so that calibration \n" 00097 " space will be well covered. \n" 00098 "\n" 00099 " Hit ‘p’ to pause/unpause, ESC to quit\n" 00100 "\n"; 00101 }*/ 00102 00103 class CameraCalibratorBlock: public QVProcessingBlock 00104 { 00105 private: 00106 QVImage<uChar, 3> actualImage; 00107 00108 const int board_w, board_h, n_boards, board_dt, board_n; 00109 const CvSize board_sz; 00110 CvSize image_sz; 00111 00112 CvMat* image_points; 00113 CvMat* object_points; 00114 CvMat* point_counts; 00115 00116 CvPoint2D32f* corners; 00117 int successes;//, corner_count, step;//, frame; 00118 00119 public: 00120 CameraCalibratorBlock(QString name): QVProcessingBlock(name), 00121 board_w(6), board_h(9), n_boards(10), board_dt(25), board_n(board_w * board_h), 00122 board_sz(cvSize( board_w, board_h )), image_points(cvCreateMat(n_boards*board_n,2,CV_32FC1)), 00123 object_points(cvCreateMat(n_boards*board_n,3,CV_32FC1)), point_counts(cvCreateMat(n_boards,1,CV_32SC1)), 00124 corners(new CvPoint2D32f[ board_n ]), successes(0)//, frame(0) 00125 { 00126 addProperty< QVImage<uChar,3> >("Input image", inputFlag|outputFlag); 00127 addTrigger("Grab chessboard"); 00128 addTrigger("Calibrate"); 00129 } 00130 00131 void processTrigger(const QString triggerName) 00132 { 00133 if (triggerName == "Grab chessboard") 00134 { 00135 if (successes >= n_boards) 00136 { 00137 std::cout << "Already got "<< n_boards << " boards" << std::endl; 00138 return; 00139 } 00140 00141 std::cout << "Capturing image" << std::endl; 00142 IplImage *image = actualImage; 00143 IplImage *gray_image = cvCreateImage(cvGetSize(image), 8, 1); //subpixel 00144 00145 image_sz = cvGetSize(image); 00146 00147 int corner_count, found = cvFindChessboardCorners( 00148 image, board_sz, corners, &corner_count, 00149 CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FILTER_QUADS); 00150 00151 //Get Subpixel accuracy on those corners 00152 cvCvtColor(image, gray_image, CV_BGR2GRAY); 00153 cvFindCornerSubPix( gray_image, corners, corner_count, cvSize(11,11),cvSize(-1,-1), 00154 cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1)); 00155 00156 if(corner_count == board_n) 00157 { 00158 //cvShowImage( "Calibration", image ); //show in color if we did collect the image 00159 int step = successes*board_n; 00160 for( int i=step, j=0; j<board_n; ++i,++j ) 00161 { 00162 CV_MAT_ELEM(*image_points, float,i,0) = corners[j].x; 00163 CV_MAT_ELEM(*image_points, float,i,1) = corners[j].y; 00164 CV_MAT_ELEM(*object_points,float,i,0) = j/board_w; 00165 CV_MAT_ELEM(*object_points,float,i,1) = j%board_w; 00166 CV_MAT_ELEM(*object_points,float,i,2) = 0.0f; 00167 } 00168 CV_MAT_ELEM(*point_counts, int,successes,0) = board_n; 00169 successes++; 00170 std::cout << "Got board # " << successes << " of " << n_boards << " required" << std::endl; 00171 } 00172 cvReleaseImage(&image); 00173 cvReleaseImage(&gray_image); 00174 } 00175 else if (triggerName == "Calibrate") 00176 { 00177 if (successes < n_boards) 00178 { 00179 std::cout << "Not enough boards" << std::endl; 00180 return; 00181 } 00182 std::cout << "Proceeding to camera calibration." << std::endl; 00183 CvMat* object_points2 = cvCreateMat(successes*board_n,3,CV_32FC1); 00184 CvMat* image_points2 = cvCreateMat(successes*board_n,2,CV_32FC1); 00185 CvMat* point_counts2 = cvCreateMat(successes,1,CV_32SC1); 00186 00187 //TRANSFER THE POINTS INTO THE CORRECT SIZE MATRICES 00188 for(int i = 0; i<successes*board_n; ++i) 00189 { 00190 CV_MAT_ELEM( *image_points2, float, i, 0) = CV_MAT_ELEM( *image_points, float, i, 0); 00191 CV_MAT_ELEM( *image_points2, float,i,1) = CV_MAT_ELEM( *image_points, float, i, 1); 00192 CV_MAT_ELEM(*object_points2, float, i, 0) = CV_MAT_ELEM( *object_points, float, i, 0) ; 00193 CV_MAT_ELEM( *object_points2, float, i, 1) = CV_MAT_ELEM( *object_points, float, i, 1) ; 00194 CV_MAT_ELEM( *object_points2, float, i, 2) = CV_MAT_ELEM( *object_points, float, i, 2) ; 00195 } 00196 00197 for(int i=0; i<successes; ++i) 00198 //These are all the same number 00199 CV_MAT_ELEM( *point_counts2, int, i, 0) = CV_MAT_ELEM( *point_counts, int, i, 0); 00200 00201 CvMat* intrinsic_matrix = cvCreateMat(3,3,CV_32FC1); 00202 CvMat* distortion_coeffs = cvCreateMat(4,1,CV_32FC1); 00203 00204 CV_MAT_ELEM( *intrinsic_matrix, float, 0, 0 ) = 1.0f; 00205 CV_MAT_ELEM( *intrinsic_matrix, float, 1, 1 ) = 1.0f; 00206 00207 cvCalibrateCamera2(object_points2, image_points2, point_counts2, image_sz, intrinsic_matrix, distortion_coeffs, NULL, NULL,0); 00208 00209 std::cout << "Intrinsic Matrix K = " << std::endl << QVMatrix(intrinsic_matrix) << std::endl; 00210 std::cout << "Distortion coefficents = " << std::endl << QVMatrix(distortion_coeffs) << std::endl; 00211 00212 cvReleaseMat(&object_points2); 00213 cvReleaseMat(&image_points2); 00214 cvReleaseMat(&point_counts2); 00215 cvReleaseMat(&intrinsic_matrix); 00216 cvReleaseMat(&distortion_coeffs); 00217 } 00218 } 00219 00220 void iterate() 00221 { 00222 actualImage = getPropertyValue<QVImage<uChar, 3> >("Input image"); 00223 } 00224 }; 00225 00226 #include <QVVector> 00227 #include <QVMatrix> 00228 int main(int argc, char *argv[]) 00229 { 00230 QVApplication app(argc, argv, "Example program for QVision library. Displays the contents of a video source."); 00231 00232 QVMPlayerReaderBlock camera("Video"); 00233 00234 CameraCalibratorBlock player("Video player"); 00235 camera.linkProperty(&player,"Input image"); 00236 00237 QVDefaultGUI interface; 00238 00239 QVImageCanvas imageCanvas("Output image"); 00240 player.linkProperty("Input image", imageCanvas); 00241 00242 return app.exec(); 00243 } 00244 00245 /*int main(int argc, char* argv[]) 00246 { 00247 exit(0); 00248 CvCapture* capture; 00249 00250 if(argc != 5) 00251 { 00252 std::cout << std::endl << "ERROR: Wrong number of input parameters" << std::endl; 00253 help(); 00254 return -1; 00255 } 00256 00257 const int board_w = 6, 00258 board_h = 9, 00259 n_boards = 10, 00260 board_dt = 25, 00261 board_n = board_w * board_h; 00262 00263 CvSize board_sz = cvSize( board_w, board_h ); 00264 00266 capture = cvCreateCameraCapture( 0 ); 00267 if(!capture) 00268 { 00269 std::cout << std::endl << "Couldn't open the camera" << std::endl; 00270 help(); 00271 return -1; 00272 } 00273 00274 cvNamedWindow("Calibration"); 00275 cvNamedWindow("Raw Video"); 00277 00278 //ALLOCATE STORAGE 00279 CvMat* image_points = cvCreateMat(n_boards*board_n,2,CV_32FC1); 00280 CvMat* object_points = cvCreateMat(n_boards*board_n,3,CV_32FC1); 00281 CvMat* point_counts = cvCreateMat(n_boards,1,CV_32SC1); 00282 00283 CvPoint2D32f* corners = new CvPoint2D32f[ board_n ]; 00284 int corner_count, successes = 0, step, frame = 0; 00285 IplImage *image = cvQueryFrame( capture ); 00286 IplImage *gray_image = cvCreateImage(cvGetSize(image), 8, 1); //subpixel 00287 00288 // CAPTURE CORNER VIEWS LOOP UNTIL WE’VE GOT n_boards 00289 // SUCCESSFUL CAPTURES (ALL CORNERS ON THE BOARD ARE FOUND) 00290 // 00291 help(); 00292 00293 while(successes < n_boards) 00294 { 00295 //Skip every board_dt frames to allow user to move chessboard 00296 if((frame++ % board_dt) == 0) 00297 { 00298 //Find chessboard corners: 00299 int found = cvFindChessboardCorners( image, board_sz, corners, &corner_count, 00300 CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FILTER_QUADS); 00301 00302 //Get Subpixel accuracy on those corners 00303 cvCvtColor(image, gray_image, CV_BGR2GRAY); 00304 cvFindCornerSubPix( gray_image, corners, corner_count, cvSize(11,11),cvSize(-1,-1), 00305 cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1)); 00306 00307 //Draw it 00308 cvDrawChessboardCorners(image, board_sz, corners, corner_count, found); 00309 00310 // If we got a good board, add it to our data 00311 if(corner_count == board_n) 00312 { 00313 cvShowImage( "Calibration", image ); //show in color if we did collect the image 00314 step = successes*board_n; 00315 for( int i=step, j=0; j<board_n; ++i,++j ) 00316 { 00317 CV_MAT_ELEM(*image_points, float,i,0) = corners[j].x; 00318 CV_MAT_ELEM(*image_points, float,i,1) = corners[j].y; 00319 CV_MAT_ELEM(*object_points,float,i,0) = j/board_w; 00320 CV_MAT_ELEM(*object_points,float,i,1) = j%board_w; 00321 CV_MAT_ELEM(*object_points,float,i,2) = 0.0f; 00322 } 00323 CV_MAT_ELEM(*point_counts, int,successes,0) = board_n; 00324 successes++; 00325 std::cout << "Collected our " << successes << " of " << n_boards << " needed chessboard images" << std::endl; 00326 } 00327 else 00328 cvShowImage("Calibration", gray_image); //Show Gray if we didn't collect the image 00329 } //end skip board_dt between chessboard capture 00330 00331 //Handle pause/unpause and ESC 00332 int c = cvWaitKey(15); 00333 if(c == 'p') 00334 { 00335 c = 0; 00336 while(c != 'p' && c != 27) 00337 c = cvWaitKey(250); 00338 } 00339 00340 if(c == 27) 00341 return 0; 00342 00343 image = cvQueryFrame( capture ); //Get next image 00344 cvShowImage("Raw Video", image); 00345 } //END COLLECTION WHILE LOOP. 00346 00347 cvDestroyWindow("Calibration"); 00348 std::cout << "\n\n*** CALLIBRATING THE CAMERA..." << std::endl; 00349 00350 //ALLOCATE MATRICES ACCORDING TO HOW MANY CHESSBOARDS FOUND 00351 CvMat* object_points2 = cvCreateMat(successes*board_n,3,CV_32FC1); 00352 CvMat* image_points2 = cvCreateMat(successes*board_n,2,CV_32FC1); 00353 CvMat* point_counts2 = cvCreateMat(successes,1,CV_32SC1); 00354 00355 //TRANSFER THE POINTS INTO THE CORRECT SIZE MATRICES 00356 for(int i = 0; i<successes*board_n; ++i) 00357 { 00358 CV_MAT_ELEM( *image_points2, float, i, 0) = CV_MAT_ELEM( *image_points, float, i, 0); 00359 CV_MAT_ELEM( *image_points2, float,i,1) = CV_MAT_ELEM( *image_points, float, i, 1); 00360 CV_MAT_ELEM(*object_points2, float, i, 0) = CV_MAT_ELEM( *object_points, float, i, 0) ; 00361 CV_MAT_ELEM( *object_points2, float, i, 1) = CV_MAT_ELEM( *object_points, float, i, 1) ; 00362 CV_MAT_ELEM( *object_points2, float, i, 2) = CV_MAT_ELEM( *object_points, float, i, 2) ; 00363 } 00364 00365 for(int i=0; i<successes; ++i) 00366 //These are all the same number 00367 CV_MAT_ELEM( *point_counts2, int, i, 0) = CV_MAT_ELEM( *point_counts, int, i, 0); 00368 00369 cvReleaseMat(&object_points); 00370 cvReleaseMat(&image_points); 00371 cvReleaseMat(&point_counts); 00372 00373 // At this point we have all of the chessboard corners we need. 00374 // Initialize the intrinsic matrix such that the two focal 00375 // lengths have a ratio of 1.0 00376 CvMat* intrinsic_matrix = cvCreateMat(3,3,CV_32FC1); 00377 CvMat* distortion_coeffs = cvCreateMat(4,1,CV_32FC1); 00378 00379 CV_MAT_ELEM( *intrinsic_matrix, float, 0, 0 ) = 1.0f; 00380 CV_MAT_ELEM( *intrinsic_matrix, float, 1, 1 ) = 1.0f; 00381 00382 //CALIBRATE THE CAMERA! 00383 cvCalibrateCamera2(object_points2, image_points2, point_counts2, cvGetSize( image ), intrinsic_matrix, distortion_coeffs, NULL, NULL,0); 00384 00385 // SAVE THE INTRINSICS AND DISTORTIONS 00386 std::cout << " *** DONE!" << std::endl << std::endl << "Storing Intrinsics.xml and Distortions.xml files" << std::endl << std::endl; 00387 00388 //std::cout << "Intrinsic Matrix K = " << std::endl << CvMatToQVMatrix(intrinsic_matrix) << std::endl; 00389 std::cout << "Intrinsic Matrix K = " << std::endl << QVMatrix(intrinsic_matrix) << std::endl; 00390 //std::cout << "Distortion coefficents = " << std::endl << CvMatToQVMatrix(distortion_coeffs) << std::endl; 00391 std::cout << "Distortion coefficents = " << std::endl << QVMatrix(distortion_coeffs) << std::endl; 00392 00393 return 0; 00394 }*/ 00395 #else // not OPENCV 00396 int main(int argc, char* argv[]) 00397 { 00398 std::cout << "ERROR: OpenCV compatibility was not activated in QVision compilation." << std::endl; 00399 return -1; 00400 } 00401 #endif // OPENCV 00402 #endif // DOXYGEN_IGNORE_THIS 00403 |