Home | History | Annotate | Download | only in src
      1 // C++
      2 #include <iostream>
      3 // OpenCV
      4 #include <opencv2/core/core.hpp>
      5 #include <opencv2/imgproc/imgproc.hpp>
      6 #include <opencv2/calib3d/calib3d.hpp>
      7 #include <opencv2/features2d/features2d.hpp>
      8 // PnP Tutorial
      9 #include "Mesh.h"
     10 #include "Model.h"
     11 #include "PnPProblem.h"
     12 #include "RobustMatcher.h"
     13 #include "ModelRegistration.h"
     14 #include "Utils.h"
     15 
     16 using namespace cv;
     17 using namespace std;
     18 
     19 /**  GLOBAL VARIABLES  **/
     20 
     21 string tutorial_path = "../../samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/"; // path to tutorial
     22 
     23 string img_path = tutorial_path + "Data/resized_IMG_3875.JPG";  // image to register
     24 string ply_read_path = tutorial_path + "Data/box.ply";          // object mesh
     25 string write_path = tutorial_path + "Data/cookies_ORB.yml";     // output file
     26 
     27 // Boolean the know if the registration it's done
     28 bool end_registration = false;
     29 
     30 // Intrinsic camera parameters: UVC WEBCAM
     31 double f = 45; // focal length in mm
     32 double sx = 22.3, sy = 14.9;
     33 double width = 2592, height = 1944;
     34 double params_CANON[] = { width*f/sx,   // fx
     35                           height*f/sy,  // fy
     36                           width/2,      // cx
     37                           height/2};    // cy
     38 
     39 // Setup the points to register in the image
     40 // In the order of the *.ply file and starting at 1
     41 int n = 8;
     42 int pts[] = {1, 2, 3, 4, 5, 6, 7, 8}; // 3 -> 4
     43 
     44 // Some basic colors
     45 Scalar red(0, 0, 255);
     46 Scalar green(0,255,0);
     47 Scalar blue(255,0,0);
     48 Scalar yellow(0,255,255);
     49 
     50 /*
     51  * CREATE MODEL REGISTRATION OBJECT
     52  * CREATE OBJECT MESH
     53  * CREATE OBJECT MODEL
     54  * CREATE PNP OBJECT
     55  */
     56 ModelRegistration registration;
     57 Model model;
     58 Mesh mesh;
     59 PnPProblem pnp_registration(params_CANON);
     60 
     61 /**  Functions headers  **/
     62 void help();
     63 
     64 // Mouse events for model registration
     65 static void onMouseModelRegistration( int event, int x, int y, int, void* )
     66 {
     67   if  ( event == EVENT_LBUTTONUP )
     68   {
     69       int n_regist = registration.getNumRegist();
     70       int n_vertex = pts[n_regist];
     71 
     72       Point2f point_2d = Point2f((float)x,(float)y);
     73       Point3f point_3d = mesh.getVertex(n_vertex-1);
     74 
     75       bool is_registrable = registration.is_registrable();
     76       if (is_registrable)
     77       {
     78         registration.registerPoint(point_2d, point_3d);
     79         if( registration.getNumRegist() == registration.getNumMax() ) end_registration = true;
     80       }
     81   }
     82 }
     83 
     84 /**  Main program  **/
     85 int main()
     86 {
     87 
     88   help();
     89 
     90   // load a mesh given the *.ply file path
     91   mesh.load(ply_read_path);
     92 
     93   // set parameters
     94   int numKeyPoints = 10000;
     95 
     96   //Instantiate robust matcher: detector, extractor, matcher
     97   RobustMatcher rmatcher;
     98   Ptr<FeatureDetector> detector = ORB::create(numKeyPoints);
     99   rmatcher.setFeatureDetector(detector);
    100 
    101   /**  GROUND TRUTH OF THE FIRST IMAGE  **/
    102 
    103   // Create & Open Window
    104   namedWindow("MODEL REGISTRATION", WINDOW_KEEPRATIO);
    105 
    106   // Set up the mouse events
    107   setMouseCallback("MODEL REGISTRATION", onMouseModelRegistration, 0 );
    108 
    109   // Open the image to register
    110   Mat img_in = imread(img_path, IMREAD_COLOR);
    111   Mat img_vis = img_in.clone();
    112 
    113   if (!img_in.data) {
    114     cout << "Could not open or find the image" << endl;
    115     return -1;
    116   }
    117 
    118   // Set the number of points to register
    119   int num_registrations = n;
    120   registration.setNumMax(num_registrations);
    121 
    122   cout << "Click the box corners ..." << endl;
    123   cout << "Waiting ..." << endl;
    124 
    125   // Loop until all the points are registered
    126   while ( waitKey(30) < 0 )
    127   {
    128     // Refresh debug image
    129     img_vis = img_in.clone();
    130 
    131     // Current registered points
    132     vector<Point2f> list_points2d = registration.get_points2d();
    133     vector<Point3f> list_points3d = registration.get_points3d();
    134 
    135     // Draw current registered points
    136     drawPoints(img_vis, list_points2d, list_points3d, red);
    137 
    138     // If the registration is not finished, draw which 3D point we have to register.
    139     // If the registration is finished, breaks the loop.
    140     if (!end_registration)
    141     {
    142       // Draw debug text
    143       int n_regist = registration.getNumRegist();
    144       int n_vertex = pts[n_regist];
    145       Point3f current_poin3d = mesh.getVertex(n_vertex-1);
    146 
    147       drawQuestion(img_vis, current_poin3d, green);
    148       drawCounter(img_vis, registration.getNumRegist(), registration.getNumMax(), red);
    149     }
    150     else
    151     {
    152       // Draw debug text
    153       drawText(img_vis, "END REGISTRATION", green);
    154       drawCounter(img_vis, registration.getNumRegist(), registration.getNumMax(), green);
    155       break;
    156     }
    157 
    158     // Show the image
    159     imshow("MODEL REGISTRATION", img_vis);
    160   }
    161 
    162   /** COMPUTE CAMERA POSE **/
    163 
    164   cout << "COMPUTING POSE ..." << endl;
    165 
    166   // The list of registered points
    167   vector<Point2f> list_points2d = registration.get_points2d();
    168   vector<Point3f> list_points3d = registration.get_points3d();
    169 
    170   // Estimate pose given the registered points
    171   bool is_correspondence = pnp_registration.estimatePose(list_points3d, list_points2d, SOLVEPNP_ITERATIVE);
    172   if ( is_correspondence )
    173   {
    174     cout << "Correspondence found" << endl;
    175 
    176     // Compute all the 2D points of the mesh to verify the algorithm and draw it
    177     vector<Point2f> list_points2d_mesh = pnp_registration.verify_points(&mesh);
    178     draw2DPoints(img_vis, list_points2d_mesh, green);
    179 
    180   } else {
    181     cout << "Correspondence not found" << endl << endl;
    182   }
    183 
    184   // Show the image
    185   imshow("MODEL REGISTRATION", img_vis);
    186 
    187   // Show image until ESC pressed
    188   waitKey(0);
    189 
    190 
    191    /** COMPUTE 3D of the image Keypoints **/
    192 
    193   // Containers for keypoints and descriptors of the model
    194   vector<KeyPoint> keypoints_model;
    195   Mat descriptors;
    196 
    197   // Compute keypoints and descriptors
    198   rmatcher.computeKeyPoints(img_in, keypoints_model);
    199   rmatcher.computeDescriptors(img_in, keypoints_model, descriptors);
    200 
    201   // Check if keypoints are on the surface of the registration image and add to the model
    202   for (unsigned int i = 0; i < keypoints_model.size(); ++i) {
    203     Point2f point2d(keypoints_model[i].pt);
    204     Point3f point3d;
    205     bool on_surface = pnp_registration.backproject2DPoint(&mesh, point2d, point3d);
    206     if (on_surface)
    207     {
    208         model.add_correspondence(point2d, point3d);
    209         model.add_descriptor(descriptors.row(i));
    210         model.add_keypoint(keypoints_model[i]);
    211     }
    212     else
    213     {
    214         model.add_outlier(point2d);
    215     }
    216   }
    217 
    218   // save the model into a *.yaml file
    219   model.save(write_path);
    220 
    221   // Out image
    222   img_vis = img_in.clone();
    223 
    224   // The list of the points2d of the model
    225   vector<Point2f> list_points_in = model.get_points2d_in();
    226   vector<Point2f> list_points_out = model.get_points2d_out();
    227 
    228   // Draw some debug text
    229   string num = IntToString((int)list_points_in.size());
    230   string text = "There are " + num + " inliers";
    231   drawText(img_vis, text, green);
    232 
    233   // Draw some debug text
    234   num = IntToString((int)list_points_out.size());
    235   text = "There are " + num + " outliers";
    236   drawText2(img_vis, text, red);
    237 
    238   // Draw the object mesh
    239   drawObjectMesh(img_vis, &mesh, &pnp_registration, blue);
    240 
    241   // Draw found keypoints depending on if are or not on the surface
    242   draw2DPoints(img_vis, list_points_in, green);
    243   draw2DPoints(img_vis, list_points_out, red);
    244 
    245   // Show the image
    246   imshow("MODEL REGISTRATION", img_vis);
    247 
    248   // Wait until ESC pressed
    249   waitKey(0);
    250 
    251   // Close and Destroy Window
    252   destroyWindow("MODEL REGISTRATION");
    253 
    254   cout << "GOODBYE" << endl;
    255 
    256 }
    257 
    258 /**********************************************************************************************************/
    259 void help()
    260 {
    261   cout
    262   << "--------------------------------------------------------------------------"   << endl
    263   << "This program shows how to create your 3D textured model. "                    << endl
    264   << "Usage:"                                                                       << endl
    265   << "./cpp-tutorial-pnp_registration"                                              << endl
    266   << "--------------------------------------------------------------------------"   << endl
    267   << endl;
    268 }
    269