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
00063 {
00064
00065 }
00066
00067
00068
00069 ObjectModel::ObjectModel(const std::string &dir,
00070 bool load_visualization_model):
00071 m_visualization_model(NULL)
00072
00073 {
00074 loadDirectory(dir, load_visualization_model);
00075 }
00076
00077
00078
00079 ObjectModel::~ObjectModel()
00080 {
00081
00082
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
00092
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
00109
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
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 this->Faces.reserve(data.NFaces);
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
00151
00152
00153
00154
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
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()) ));
00177
00178
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
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
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
00345
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();
00353 const int L = scene.GetDescriptorLength();
00354
00355 if(N < 3)
00356 {
00357
00358 return;
00359 }
00360
00361 vector<faceMatches> all_face_matches(this->Faces.size());
00362
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
00379
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;
00387
00388 #if !OPENCV_ADV_MATCHER
00389 if(!fit->flann_matcher) continue;
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
00426 if(scene.laplacians[idx_in_scene] == fit->surf.laplacians[idx_in_face])
00427 {
00428
00429
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
00436 int existing_pos = fiit - face_indices.begin();
00437
00438 if(dist < distances[existing_pos] )
00439 {
00440
00441 scene_indices[existing_pos] = idx_in_scene;
00442 distances[existing_pos] = dist;
00443
00444 }
00445 }
00446 else
00447 {
00448
00449 face_indices.push_back(idx_in_face);
00450 scene_indices.push_back(idx_in_scene);
00451 distances.push_back(dist);
00452
00453 }
00454 }
00455 }
00456
00457 }
00458
00459 }
00460
00461
00462 sort(all_face_matches.begin(), all_face_matches.end(),
00463 descendingNumberOfDetections);
00464
00465
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
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
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
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
00547 vector<int> scene_matches;
00548 vector<int> model_matches;
00549 vector<float> dist_matches;
00550 vector<int>::iterator mit;
00551
00552
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
00568
00569 if(false)
00570
00571 {
00572
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
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
00592
00593
00594
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
00623 int global_key_idx = indices_ptr[2*i];
00624 if (dists_ptr[2*i] < max_ratio * dists_ptr[2*i+1])
00625 {
00626
00627
00628
00629
00630 {
00631
00632
00633 const vector<vector<int> > &map = m_map[global_key_idx];
00634
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
00657 sort(matches.begin(), matches.end(), descendingNumberOfDetections);
00658
00659
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