PageRenderTime 109ms CodeModel.GetById 71ms RepoModel.GetById 0ms app.codeStats 0ms

/src/calibrate.cc

https://github.com/vbajpai/cameracalibration
C++ | 294 lines | 202 code | 61 blank | 31 comment | 24 complexity | 2effb3e1ced5fa0c527b07e5ff73d77e MD5 | raw file
  1. /* Camera Calibration - Vaibhav Bajpai */
  2. #include <opencv2/opencv.hpp>
  3. #include <iostream>
  4. #include <iomanip>
  5. #include <vector>
  6. #include <cstdlib>
  7. #include <stdio.h>
  8. #define HEIGHT 4
  9. #define WIDTH 6
  10. using namespace std;
  11. class CalibrateCamera{
  12. private:
  13. int width, height, numberOfCorners, cvFindCornerCount, numberOfImages, numberOfSuccessfulImages;
  14. CvPoint2D32f* corners;
  15. IplImage *img, *dest;
  16. string filename;
  17. vector<string> imageList;
  18. CvMat* objectPointsOld, *imagePointsOld, *pointCountsOld;
  19. CvMat* objectPointsNew, *imagePointsNew, *pointCountsNew;
  20. CvMat* cameraMatrix, *distCoeffs, *rvecs, *tvecs;
  21. void liveCapture(){
  22. cout << endl << endl << "initializing camera ...";
  23. /* initialize capture source */
  24. cvNamedWindow("Webcam", CV_WINDOW_AUTOSIZE);
  25. CvCapture* capture = cvCaptureFromCAM(0);
  26. cout << "[done]" << endl << endl << "looking for chessboard corners ...";
  27. do{
  28. /* grab and copy the frame to buffer */
  29. img = cvQueryFrame(capture);
  30. dest = cvCloneImage(img);
  31. /* search and draw chessboard corners */
  32. int ifFound = cvFindChessboardCorners(img, cvSize(width,height), corners, &cvFindCornerCount);
  33. cvDrawChessboardCorners(img, cvSize(width, height), corners, cvFindCornerCount, ifFound);
  34. cvShowImage("Webcam", img);
  35. cvWaitKey(10);
  36. if(cvFindCornerCount == numberOfCorners){
  37. cout << endl << endl << "capturing ...";
  38. /* save the image from buffer to a file */
  39. time_t rawtime;
  40. struct tm * timeinfo;
  41. /* generate unique filename using current time */
  42. time ( &rawtime );
  43. timeinfo = localtime ( &rawtime );
  44. string filename = string(asctime(timeinfo)).substr(11, 8);
  45. char iter[1];
  46. sprintf(iter, "%d", numberOfSuccessfulImages);
  47. filename.append(iter);
  48. filename.append(".jpg");
  49. if (!cvSaveImage(filename.c_str(), dest)) {
  50. cout << "Could not save image" << endl;
  51. exit(1);
  52. }
  53. /* push the filename to a vector */
  54. imageList.push_back(filename);
  55. cout << "[done]" << endl << "saving as " << filename << "..."<< "[done]";
  56. numberOfSuccessfulImages++;
  57. }
  58. }while(numberOfSuccessfulImages < 10);
  59. /* release capture source */
  60. numberOfSuccessfulImages = 0;
  61. cvDestroyWindow("Webcam");
  62. cvReleaseCapture(&capture);
  63. }
  64. void allocateMatrixObjects(){
  65. objectPointsOld = cvCreateMat(numberOfCorners * numberOfImages, 3, CV_32FC1 );
  66. imagePointsOld = cvCreateMat(numberOfCorners * numberOfImages, 2, CV_32FC1 );
  67. pointCountsOld = cvCreateMat(numberOfImages, 1, CV_32SC1 );
  68. cameraMatrix = cvCreateMat( 3, 3, CV_32FC1 );
  69. distCoeffs = cvCreateMat( 5, 1, CV_32FC1 );
  70. }
  71. void findChessboardCorner(){
  72. for (int imageIndex=0; imageIndex<numberOfImages; imageIndex++) {
  73. /* load the image from filename */
  74. filename = imageList[imageIndex];
  75. img = cvLoadImage(filename.c_str(), CV_LOAD_IMAGE_UNCHANGED);
  76. /* search chessboard corners */
  77. int ifFound = cvFindChessboardCorners(img, cvSize(width, height), corners, &cvFindCornerCount);
  78. if(ifFound)
  79. cout << "[filename:"<< filename << "]" << "[corners:" << cvFindCornerCount << "]"<< endl;
  80. else
  81. cout << "[filename:"<< filename << "]" << "[corners: 0]" << endl;
  82. /* fill structures */
  83. if(cvFindCornerCount == numberOfCorners){
  84. CV_MAT_ELEM(*pointCountsOld, int, numberOfSuccessfulImages, 0) = numberOfCorners;
  85. int step = numberOfSuccessfulImages*numberOfCorners;
  86. for( int i=step, j=0; j < numberOfCorners; ++i, ++j ){
  87. CV_MAT_ELEM( *imagePointsOld, float, i, 0 ) = corners[j].x;
  88. CV_MAT_ELEM( *imagePointsOld, float, i, 1 ) = corners[j].y;
  89. CV_MAT_ELEM( *objectPointsOld, float, i, 0 ) = j/width;
  90. CV_MAT_ELEM( *objectPointsOld, float, i, 1 ) = j%width;
  91. CV_MAT_ELEM( *objectPointsOld, float, i, 2 ) = 0.0f;
  92. }
  93. numberOfSuccessfulImages++;
  94. }
  95. }
  96. }
  97. void calibrateCamera(){
  98. if (numberOfSuccessfulImages != 0){
  99. /* reallocate the matrix objects */
  100. objectPointsNew = cvCreateMat(numberOfSuccessfulImages*numberOfCorners, 3, CV_32FC1 );
  101. imagePointsNew = cvCreateMat(numberOfSuccessfulImages*numberOfCorners, 2, CV_32FC1 );
  102. pointCountsNew = cvCreateMat(numberOfSuccessfulImages, 1, CV_32SC1 );
  103. reAllocateMatrixObjects();
  104. /* calibrate the camera */
  105. rvecs = cvCreateMat(numberOfSuccessfulImages, 3, CV_32FC1);
  106. tvecs = cvCreateMat(numberOfSuccessfulImages, 3, CV_32FC1);
  107. cout << endl << endl << "running cvCalibrateCamera2() ..." << endl << endl;
  108. cvCalibrateCamera2(objectPointsNew, imagePointsNew, pointCountsNew, cvGetSize(img), cameraMatrix, distCoeffs, rvecs, tvecs);
  109. /* print intrinsic | extrinsic parameters */
  110. printParameters();
  111. /* undistort image */
  112. img = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
  113. dest = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
  114. cvUndistort2(img, dest, cameraMatrix, distCoeffs);
  115. cvDrawChessboardCorners(dest, cvSize(WIDTH,HEIGHT), corners,
  116. numberOfCorners, cvFindChessboardCorners(dest, cvSize(WIDTH,HEIGHT), corners, &cvFindCornerCount));
  117. /* show the undistort image */
  118. cvNamedWindow("Undistorted Image", CV_WINDOW_AUTOSIZE);
  119. cvShowImage("Undistorted Image",dest);
  120. cout << endl << endl << "press enter to save the image...";
  121. cin.get();
  122. cvDestroyWindow("Undistorted Image");
  123. /* save the undistort image */
  124. string filename = "undistorted_grab.jpg";
  125. cvSaveImage(filename.c_str(), dest);
  126. cout << endl <<endl << "saving undistorted copy as..." << filename << " [done]" << endl << endl;
  127. }else{
  128. cout << endl << endl << "cannot calibrate the camera" << endl << endl;
  129. }
  130. }
  131. void reAllocateMatrixObjects(){
  132. // transfer to new matrix
  133. for( int i = 0; i < numberOfSuccessfulImages*numberOfCorners; ++i ){
  134. CV_MAT_ELEM( *imagePointsNew, float, i, 0) = cvmGet(imagePointsOld, i, 0);
  135. CV_MAT_ELEM( *imagePointsNew, float, i, 1) = cvmGet(imagePointsOld, i, 1);
  136. CV_MAT_ELEM( *objectPointsNew, float, i, 0) = cvmGet(objectPointsOld, i, 0);
  137. CV_MAT_ELEM( *objectPointsNew, float, i, 1) = cvmGet(objectPointsOld, i, 1);
  138. CV_MAT_ELEM( *objectPointsNew, float, i, 2) = cvmGet(objectPointsOld, i, 2);
  139. }
  140. for( int i=0; i < numberOfSuccessfulImages; ++i ){
  141. CV_MAT_ELEM(*pointCountsNew, int, i, 0) = CV_MAT_ELEM(*pointCountsOld, int, i, 0);
  142. }
  143. /* release old matrix objects */
  144. cvReleaseMat(&imagePointsOld);
  145. cvReleaseMat(&objectPointsOld);
  146. cvReleaseMat(&pointCountsOld);
  147. }
  148. void printParameters(){
  149. // print distortion matrix
  150. if (distCoeffs){
  151. cout << "radial-distoration k1: " << cvmGet(distCoeffs, 0, 0) << endl;
  152. cout << "radial-distoration k2: " << cvmGet(distCoeffs, 1, 0) << endl << endl;
  153. cout << "tangential-distoration p1: " << cvmGet(distCoeffs, 2, 0) << endl;
  154. cout << "tangential-distoration p2: " << cvmGet(distCoeffs, 3, 0) << endl << endl;
  155. }
  156. // print camera matrix
  157. if (cameraMatrix){
  158. cout << "optical-center cx: " << cvmGet(cameraMatrix, 0, 2) << endl;
  159. cout << "optical-center cy: " << cvmGet(cameraMatrix, 1, 2) << endl << endl;
  160. cout << "focal-length fx: " << cvmGet(cameraMatrix, 0, 0) << endl;
  161. cout << "focal-length fy: " << cvmGet(cameraMatrix, 1, 1) << endl << endl;
  162. }
  163. // print translation matrix
  164. if (tvecs){
  165. cout << "translation matrix - " << endl << endl;
  166. for (int j = 0; j < numberOfSuccessfulImages; j++){
  167. for (int i = 0; i < 3; i++){
  168. if(i!=0)
  169. cout << setw(20);
  170. cout << cvmGet(tvecs, j, i);
  171. }
  172. cout << endl;
  173. }
  174. }
  175. // print rotation matrix
  176. if (rvecs){
  177. cout << endl << endl << "rotation matrix - " << endl << endl;
  178. for (int j = 0; j < numberOfSuccessfulImages; j++){
  179. for (int i = 0; i < 3; i++){
  180. if(i!=0)
  181. cout << setw(20);
  182. cout << cvmGet(rvecs, j, i);
  183. }
  184. cout << endl;
  185. }
  186. }
  187. }
  188. public:
  189. CalibrateCamera(int width, int height){
  190. this->width = width;
  191. this->height = height;
  192. numberOfCorners = width * height;
  193. corners = new CvPoint2D32f[numberOfCorners];
  194. }
  195. void calibrateFromImages(vector<string> imageList){
  196. /* allocate matrix objects */
  197. this->imageList = imageList;
  198. numberOfImages = imageList.size();
  199. allocateMatrixObjects();
  200. /* findChessboardCorners */
  201. cout << endl << endl << "running cvFindChessboardCorners() ..." << endl << endl;
  202. findChessboardCorner();
  203. /* calibrate camera */
  204. calibrateCamera();
  205. }
  206. void calibrateFromLiveCapture(){
  207. /* live capture images */
  208. liveCapture();
  209. /* allocate matrix objects */
  210. numberOfImages = imageList.size();
  211. allocateMatrixObjects();
  212. /* findChessboardCorners */
  213. cout << endl << endl << "running cvFindChessboardCorners() ..." << endl << endl;
  214. findChessboardCorner();
  215. /* calibrate camera */
  216. calibrateCamera();
  217. }
  218. };
  219. int main(int argc, char *argv[]){
  220. CalibrateCamera *camera = new CalibrateCamera(WIDTH, HEIGHT);
  221. if (argc <= 1){
  222. camera->calibrateFromLiveCapture();
  223. }
  224. else{
  225. /* push filenames to a vector */
  226. vector<string> imageList;
  227. for(int i=1; i<argc; i++){
  228. string filename = argv[i];
  229. imageList.push_back(filename);
  230. }
  231. camera->calibrateFromImages(imageList);
  232. }
  233. }