ObjectModel.cpp
Go to the documentation of this file.
00001 
00033 #include "ObjectModel.h"
00034 #include "MetaFile.h"
00035 #include "PlanarVisualizationModel.h"
00036 #include "PointCloudVisualizationModel.h"
00037 
00038 #include "DUtils.h"
00039 #include "DUtilsCV.h"
00040 #include "DVision.h"
00041 
00042 #include <opencv/cv.h>
00043 #include <string>
00044 #include <iostream>
00045 #include <stdio.h>
00046 #include <vector>
00047 #include <fstream>
00048 #include <algorithm>
00049 
00050 typedef DVision::PMVS::PLYFile PLYFile;
00051 typedef DVision::PMVS::PLYFile::PLYPoint PLYPoint;
00052 typedef DVision::Bundle::CameraFile CameraFile;
00053 typedef DVision::Bundle::CameraFile::Camera Camera;
00054 typedef DVision::SurfSet SurfSet;
00055 
00056 using namespace std;
00057 
00058 // ----------------------------------------------------------------------------
00059 
00060 ObjectModel::ObjectModel():
00061   m_visualization_model(NULL)
00062   //, m_flann(NULL), m_features(NULL),
00063 {
00064 
00065 }
00066 
00067 // ----------------------------------------------------------------------------
00068 
00069 ObjectModel::ObjectModel(const std::string &dir,
00070   bool load_visualization_model):
00071   m_visualization_model(NULL)
00072   //, m_flann(NULL), m_features(NULL),
00073 {
00074   loadDirectory(dir, load_visualization_model);
00075 }
00076 
00077 // ----------------------------------------------------------------------------
00078 
00079 ObjectModel::~ObjectModel()
00080 {
00081   //delete m_features;
00082   //delete m_flann;
00083 
00084   delete m_visualization_model;
00085   m_visualization_model = NULL;
00086 
00087 #if !OPENCV_ADV_MATCHER
00088   vector<Face>::iterator fit;
00089   for(fit = Faces.begin(); fit != Faces.end(); ++fit)
00090   {
00091     //delete fit->flann_matcher;
00092     //fit->flann_matcher = NULL;
00093   }
00094 #endif
00095 
00096 }
00097 
00098 // ----------------------------------------------------------------------------
00099 
00100 void ObjectModel::loadDirectory(const std::string &dir,
00101   bool load_visualization_model)
00102 {
00103   const int N = 1024;
00104   char buffer[N];
00105 
00106   this->Name = this->Type = "";
00107   this->Faces.clear();
00108   //this->m_map.clear();
00109   //delete m_flann; // ####
00110 
00111   snprintf(buffer, N, "%s/meta.xml", dir.c_str());
00112 
00113   MetaFile::MetaData data;
00114   MetaFile::readFile(buffer, data);
00115 
00116   this->Name = data.Name;
00117   this->Type = data.Type;
00118 
00119   /*
00120   snprintf(buffer, N, "%s/index_tree.", dir.c_str());
00121   //if(DUtils::FileFunctions::FileExists(buffer))
00122   // ####
00123   if(true)
00124   {
00125     loadFlann(string(buffer) + "fln", string(buffer) + "key.gz"); // ###
00126 
00127     m_map.resize(0);
00128     m_map.resize(m_flann->size(), std::vector<vector<int> >(data.NFaces)); // ###
00129   }
00130   */
00131 
00132   this->Faces.reserve(data.NFaces); // avoid reallocations (important!)
00133   for(int i = 0; i < data.NFaces; ++i)
00134   {
00135     this->Faces.push_back(Face());
00136     Face& face = this->Faces.back();
00137 
00138     snprintf(buffer, N, "%s/face_%03d.png", dir.c_str(), i);
00139     face.image = cv::imread(buffer);
00140     if(face.image.empty())
00141       throw string("ObjectModel: cannot load image ") + buffer;
00142 
00143     snprintf(buffer, N, "%s/face_%03d.key.gz", dir.c_str(), i);
00144     face.surf.Load(buffer);
00145 
00146     snprintf(buffer, N, "%s/face_%03d.ply", dir.c_str(), i);
00147     PLYFile::readFile(buffer, face.plypoints);
00148 
00149     /*
00150     snprintf(buffer, N, "%s/face_%03d.idx", dir.c_str(), i);
00151     //if(DUtils::FileFunctions::FileExists(buffer)) // ###
00152     if(true)
00153     {
00154       updateMap(buffer, i, face.surf.keys.size()); // ###
00155     }
00156     */
00157 
00158     snprintf(buffer, N, "%s/face_%03d.txt", dir.c_str(), i);
00159     Camera camera(buffer);
00160 
00161     face.A = (cv::Mat_<float>(3, 3) <<
00162       camera.f, 0, face.image.cols/2.f,
00163       0, camera.f, face.image.rows/2.f,
00164       0, 0, 1);
00165 
00166     face.cRo = camera.R;
00167     face.cto = camera.t;
00168 
00169     // create flann matcher (it cannot be stored!)
00170     vector<cv::Mat> flann_training_desc;
00171 
00172     if(!face.surf.keys.empty())
00173     {
00174       flann_training_desc.push_back(cv::Mat
00175         (face.surf.keys.size(), face.surf.GetDescriptorLength(), CV_32F,
00176         &(*face.surf.descriptors.begin())  )); // shared data
00177       // note: these data will be used by the flann matcher (it stores a pointer)
00178       // it is important not to reallocate them
00179     }
00180 
00181 #if OPENCV_ADV_MATCHER
00182     face.flann_matcher.add(flann_training_desc);
00183     face.flann_matcher.train();
00184 #else
00185     if(!flann_training_desc.empty()){
00186       face.flann_matcher = new cv::flann::Index(flann_training_desc[0],
00187         cv::flann::KDTreeIndexParams(4));
00188     }else{
00189       face.flann_matcher = NULL;
00190     }
00191 #endif
00192   }
00193 
00194   delete m_visualization_model;
00195   m_visualization_model = NULL;
00196 
00197   if(load_visualization_model)
00198   {
00199     if(Type == "planar")
00200     {
00201       m_visualization_model = new PlanarVisualizationModel
00202         (this->Faces, data.Dimensions.Planar);
00203     }
00204     else if(Type == "3D")
00205     {
00206       snprintf(buffer, N, "%s/drawing_model.ply", dir.c_str());
00207       m_visualization_model = new PointCloudVisualizationModel(buffer);
00208     }
00209   }
00210 }
00211 
00212 // ----------------------------------------------------------------------------
00213 
00214 bool ObjectModel::checkDirectory(const std::string &dir)
00215 {
00216   const int N = 1024;
00217   char buffer[N];
00218 
00219   MetaFile::MetaData data;
00220 
00221   try {
00222     snprintf(buffer, N, "%s/meta.xml", dir.c_str());
00223     MetaFile::readFile(buffer, data);
00224   }catch(std::string ex)
00225   {
00226     return false;
00227   }
00228 
00229   for(int i = 0; i < data.NFaces; ++i)
00230   {
00231     snprintf(buffer, N, "%s/face_%03d.png", dir.c_str(), i);
00232     if(!DUtils::FileFunctions::FileExists(buffer)) return false;
00233 
00234     snprintf(buffer, N, "%s/face_%03d.key.gz", dir.c_str(), i);
00235     if(!DUtils::FileFunctions::FileExists(buffer)) return false;
00236 
00237     snprintf(buffer, N, "%s/face_%03d.ply", dir.c_str(), i);
00238     if(!DUtils::FileFunctions::FileExists(buffer)) return false;
00239 
00240     snprintf(buffer, N, "%s/face_%03d.txt", dir.c_str(), i);
00241     if(!DUtils::FileFunctions::FileExists(buffer)) return false;
00242   }
00243 
00244   return true;
00245 }
00246 
00247 // ----------------------------------------------------------------------------
00248 
00249 std::string ObjectModel::getName(const std::string &dir)
00250 {
00251   stringstream ss;
00252   ss << dir << "/meta.xml";
00253 
00254   MetaFile::MetaData data;
00255   try {
00256     MetaFile::readFile(ss.str().c_str(), data);
00257     return data.Name;
00258   }catch(std::string ex)
00259   {
00260     return "";
00261   }
00262 }
00263 
00264 // ----------------------------------------------------------------------------
00265 
00266 /*
00267 void ObjectModel::loadFlann(const std::string &flan_filename,
00268   const std::string &keys_filename)
00269 {
00270   delete m_features;
00271   m_features = new SurfSet;
00272   m_features->Load(keys_filename);
00273 
00274   if(m_flann) delete m_flann;  // ###
00275 
00276   cv::Mat features(m_features->keys.size(),
00277     m_features->GetDescriptorLength(), CV_32F,
00278     &m_features->descriptors[0]);
00279 
00280   m_flann = new cv::flann::Index(features,
00281     cv::flann::SavedIndexParams(flan_filename));
00282 }
00283 */
00284 
00285 // ----------------------------------------------------------------------------
00286 
00287 /*
00288 void ObjectModel::updateMap(const char *filename, int face_idx, int N)
00289 {
00290   fstream f(filename, ios::in);
00291 
00292   int global_key_idx;
00293   for(int i = 0; i < N; ++i)
00294   {
00295     // m_map[ global_key_idx ][ face_idx ] = [ local_idx, ... ]
00296     f >> global_key_idx;
00297     m_map[global_key_idx][face_idx].push_back(i);
00298   }
00299 
00300   f.close();
00301 }
00302 */
00303 
00304 // ----------------------------------------------------------------------------
00305 
00306 struct faceMatches
00307 {
00308   int face_idx;
00309   std::vector<int> *scene_indices;
00310   std::vector<int> *face_indices;
00311   std::vector<float> *distances;
00312 
00313   faceMatches(): scene_indices(NULL), face_indices(NULL), distances(NULL){}
00314 
00315   void allocate()
00316   {
00317     scene_indices = new std::vector<int>();
00318     face_indices = new std::vector<int>();
00319     distances = new std::vector<float>();
00320   }
00321 
00322   void deallocate()
00323   {
00324     delete scene_indices;
00325     delete face_indices;
00326     delete distances;
00327   }
00328 };
00329 
00330 static bool descendingNumberOfDetections(
00331   const faceMatches &a, const faceMatches &b)
00332 {
00333   return a.face_indices->size() > b.face_indices->size();
00334 }
00335 
00336 void ObjectModel::detectFaces(const SurfSet &scene,
00337   std::vector<int>& face_indices,
00338   std::vector<std::vector<int> >& key_indices,
00339   std::vector<std::vector<int> >& scene_indices,
00340   std::vector<std::vector<float> >& distances,
00341   int min_detected_points, int max_correspondences_per_point,
00342   float max_ratio)
00343 {
00344   // Usual implementation: no repeated matches (max_correspondences_per_point
00345   // is ignored), matching by neighbor ratio
00346 
00347   face_indices.resize(0);
00348   key_indices.resize(0);
00349   scene_indices.resize(0);
00350   distances.resize(0);
00351 
00352   const int N = scene.keys.size(); // number of query descriptors
00353   const int L = scene.GetDescriptorLength(); // length of descriptors
00354 
00355   if(N < 3)
00356   {
00357     // no match can be done
00358     return;
00359   }
00360 
00361   vector<faceMatches> all_face_matches(this->Faces.size());
00362   // matches[face_idx] = <face_idx, [local_idx, ...]> // all the faces
00363   for(unsigned int i = 0; i < all_face_matches.size(); ++i)
00364   {
00365     all_face_matches[i].face_idx = i;
00366     all_face_matches[i].allocate();
00367   }
00368 
00369 #if OPENCV_ADV_MATCHER
00370   vector<vector<cv::DMatch> > flann_matches;
00371 #else
00372   cv::flann::SearchParams flann_params(64);
00373   cv::Mat flann_indices(N, 2, CV_32S);
00374   cv::Mat flann_dists(N, 2, CV_32F);
00375 #endif
00376 
00377 
00378   // for holding the scene descriptors
00379   //cv::Mat queryDescs(N, L, CV_32F);
00380   cv::Mat queryDescs(N, L, CV_32F,
00381     const_cast<float*>(&scene.descriptors[0]));
00382 
00383   vector<Face>::iterator fit;
00384   for(fit = Faces.begin(); fit != Faces.end(); ++fit)
00385   {
00386     if(fit->surf.size() < 3) continue; // not enough points
00387     
00388 #if !OPENCV_ADV_MATCHER
00389     if(!fit->flann_matcher) continue; // if no flann-matcher (there were not keys)
00390 #endif
00391 
00392     faceMatches& this_face_match = all_face_matches[fit - Faces.begin()];
00393     vector<int> &face_indices = *this_face_match.face_indices;
00394     vector<int> &scene_indices = *this_face_match.scene_indices;
00395     vector<float> &distances = *this_face_match.distances;
00396 
00397 #if OPENCV_ADV_MATCHER
00398     flann_matches.resize(0);
00399     fit->flann_matcher.knnMatch(queryDescs, flann_matches, 2);
00400 #else
00401     fit->flann_matcher->knnSearch(queryDescs, flann_indices,
00402       flann_dists, 2, flann_params);
00403 #endif
00404 
00405 
00406     for(int i = 0; i < N; ++i)
00407     {
00408 #if OPENCV_ADV_MATCHER
00409       if(flann_matches[i].size() == 2 &&
00410         flann_matches[i][0].distance / flann_matches[i][1].distance < max_ratio)
00411 #else
00412       if(flann_dists.at<float>(i, 0) / flann_dists.at<float>(i, 1) < max_ratio)
00413 #endif
00414       {
00415 #if OPENCV_ADV_MATCHER
00416         int idx_in_face = flann_matches[i][0].trainIdx;
00417         int idx_in_scene = flann_matches[i][0].queryIdx;
00418         float dist = flann_matches[i][0].distance;
00419 #else
00420         int idx_in_face = flann_indices.at<int>(i, 0);
00421         int idx_in_scene = i;
00422         float dist = flann_dists.at<float>(i, 0);
00423 #endif
00424 
00425         // check laplacian sign
00426         if(scene.laplacians[idx_in_scene] == fit->surf.laplacians[idx_in_face])
00427         {
00428 
00429           // check if there was already a match
00430           vector<int>::const_iterator fiit =
00431             find(face_indices.begin(), face_indices.end(), idx_in_face);
00432 
00433           if(fiit != face_indices.end())
00434           {
00435             // check if replacing
00436             int existing_pos = fiit - face_indices.begin();
00437 
00438             if(dist < distances[existing_pos] )
00439             {
00440               // replace
00441               scene_indices[existing_pos] = idx_in_scene;
00442               distances[existing_pos] = dist;
00443 
00444             }
00445           }
00446           else
00447           {
00448             // add match
00449             face_indices.push_back(idx_in_face);
00450             scene_indices.push_back(idx_in_scene);
00451             distances.push_back(dist);
00452 
00453           } // if adding match
00454         } // if laplacians match
00455       } // if ratio ok
00456 
00457     } // for each query point
00458 
00459   } // for each face
00460 
00461   // sort face matches in
00462   sort(all_face_matches.begin(), all_face_matches.end(),
00463     descendingNumberOfDetections);
00464 
00465   // copy to the final structure those face matches which have enough matches
00466   face_indices.resize(0); face_indices.reserve(all_face_matches.size());
00467   key_indices.resize(0); key_indices.reserve(all_face_matches.size());
00468   scene_indices.resize(0); scene_indices.reserve(all_face_matches.size());
00469   distances.resize(0); distances.reserve(all_face_matches.size());
00470 
00471   for(unsigned int i = 0; i < all_face_matches.size(); ++i)
00472   {
00473     const faceMatches &face_matches = all_face_matches[i];
00474 
00475     if((int)face_matches.face_indices->size() > min_detected_points)
00476     {
00477       face_indices.push_back(face_matches.face_idx);
00478 
00479       key_indices.push_back(vector<int>());
00480       key_indices.back().insert(key_indices.back().end(),
00481         face_matches.face_indices->begin(), face_matches.face_indices->end());
00482 
00483       scene_indices.push_back(vector<int>());
00484       scene_indices.back().insert(scene_indices.back().end(),
00485         face_matches.scene_indices->begin(), face_matches.scene_indices->end());
00486 
00487       distances.push_back(vector<float>());
00488       distances.back().insert(distances.back().end(),
00489         face_matches.distances->begin(), face_matches.distances->end());
00490     }
00491     else{ break; }
00492   }
00493   // done
00494   for(unsigned int i = 0; i < all_face_matches.size(); ++i)
00495     all_face_matches[i].deallocate();
00496 
00497 }
00498 
00499 // ----------------------------------------------------------------------------
00500 
00501 #if 0
00502 // This implementation used the old flann structure
00503 void ObjectModel::detectFaces(const SurfSet &scene, std::vector<int>& face_indices,
00504       std::vector<std::vector<int> >& key_indices,
00505       std::vector<std::vector<int> >& scene_indices,
00506       std::vector<std::vector<float> >& distances,
00507       int min_detected_points, int max_correspondences_per_point,
00508       float max_ratio) const
00509 {
00510 
00511 #define USE_SEVERAL_MATCHES 1
00512 
00513   face_indices.resize(0);
00514   key_indices.resize(0);
00515 
00516   const int nqueries = scene.keys.size();
00517   if(nqueries == 0) return;
00518 
00519   const int L = scene.GetDescriptorLength();
00520 
00521   cv::Mat indices(nqueries, 2, CV_32S);
00522   cv::Mat dists(nqueries, 2, CV_32F);
00523   const cv::Mat queries( nqueries, L, CV_32F,
00524     const_cast<float*>(&scene.descriptors[0]) );
00525 
00526 #if USE_SEVERAL_MATCHES
00527   int nmatches = max_correspondences_per_point;
00528   m_flann->knnSearch(queries, indices, dists, nmatches,
00529     cv::flann::SearchParams(64));
00530 #else
00531   m_flann->knnSearch(queries, indices, dists, 2,
00532     cv::flann::SearchParams(64));
00533 #endif
00534 
00535   vector<faceMatches> matches(this->Faces.size());
00536   // matches[face_idx] = <face_idx, [local_idx, ...]> // all the faces
00537   for(unsigned int i = 0; i < matches.size(); ++i)
00538   {
00539     matches[i].face_idx = i;
00540   }
00541 
00542   int* indices_ptr = indices.ptr<int>(0);
00543   float* dists_ptr = dists.ptr<float>(0);
00544 
00545 #if USE_SEVERAL_MATCHES
00546   // avoid repeated matches from model to scene
00547   vector<int> scene_matches;
00548   vector<int> model_matches;
00549   vector<float> dist_matches;
00550   vector<int>::iterator mit;
00551 
00552   // scene_matches[i] <--> model_matches[i]
00553   scene_matches.reserve(nmatches * indices.rows);
00554   model_matches.reserve(nmatches * indices.rows);
00555   dist_matches.reserve(nmatches * indices.rows);
00556 
00557   for(int scene_idx = 0; scene_idx < indices.rows; ++scene_idx)
00558   {
00559     indices_ptr = indices.ptr<int>(scene_idx);
00560     dists_ptr = dists.ptr<float>(scene_idx);
00561 
00562     for(int j = 0; j < nmatches; ++j)
00563     {
00564       int model_idx = indices_ptr[j];
00565       float dist = dists_ptr[j];
00566 
00567       // check if there is alredy a match from model_idx
00568       //mit = find(model_matches.begin(), model_matches.end(), model_idx);
00569       if(false)
00570       //if(mit != model_matches.end())
00571       {
00572         // update
00573         int k = mit - model_matches.begin();
00574         if(dist < dist_matches[k])
00575         {
00576           scene_matches[k] = scene_idx;
00577           model_matches[k] = model_idx;
00578           dist_matches[k] = dist;
00579         }
00580       }
00581       else
00582       {
00583         // add
00584         scene_matches.push_back(scene_idx);
00585         model_matches.push_back(model_idx);
00586         dist_matches.push_back(dist);
00587       }
00588     }
00589   }
00590 
00591   // transform into face information
00592 
00593   // matches[face_idx] = <face_idx, [local_idx, ...]> // all the faces
00594   // m_map[global_key_idx][ face_idx ] = [local_idx, ...]
00595 
00596   for(unsigned int i = 0; i < model_matches.size(); ++i)
00597   {
00598     int model_idx = model_matches[i];
00599     int scene_idx = scene_matches[i];
00600     float dist = dist_matches[i];
00601     const vector<vector<int> > &map = m_map[model_idx];
00602 
00603     for(unsigned int face_idx = 0; face_idx < this->Faces.size(); ++face_idx)
00604     {
00605       matches[face_idx].face_indices.insert(
00606         matches[face_idx].face_indices.end(),
00607         map[face_idx].begin(), map[face_idx].end());
00608 
00609       matches[face_idx].scene_indices.insert(
00610         matches[face_idx].scene_indices.end(),
00611         map[face_idx].size(), scene_idx);
00612 
00613       matches[face_idx].distances.insert(
00614         matches[face_idx].distances.end(),
00615         map[face_idx].size(), dist);
00616     }
00617   }
00618 
00619 
00620 #else
00621   for (int i=0; i < indices.rows; ++i) {
00622     // indices_ptr[2*i]: model global key index
00623     int global_key_idx = indices_ptr[2*i];
00624     if (dists_ptr[2*i] < max_ratio * dists_ptr[2*i+1]) // old
00625     {
00626       //git = find(global_key_indices_matched.begin(),
00627       //  global_key_indices_matched.end(),
00628       //  global_key_idx);
00629       //if(git == global_key_indices_matched.end())
00630       {
00631         //global_key_indices_matched.push_back(global_key_idx);
00632 
00633         const vector<vector<int> > &map = m_map[global_key_idx];
00634         // m_map[global_key_idx][ face_idx ] = [local_idx, ...]
00635 
00636         for(unsigned int face_idx = 0; face_idx < this->Faces.size(); ++face_idx)
00637         {
00638           matches[face_idx].face_indices.insert(
00639             matches[face_idx].face_indices.end(),
00640             map[face_idx].begin(), map[face_idx].end());
00641 
00642           matches[face_idx].scene_indices.insert(
00643             matches[face_idx].scene_indices.end(),
00644             map[face_idx].size(), i);
00645 
00646           matches[face_idx].distances.insert(
00647             matches[face_idx].distances.end(),
00648             map[face_idx].size(), dists_ptr[2*i]);
00649         }
00650 
00651       }
00652     }
00653   }
00654 #endif
00655 
00656   // sort in descending order of detected points
00657   sort(matches.begin(), matches.end(), descendingNumberOfDetections);
00658 
00659   // copy those faces with enough points
00660   face_indices.reserve(matches.size());
00661   key_indices.reserve(matches.size());
00662   scene_indices.reserve(matches.size());
00663   distances.reserve(matches.size());
00664 
00665   for(unsigned int i = 0; i < matches.size(); ++i)
00666   {
00667     if((int)matches[i].face_indices.size() >= min_detected_points)
00668     {
00669       face_indices.push_back(matches[i].face_idx);
00670       key_indices.push_back(matches[i].face_indices);
00671       scene_indices.push_back(matches[i].scene_indices);
00672       distances.push_back(matches[i].distances);
00673     }
00674     else{ break; }
00675   }
00676 
00677 }
00678 #endif
00679 
00680 // ----------------------------------------------------------------------------
00681 
00682 
00683 
00684 


re_vision
Author(s): Dorian Galvez-Lopez
autogenerated on Sun Jan 5 2014 11:32:01