trajectory_reconstruction.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. #include <opencv2/core.hpp>
  2. #include <opencv2/sfm.hpp>
  3. #include <opencv2/viz.hpp>
  4. #include <iostream>
  5. #include <fstream>
  6. using namespace std;
  7. using namespace cv;
  8. using namespace cv::sfm;
  9. static void help() {
  10. cout
  11. << "\n------------------------------------------------------------------\n"
  12. << " This program shows the camera trajectory reconstruction capabilities\n"
  13. << " in the OpenCV Structure From Motion (SFM) module.\n"
  14. << " \n"
  15. << " Usage:\n"
  16. << " example_sfm_trajectory_reconstruction <path_to_tracks_file> <f> <cx> <cy>\n"
  17. << " where: is the tracks file absolute path into your system. \n"
  18. << " \n"
  19. << " The file must have the following format: \n"
  20. << " row1 : x1 y1 x2 y2 ... x36 y36 for track 1\n"
  21. << " row2 : x1 y1 x2 y2 ... x36 y36 for track 2\n"
  22. << " etc\n"
  23. << " \n"
  24. << " i.e. a row gives the 2D measured position of a point as it is tracked\n"
  25. << " through frames 1 to 36. If there is no match found in a view then x\n"
  26. << " and y are -1.\n"
  27. << " \n"
  28. << " Each row corresponds to a different point.\n"
  29. << " \n"
  30. << " f is the focal length in pixels. \n"
  31. << " cx is the image principal point x coordinates in pixels. \n"
  32. << " cy is the image principal point y coordinates in pixels. \n"
  33. << "------------------------------------------------------------------\n\n"
  34. << endl;
  35. }
  36. /* Build the following structure data
  37. *
  38. * frame1 frame2 frameN
  39. * track1 | (x11,y11) | -> | (x12,y12) | -> | (x1N,y1N) |
  40. * track2 | (x21,y11) | -> | (x22,y22) | -> | (x2N,y2N) |
  41. * trackN | (xN1,yN1) | -> | (xN2,yN2) | -> | (xNN,yNN) |
  42. *
  43. *
  44. * In case a marker (x,y) does not appear in a frame its
  45. * values will be (-1,-1).
  46. */
  47. static void parser_2D_tracks(const String &_filename, std::vector<Mat> &points2d )
  48. {
  49. ifstream myfile(_filename.c_str());
  50. if (!myfile.is_open())
  51. {
  52. cout << "Unable to read file: " << _filename << endl;
  53. exit(0);
  54. } else {
  55. double x, y;
  56. string line_str;
  57. int n_frames = 0, n_tracks = 0;
  58. // extract data from text file
  59. vector<vector<Vec2d> > tracks;
  60. for ( ; getline(myfile,line_str); ++n_tracks)
  61. {
  62. istringstream line(line_str);
  63. vector<Vec2d> track;
  64. for ( n_frames = 0; line >> x >> y; ++n_frames)
  65. {
  66. if ( x > 0 && y > 0)
  67. track.push_back(Vec2d(x,y));
  68. else
  69. track.push_back(Vec2d(-1));
  70. }
  71. tracks.push_back(track);
  72. }
  73. // embed data in reconstruction api format
  74. for (int i = 0; i < n_frames; ++i)
  75. {
  76. Mat_<double> frame(2, n_tracks);
  77. for (int j = 0; j < n_tracks; ++j)
  78. {
  79. frame(0,j) = tracks[j][i][0];
  80. frame(1,j) = tracks[j][i][1];
  81. }
  82. points2d.push_back(Mat(frame));
  83. }
  84. myfile.close();
  85. }
  86. }
  87. /* Keyboard callback to control 3D visualization
  88. */
  89. bool camera_pov = false;
  90. static void keyboard_callback(const viz::KeyboardEvent &event, void* cookie)
  91. {
  92. if ( event.action == 0 &&!event.symbol.compare("s") )
  93. camera_pov = !camera_pov;
  94. }
  95. /* Sample main code
  96. */
  97. int main(int argc, char** argv)
  98. {
  99. // Read input parameters
  100. if ( argc != 5 )
  101. {
  102. help();
  103. exit(0);
  104. }
  105. // Read 2D points from text file
  106. std::vector<Mat> points2d;
  107. parser_2D_tracks( argv[1], points2d );
  108. // Set the camera calibration matrix
  109. const double f = atof(argv[2]),
  110. cx = atof(argv[3]), cy = atof(argv[4]);
  111. Matx33d K = Matx33d( f, 0, cx,
  112. 0, f, cy,
  113. 0, 0, 1);
  114. /// Reconstruct the scene using the 2d correspondences
  115. bool is_projective = true;
  116. vector<Mat> Rs_est, ts_est, points3d_estimated;
  117. reconstruct(points2d, Rs_est, ts_est, K, points3d_estimated, is_projective);
  118. // Print output
  119. cout << "\n----------------------------\n" << endl;
  120. cout << "Reconstruction: " << endl;
  121. cout << "============================" << endl;
  122. cout << "Estimated 3D points: " << points3d_estimated.size() << endl;
  123. cout << "Estimated cameras: " << Rs_est.size() << endl;
  124. cout << "Refined intrinsics: " << endl << K << endl << endl;
  125. cout << "3D Visualization: " << endl;
  126. cout << "============================" << endl;
  127. /// Create 3D windows
  128. viz::Viz3d window_est("Estimation Coordinate Frame");
  129. window_est.setBackgroundColor(); // black by default
  130. window_est.registerKeyboardCallback(&keyboard_callback);
  131. // Create the pointcloud
  132. cout << "Recovering points ... ";
  133. // recover estimated points3d
  134. vector<Vec3f> point_cloud_est;
  135. for (int i = 0; i < points3d_estimated.size(); ++i)
  136. point_cloud_est.push_back(Vec3f(points3d_estimated[i]));
  137. cout << "[DONE]" << endl;
  138. /// Recovering cameras
  139. cout << "Recovering cameras ... ";
  140. vector<Affine3d> path_est;
  141. for (size_t i = 0; i < Rs_est.size(); ++i)
  142. path_est.push_back(Affine3d(Rs_est[i],ts_est[i]));
  143. cout << "[DONE]" << endl;
  144. /// Add cameras
  145. cout << "Rendering Trajectory ... ";
  146. /// Wait for key 'q' to close the window
  147. cout << endl << "Press: " << endl;
  148. cout << " 's' to switch the camera pov" << endl;
  149. cout << " 'q' to close the windows " << endl;
  150. if ( path_est.size() > 0 )
  151. {
  152. // animated trajectory
  153. int idx = 0, forw = -1, n = static_cast<int>(path_est.size());
  154. while(!window_est.wasStopped())
  155. {
  156. /// Render points as 3D cubes
  157. for (size_t i = 0; i < point_cloud_est.size(); ++i)
  158. {
  159. Vec3d point = point_cloud_est[i];
  160. Affine3d point_pose(Mat::eye(3,3,CV_64F), point);
  161. char buffer[50];
  162. sprintf (buffer, "%d", static_cast<int>(i));
  163. viz::WCube cube_widget(Point3f(0.1,0.1,0.0), Point3f(0.0,0.0,-0.1), true, viz::Color::blue());
  164. cube_widget.setRenderingProperty(viz::LINE_WIDTH, 2.0);
  165. window_est.showWidget("Cube"+String(buffer), cube_widget, point_pose);
  166. }
  167. Affine3d cam_pose = path_est[idx];
  168. viz::WCameraPosition cpw(0.25); // Coordinate axes
  169. viz::WCameraPosition cpw_frustum(K, 0.3, viz::Color::yellow()); // Camera frustum
  170. if ( camera_pov )
  171. window_est.setViewerPose(cam_pose);
  172. else
  173. {
  174. // render complete trajectory
  175. window_est.showWidget("cameras_frames_and_lines_est", viz::WTrajectory(path_est, viz::WTrajectory::PATH, 1.0, viz::Color::green()));
  176. window_est.showWidget("CPW", cpw, cam_pose);
  177. window_est.showWidget("CPW_FRUSTUM", cpw_frustum, cam_pose);
  178. }
  179. // update trajectory index (spring effect)
  180. forw *= (idx==n || idx==0) ? -1: 1; idx += forw;
  181. // frame rate 1s
  182. window_est.spinOnce(1, true);
  183. window_est.removeAllWidgets();
  184. }
  185. }
  186. return 0;
  187. }