00001
00024 #include "rgbdtools/graph/keyframe_graph_detector.h"
00025 #include "rgbdtools/matcher.h"
00026
00027 namespace rgbdtools {
00028
00029 aruco::MarkerDetector MDetector;
00030 KeyframeGraphDetector::KeyframeGraphDetector()
00031 {
00032 srand(time(NULL));
00033
00034 MDetector.setThresholdParams( 10.0,7.0);
00035 MDetector.setCornerRefinementMethod(aruco::MarkerDetector::LINES);
00036 marker_size = 0.2;
00037
00038 n_keypoints_ = 600;
00039 init_surf_threshold_ = 400;
00040 n_matches_accept = 16;
00041
00042
00043 pairwise_matching_method_ = PAIRWISE_MATCHING_RANSAC;
00044
00045
00046 candidate_method_ = CANDIDATE_GENERATION_SURF_TREE;
00047 n_candidates_ = 10;
00048 k_nearest_neighbors_ = 4;
00049
00050
00051 pairwise_matcher_index_ = PAIRWISE_MATCHER_KDTREE;
00052 matcher_use_desc_ratio_test_ = true;
00053 matcher_max_desc_ratio_ = 1;
00054 matcher_max_desc_dist_ = 0.5;
00055 n_original_poses = 0;
00056
00057 sac_max_eucl_dist_sq_ = 0.05 * 0.05;
00058 sac_min_inliers_ = 15;
00059 sac_reestimate_tf_ = false;
00060
00061
00062 ransac_confidence_ = 0.97;
00063 ransac_max_iterations_ = 1000;
00064 ransac_sufficient_inlier_ratio_ = 0.65;
00065
00066
00067 verbose_ = true;
00068 sac_save_results_ = true;
00069
00070
00071 log_one_minus_ransac_confidence_ = log(1.0 - ransac_confidence_);
00072
00073 setOutputPath( "~/SAC");
00074 }
00075
00076 KeyframeGraphDetector::~KeyframeGraphDetector()
00077 {
00078
00079 }
00080 void KeyframeGraphDetector::setMapping(bool mapping)
00081 {
00082 mapping_ = mapping;
00083 }
00084 void KeyframeGraphDetector::setMaxIterations(bool ransac_max_iterations)
00085 {
00086 ransac_max_iterations_ = ransac_max_iterations;
00087 }
00088
00089 void KeyframeGraphDetector::setSacMinInliers(int min)
00090 {
00091 assert(min > 0);
00092 sac_min_inliers_ = min;
00093 }
00094
00095 void KeyframeGraphDetector::setSACReestimateTf(bool sac_reestimate_tf)
00096 {
00097 sac_reestimate_tf_ = sac_reestimate_tf;
00098 }
00099
00100 void KeyframeGraphDetector::setMatcherUseDescRatioTest(bool matcher_use_desc_ratio_test)
00101 {
00102 matcher_use_desc_ratio_test_ = matcher_use_desc_ratio_test;
00103 }
00104
00105 void KeyframeGraphDetector::setMatcherMaxDescRatio(double matcher_max_desc_ratio)
00106 {
00107 matcher_max_desc_ratio_ = matcher_max_desc_ratio;
00108 }
00109
00110 void KeyframeGraphDetector::setMatcherMaxDescDist(double matcher_max_desc_dist)
00111 {
00112 matcher_max_desc_dist_ = matcher_max_desc_dist;
00113 }
00114
00115 void KeyframeGraphDetector::setNCandidates(int n_candidates)
00116 {
00117 n_candidates_ = n_candidates;
00118 }
00119
00120 void KeyframeGraphDetector::setKNearestNeighbors(int k_nearest_neighbors)
00121 {
00122 k_nearest_neighbors_ = k_nearest_neighbors;
00123 }
00124
00125 void KeyframeGraphDetector::setNKeypoints(int n_keypoints)
00126 {
00127 n_keypoints_ = n_keypoints;
00128 }
00129
00130 void KeyframeGraphDetector::setOutputPath(const std::string& output_path)
00131 {
00132 output_path_ = output_path;
00133 boost::filesystem::create_directories(output_path_);
00134 }
00135
00136 void KeyframeGraphDetector::setSACSaveResults(bool sac_save_results)
00137 {
00138 sac_save_results_ = sac_save_results;
00139 }
00140
00141 void KeyframeGraphDetector::setVerbose(bool verbose)
00142 {
00143 verbose_ = verbose;
00144 }
00145
00146 void KeyframeGraphDetector::setCandidateGenerationMethod(
00147 CandidateGenerationMethod candidate_method)
00148 {
00149 assert(candidate_method == CANDIDATE_GENERATION_BRUTE_FORCE ||
00150 candidate_method == CANDIDATE_GENERATION_SURF_TREE);
00151
00152 candidate_method_ = candidate_method;
00153 }
00154
00155 void KeyframeGraphDetector::setPairwiseMatchingMethod(
00156 PairwiseMatchingMethod pairwise_matching_method)
00157 {
00158 assert(pairwise_matching_method == PAIRWISE_MATCHING_BFSAC ||
00159 pairwise_matching_method == PAIRWISE_MATCHING_RANSAC);
00160
00161 pairwise_matching_method_ = pairwise_matching_method;
00162 }
00163
00164 void KeyframeGraphDetector::setPairwiseMatcherIndex(
00165 PairwiseMatcherIndex pairwise_matcher_index)
00166 {
00167 assert(pairwise_matcher_index == PAIRWISE_MATCHER_LINEAR ||
00168 pairwise_matcher_index == PAIRWISE_MATCHER_KDTREE);
00169
00170 pairwise_matcher_index_ = pairwise_matcher_index;
00171 }
00172
00173 void KeyframeGraphDetector::generateKeyframeAssociations(
00174 KeyframeVector& keyframes,
00175 KeyframeAssociationVector& associations)
00176 {
00177
00178 prepareFeaturesForRANSAC(keyframes);
00179
00180 buildAssociationMatrix(keyframes, associations);
00181 }
00182 bool first = true;
00183 void KeyframeGraphDetector::generateKeyframeAssociations_Iterative(
00184 KeyframeVector& keyframes,
00185 KeyframeAssociationVector& associations)
00186 {
00187 if(first == true)
00188 {
00189 n_original_poses = keyframes.size();
00190 first = false;
00191 }
00192
00193 prepareFeaturesForRANSAC(keyframes);
00194
00195 buildAssociationMatrix_Iterative(keyframes, associations);
00196 }
00197
00198 void KeyframeGraphDetector::prepareMatchers(
00199 const KeyframeVector& keyframes)
00200 {
00201 if(verbose_) printf("training individual keyframe matchers ...\n");
00202
00203 matchers_.clear();
00204 matchers_.resize(keyframes.size());
00205
00206 for (unsigned int kf_idx = 0; kf_idx < keyframes.size(); kf_idx++)
00207 {
00208 const RGBDKeyframe& keyframe = keyframes[kf_idx];
00209 cv::FlannBasedMatcher& matcher = matchers_[kf_idx];
00210
00211
00212 cv::Ptr<cv::flann::IndexParams> indexParams;
00213
00214 if (pairwise_matcher_index_ == PAIRWISE_MATCHER_LINEAR)
00215 indexParams = new cv::flann::LinearIndexParams();
00216 else if (pairwise_matcher_index_ == PAIRWISE_MATCHER_KDTREE)
00217 indexParams = new cv::flann::KDTreeIndexParams();
00218
00219 cv::Ptr<cv::flann::SearchParams> searchParams = new cv::flann::SearchParams(32);
00220
00221 matcher = cv::FlannBasedMatcher(indexParams, searchParams);
00222
00223
00224 std::vector<cv::Mat> descriptors_vector;
00225 descriptors_vector.push_back(keyframe.descriptors);
00226 matcher.add(descriptors_vector);
00227 matcher.train();
00228 }
00229 }
00230 void KeyframeGraphDetector::prepareFeaturesForRANSAC_Iterative(u_int kf_idx,
00231 KeyframeVector& keyframes)
00232 {
00233 bool upright = true;
00234 double min_surf_threshold = 25;
00235
00236 if(verbose_) printf("preparing SURF features for matching...\n");
00237 cv::SurfDescriptorExtractor extractor;
00238
00239
00240 RGBDKeyframe& keyframe = keyframes[kf_idx];
00241
00242 double surf_threshold = init_surf_threshold_;
00243
00244 while (surf_threshold >= min_surf_threshold)
00245 {
00246 cv::SurfFeatureDetector detector(surf_threshold, 4, 2, true, upright);
00247 keyframe.keypoints.clear();
00248 detector.detect(keyframe.rgb_img, keyframe.keypoints);
00249
00250 if ((int)keyframe.keypoints.size() < n_keypoints_)
00251 {
00252 if(verbose_)
00253 printf("[KF %d of %d] %d SURF keypoints detected (threshold: %.1f)\n",
00254 (int)kf_idx+1, (int)keyframes.size(),
00255 (int)keyframe.keypoints.size(), surf_threshold);
00256
00257 surf_threshold /= 2.0;
00258 }
00259 else
00260 {
00261 keyframe.keypoints.resize(n_keypoints_);
00262
00263 if(verbose_)
00264 printf("[KF %d of %d] %d SURF keypoints detected (threshold: %.1f)\n",
00265 (int)kf_idx+1, (int)keyframes.size(),
00266 (int)keyframe.keypoints.size(), surf_threshold);
00267
00268 break;
00269 }
00270 }
00271
00272 extractor.compute(keyframe.rgb_img, keyframe.keypoints, keyframe.descriptors);
00273 keyframe.computeDistributions(20,20);
00274 }
00275
00276 void KeyframeGraphDetector::prepareFeaturesForRANSAC(
00277 KeyframeVector& keyframes)
00278 {
00279 bool upright = true;
00280 double min_surf_threshold = 25;
00281
00282 if(verbose_) printf("preparing SURF features for matching...\n");
00283
00284 cv::SurfDescriptorExtractor extractor;
00285
00286 for (unsigned int kf_idx = 0; kf_idx < keyframes.size(); kf_idx++)
00287 {
00288 RGBDKeyframe& keyframe = keyframes[kf_idx];
00289
00290
00291
00292
00293
00294
00295
00296 double surf_threshold = init_surf_threshold_;
00297
00298 while (surf_threshold >= min_surf_threshold)
00299 {
00300 cv::SurfFeatureDetector detector(surf_threshold, 4, 2, true, upright);
00301 keyframe.keypoints.clear();
00302 detector.detect(keyframe.rgb_img, keyframe.keypoints);
00303
00304 if ((int)keyframe.keypoints.size() < n_keypoints_)
00305 {
00306 if(verbose_)
00307 printf("[KF %d of %d] %d SURF keypoints detected (threshold: %.1f)\n",
00308 (int)kf_idx+1, (int)keyframes.size(),
00309 (int)keyframe.keypoints.size(), surf_threshold);
00310
00311 surf_threshold /= 2.0;
00312 }
00313 else
00314 {
00315 keyframe.keypoints.resize(n_keypoints_);
00316
00317 if(verbose_)
00318 printf("[KF %d of %d] %d SURF keypoints detected (threshold: %.1f)\n",
00319 (int)kf_idx+1, (int)keyframes.size(),
00320 (int)keyframe.keypoints.size(), surf_threshold);
00321
00322 break;
00323 }
00324 }
00325
00326 if (sac_save_results_)
00327 {
00328 cv::Mat kp_img;
00329 cv::drawKeypoints(keyframe.rgb_img, keyframe.keypoints, kp_img);
00330 std::stringstream ss1;
00331 ss1 << "kp_" << kf_idx;
00332 cv::imwrite(output_path_ + "/" + ss1.str() + ".png", kp_img);
00333 }
00334
00335 extractor.compute(keyframe.rgb_img, keyframe.keypoints, keyframe.descriptors);
00336 keyframe.computeDistributions(20,20);
00337 }
00338 }
00339
00340 void KeyframeGraphDetector::prepareFeaturesForRANSAC_mine(
00341 KeyframeVector& keyframes)
00342 {
00343 bool upright = true;
00344
00345 if(verbose_) printf("preparing SURF features for matching...\n");
00346
00347 cv::SurfDescriptorExtractor extractor;
00348
00349 for (unsigned int kf_idx = 0; kf_idx < keyframes.size(); kf_idx++)
00350 {
00351 RGBDKeyframe& keyframe = keyframes[kf_idx];
00352
00353 double surf_threshold = init_surf_threshold_;
00354
00355
00356 cv::SurfFeatureDetector detector(surf_threshold, 4, 2, true, upright);
00357 keyframe.keypoints.clear();
00358 detector.detect(keyframe.rgb_img, keyframe.keypoints);
00359
00360
00361
00362 keyframe.keypoints.resize(n_keypoints_);
00363
00364 if(verbose_)
00365 printf("[KF %d of %d] %d SURF keypoints detected\n",
00366 (int)kf_idx+1, (int)keyframes.size(),
00367 (int)keyframe.keypoints.size());
00368
00369
00370 if (sac_save_results_)
00371 {
00372 cv::Mat kp_img;
00373 cv::drawKeypoints(keyframe.rgb_img, keyframe.keypoints, kp_img);
00374 std::stringstream ss1;
00375 ss1 << "kp_" << kf_idx;
00376 cv::imwrite(output_path_ + "/" + ss1.str() + ".png", kp_img);
00377 }
00378
00379 extractor.compute(keyframe.rgb_img, keyframe.keypoints, keyframe.descriptors);
00380 keyframe.computeDistributions();
00381 }
00382 }
00383
00384
00385 void KeyframeGraphDetector::buildAssociationMatrix(
00386 const KeyframeVector& keyframes,
00387 KeyframeAssociationVector& associations)
00388 {
00389 prepareMatchers(keyframes);
00390
00391
00392 buildCandidateMatrix(keyframes);
00393
00394
00395
00396 buildCorrespondenceMatrix_mine(keyframes,associations);
00397
00398 }
00399 void KeyframeGraphDetector::buildAssociationMatrix_Iterative(
00400 const KeyframeVector& keyframes,
00401 KeyframeAssociationVector& associations)
00402 {
00403 prepareMatchers(keyframes);
00404
00405
00406 buildCandidateMatrix(keyframes);
00407
00408 }
00409 void KeyframeGraphDetector::buildCandidateMatrix(
00410 const KeyframeVector& keyframes)
00411 {
00412 if (candidate_method_ == CANDIDATE_GENERATION_BRUTE_FORCE)
00413 {
00414
00415 int size = keyframes.size();
00416 candidate_matrix_ = cv::Mat::ones(size, size, CV_8UC1);
00417 }
00418 else if (candidate_method_ == CANDIDATE_GENERATION_SURF_TREE)
00419 {
00420
00421 buildMatchMatrixSurfTree(keyframes);
00422
00423
00424 buildCandidateMatrixSurfTree();
00425 }
00426 }
00432 cv::FlannBasedMatcher matcher;
00433 void KeyframeGraphDetector::buildMatchMatrixSurfTree_Iterative(unsigned int kf_idx,
00434 const KeyframeVector& keyframes)
00435 {
00436 if(match_matrix_.cols == 0)
00437 match_matrix_ = cv::Mat::zeros(1000, 1000, CV_16UC1);
00438
00439
00440 unsigned int kf_size = keyframes.size();
00441
00442
00443
00444 int max,min;
00445 if (!mapping_)
00446 {
00447 min = 0;
00448 max = n_original_poses;
00449 }
00450 else
00451 {
00452 min = keyframes.size() -1;
00453 max = keyframes.size();
00454 }
00455 trainSURFMatcher_Iterative(keyframes,min, max, matcher);
00456
00457
00458
00459 if(verbose_) printf("Keyframe lookups...\n");
00460
00461
00462 if(verbose_)
00463 printf("[KF %d of %d]: Computing SURF neighbors\n", (int)kf_idx+1, (int)kf_size);
00464 const RGBDFrame& keyframe = keyframes[kf_idx];
00465
00466
00467 std::vector<std::vector<cv::DMatch> > matches_vector;
00468 matcher.knnMatch(keyframe.descriptors, matches_vector, k_nearest_neighbors_);
00469
00470
00471 std::vector<std::pair<int, int> > bins;
00472 bins.resize(kf_size);
00473 for (unsigned int b = 0; b < bins.size(); ++b)
00474 bins[b] = std::pair<int, int>(0, b);
00475
00476
00477 for (unsigned int j = 0; j < matches_vector.size(); ++j)
00478 {
00479 std::vector<cv::DMatch>& matches = matches_vector[j];
00480 for (unsigned int k = 0; k < matches.size(); ++k)
00481 {
00482 if( !mapping_ && bins[matches[k].imgIdx].second >= n_original_poses)
00483 continue;
00484 bins[matches[k].imgIdx].first++;
00485 }
00486 }
00487
00488 for (unsigned int b = 0; b < kf_size; ++b)
00489 {
00490 unsigned int index_a = kf_idx;
00491 unsigned int index_b = bins[b].second;
00492 int corresp_count = bins[b].first;
00493
00494 if (index_a != index_b)
00495 match_matrix_.at<uint16_t>(index_a, index_b) = corresp_count;
00496
00497 }
00498
00499 }
00500
00506 void KeyframeGraphDetector::buildMatchMatrixSurfTree(
00507 const KeyframeVector& keyframes)
00508 {
00509 unsigned int kf_size = keyframes.size();
00510
00511
00512 cv::FlannBasedMatcher matcher;
00513 trainSURFMatcher(keyframes, matcher);
00514
00515
00516 if(verbose_) printf("Keyframe lookups...\n");
00517
00518 match_matrix_ = cv::Mat::zeros(kf_size, kf_size, CV_16UC1);
00519 for (unsigned int kf_idx = 0; kf_idx < kf_size; ++kf_idx)
00520 {
00521 if(verbose_)
00522 printf("[KF %d of %d]: Computing SURF neighbors\n", (int)kf_idx+1, (int)kf_size);
00523 const RGBDFrame& keyframe = keyframes[kf_idx];
00524
00525
00526 std::vector<std::vector<cv::DMatch> > matches_vector;
00527 matcher.knnMatch(keyframe.descriptors, matches_vector, k_nearest_neighbors_);
00528
00529
00530 std::vector<std::pair<int, int> > bins;
00531 bins.resize(kf_size);
00532 for (unsigned int b = 0; b < bins.size(); ++b)
00533 bins[b] = std::pair<int, int>(0, b);
00534
00535
00536 for (unsigned int j = 0; j < matches_vector.size(); ++j)
00537 {
00538 std::vector<cv::DMatch>& matches = matches_vector[j];
00539 for (unsigned int k = 0; k < matches.size(); ++k)
00540 {
00541 bins[matches[k].imgIdx].first++;
00542 }
00543 }
00544
00545 for (unsigned int b = 0; b < kf_size; ++b)
00546 {
00547 unsigned int index_a = kf_idx;
00548 unsigned int index_b = bins[b].second;
00549 int corresp_count = bins[b].first;
00550
00551 if (index_a != index_b)
00552 match_matrix_.at<uint16_t>(index_a, index_b) = corresp_count;
00553 }
00554 }
00555 }
00559 void KeyframeGraphDetector::buildCandidateMatrixSurfTree_Iterative(int v)
00560 {
00561
00562 assert(match_matrix_.rows == match_matrix_.cols);
00563
00564
00565 int size = match_matrix_.rows;
00566 int temp_n_candidates_ = n_candidates_;
00567 if(n_candidates_ > size)
00568 {
00569 temp_n_candidates_ = size;
00570 }
00571 assert(temp_n_candidates_ <= size);
00572
00573
00574 candidate_matrix_ = cv::Mat::eye(match_matrix_.size(), CV_8UC1);
00575
00576
00577 std::vector<std::pair<int, int> > values(match_matrix_.cols);
00578 for (int u = 0; u < match_matrix_.cols; ++u)
00579 {
00580 int value = match_matrix_.at<uint16_t>(v,u);
00581 values[u] = std::pair<int, int>(value, u);
00582 }
00583
00584
00585 std::sort(values.begin(), values.end(), std::greater<std::pair<int, int> >());
00586
00587
00588 for (int u = 0; u < temp_n_candidates_; ++u)
00589 {
00590 if (values[u].first == 0) continue;
00591 if (!mapping_ && values[u].second >= n_original_poses)
00592 {
00593 temp_n_candidates_++;
00594 continue;
00595 }
00596 unsigned int uc = values[u].second;
00597 candidate_matrix_.at<uint8_t>(v,uc) = 1;
00598 std::cout << v << " with " << uc <<std::endl;
00599 }
00600
00601 }
00605 void KeyframeGraphDetector::buildCandidateMatrixSurfTree()
00606 {
00607
00608 assert(match_matrix_.rows == match_matrix_.cols);
00609
00610
00611 int size = match_matrix_.rows;
00612 int temp_n_candidates_ = n_candidates_;
00613 if(n_candidates_ > size)
00614 {
00615 temp_n_candidates_ = size;
00616 }
00617 assert(temp_n_candidates_ <= size);
00618
00619
00620 candidate_matrix_ = cv::Mat::eye(match_matrix_.size(), CV_8UC1);
00621
00622 for (int v = 0; v < match_matrix_.rows; ++v)
00623 {
00624
00625 std::vector<std::pair<int, int> > values(match_matrix_.cols);
00626 for (int u = 0; u < match_matrix_.cols; ++u)
00627 {
00628 int value = match_matrix_.at<uint16_t>(v,u);
00629 values[u] = std::pair<int, int>(value, u);
00630 }
00631
00632
00633 std::sort(values.begin(), values.end(), std::greater<std::pair<int, int> >());
00634
00635
00636 for (int u = 0; u < temp_n_candidates_; ++u)
00637 {
00638 if (values[u].first == 0) continue;
00639 unsigned int uc = values[u].second;
00640 candidate_matrix_.at<uint8_t>(v,uc) = 1;
00641 }
00642 }
00643 }
00644 void KeyframeGraphDetector::buildCorrespondenceMatrix(
00645 const KeyframeVector& keyframes,
00646 KeyframeAssociationVector& associations)
00647 {
00648
00649 assert(candidate_matrix_.rows == candidate_matrix_.cols);
00650 int size = candidate_matrix_.rows;
00651
00652
00653 correspondence_matrix_ = cv::Mat::zeros(size, size, CV_16UC1);
00654 association_matrix_ = cv::Mat::zeros(size, size, CV_8UC1);
00655
00656 for (int kf_idx_q = 0; kf_idx_q < size; ++kf_idx_q)
00657 for (int kf_idx_t = 0; kf_idx_t < size; ++kf_idx_t)
00658 {
00659 const RGBDKeyframe& keyframe_q = keyframes[kf_idx_q];
00660 const RGBDKeyframe& keyframe_t = keyframes[kf_idx_t];
00661
00662 if (kf_idx_q == kf_idx_t)
00663 {
00664
00665
00666
00667 correspondence_matrix_.at<uint16_t>(kf_idx_q, kf_idx_q) = keyframe_q.n_valid_keypoints;
00668
00669 association_matrix_.at<uint8_t>(kf_idx_q, kf_idx_q) = 1;
00670 }
00671 else
00672 {
00673
00674 if (candidate_matrix_.at<uint8_t>(kf_idx_q, kf_idx_t) != 0)
00675 {
00676 if(verbose_) printf("[RANSAC %d to %d]: ", kf_idx_q, kf_idx_t);
00677
00678 std::vector<cv::DMatch> inlier_matches;
00679
00680
00681 Eigen::Matrix4f transformation;
00682
00683
00684 int iterations = pairwiseMatching(
00685 kf_idx_q, kf_idx_t, keyframes, inlier_matches, transformation);
00686
00687 correspondence_matrix_.at<uint16_t>(kf_idx_q, kf_idx_t) = inlier_matches.size();
00688
00689 if (inlier_matches.size() >= sac_min_inliers_)
00690 {
00691
00692 association_matrix_.at<uint8_t>(kf_idx_q, kf_idx_t) = 1;
00693
00694
00695 KeyframeAssociation association;
00696 association.type = KeyframeAssociation::RANSAC;
00697 association.kf_idx_a = kf_idx_t;
00698 association.kf_idx_b = kf_idx_q;
00699 association.matches = inlier_matches;
00700 association.a2b = transformation;
00701 associations.push_back(association);
00702
00703
00704 if(verbose_)
00705 printf("pass [%d][%d]\n", iterations, (int)inlier_matches.size());
00706
00707
00708 if (sac_save_results_)
00709 {
00710 cv::Mat img_matches;
00711 cv::drawMatches(keyframe_q.rgb_img, keyframe_q.keypoints,
00712 keyframe_t.rgb_img, keyframe_t.keypoints,
00713 inlier_matches, img_matches);
00714
00715 std::stringstream ss1;
00716 ss1 << kf_idx_q << "_to_" << kf_idx_t;
00717 cv::imwrite(output_path_ + "/" + ss1.str() + ".png", img_matches);
00718 }
00719 }
00720 else
00721 {
00722 association_matrix_.at<uint8_t>(kf_idx_q, kf_idx_t) = 0;
00723
00724 if(verbose_)
00725 printf("fail [%d][%d]\n", iterations, (int)inlier_matches.size());
00726 }
00727 }
00728 }
00729 }
00730 }
00731 void KeyframeGraphDetector::buildCorrespondenceMatrix_onlyLandmarks(
00732 const KeyframeVector& keyframes,
00733 KeyframeAssociationVector& associations)
00734 {
00735
00736 assert(candidate_matrix_.rows == candidate_matrix_.cols);
00737 int size = candidate_matrix_.rows;
00738
00739
00740 correspondence_matrix_ = cv::Mat::zeros(size, size, CV_16UC1);
00741 association_matrix_ = cv::Mat::zeros(size, size, CV_8UC1);
00742
00743 RobustMatcher rmatcher;
00744 rmatcher.setConfidenceLevel(0.98);
00745 rmatcher.setMinDistanceToEpipolar(2.0);
00746 rmatcher.setRatio(1.00f);
00747 rmatcher.setVerbose(false);
00748 for (int kf_idx_q = 0; kf_idx_q < size; ++kf_idx_q)
00749 for (int kf_idx_t = 0; kf_idx_t < size; ++kf_idx_t)
00750 {
00751 const RGBDKeyframe& keyframe_q = keyframes[kf_idx_q];
00752 const RGBDKeyframe& keyframe_t = keyframes[kf_idx_t];
00753
00754 if (kf_idx_q == kf_idx_t)
00755 {
00756
00757
00758 correspondence_matrix_.at<uint16_t>(kf_idx_q, kf_idx_q) = keyframe_q.n_valid_keypoints;
00759
00760 association_matrix_.at<uint8_t>(kf_idx_q, kf_idx_q) = 1;
00761 }
00762 else
00763 {
00764
00765 if (candidate_matrix_.at<uint8_t>(kf_idx_q, kf_idx_t) != 0)
00766 {
00767 std::vector<cv::DMatch> inlier_matches;
00768
00769
00770
00771 std::vector<cv::DMatch> matches_r;
00772 std::vector<cv::KeyPoint> kp1,kp2;
00773 kp1 = keyframe_q.keypoints;
00774 kp2 = keyframe_t.keypoints;
00775 cv::Mat fundemental = rmatcher.match(matches_r,kp1,kp2,keyframe_q.descriptors,keyframe_t.descriptors);
00776 if(matches_r.size() < n_matches_accept)
00777 {
00778 association_matrix_.at<uint8_t>(kf_idx_q, kf_idx_t) = 0;
00779
00780 if(verbose_)
00781 printf("[%d to %d] Fail: Not enough matches [%d]\n", kf_idx_q,kf_idx_t,(int)matches_r.size());
00782 continue;
00783 }
00784
00785 for (u_int i = 0; i < matches_r.size(); i++)
00786 {
00787 if (keyframe_q.kp_valid[matches_r[i].queryIdx]==true && keyframe_t.kp_valid[matches_r[i].trainIdx]==true )
00788 inlier_matches.push_back(matches_r[i]);
00789 }
00790 correspondence_matrix_.at<uint16_t>(kf_idx_q, kf_idx_t) = inlier_matches.size();
00791 if (inlier_matches.size() >= sac_min_inliers_)
00792 {
00793
00794 association_matrix_.at<uint8_t>(kf_idx_q, kf_idx_t) = 1;
00795 Eigen::Matrix4f transformation;
00796 transformation.setIdentity();
00797
00798
00799 KeyframeAssociation association;
00800 association.type = KeyframeAssociation::LANDMARKS;
00801 association.kf_idx_a = kf_idx_t;
00802 association.kf_idx_b = kf_idx_q;
00803 association.matches = inlier_matches;
00804 association.a2b = transformation;
00805 associations.push_back(association);
00806
00807
00808 if(verbose_)
00809 printf("[%d to %d] Pass: Matches [%d]\n", kf_idx_q,kf_idx_t, (int)matches_r.size());
00810
00811 }
00812
00813
00814
00815 }
00816 }
00817 }
00818 }
00819
00820 void KeyframeGraphDetector::buildCorrespondenceMatrix_mine(
00821 const KeyframeVector& keyframes,
00822 KeyframeAssociationVector& associations)
00823 {
00824
00825 assert(candidate_matrix_.rows == candidate_matrix_.cols);
00826 int size = candidate_matrix_.rows;
00827
00828
00829 correspondence_matrix_ = cv::Mat::zeros(size, size, CV_16UC1);
00830 association_matrix_ = cv::Mat::zeros(size, size, CV_8UC1);
00831
00832 RobustMatcher rmatcher;
00833 rmatcher.setConfidenceLevel(0.98);
00834 rmatcher.setMinDistanceToEpipolar(2.0);
00835 rmatcher.setRatio(1.00f);
00836 rmatcher.setVerbose(false);
00837 for (int kf_idx_q = 0; kf_idx_q < size; ++kf_idx_q)
00838 for (int kf_idx_t = 0; kf_idx_t < size; ++kf_idx_t)
00839 {
00840 const RGBDKeyframe& keyframe_q = keyframes[kf_idx_q];
00841 const RGBDKeyframe& keyframe_t = keyframes[kf_idx_t];
00842
00843 if (kf_idx_q == kf_idx_t)
00844 {
00845
00846
00847 correspondence_matrix_.at<uint16_t>(kf_idx_q, kf_idx_q) = keyframe_q.n_valid_keypoints;
00848
00849 association_matrix_.at<uint8_t>(kf_idx_q, kf_idx_q) = 1;
00850 }
00851 else
00852 {
00853
00854 if (candidate_matrix_.at<uint8_t>(kf_idx_q, kf_idx_t) != 0)
00855 {
00856 if(verbose_) printf("[RANSAC %d to %d]: ", kf_idx_q, kf_idx_t);
00857
00858 std::vector<cv::DMatch> inlier_matches;
00859
00860
00861 Eigen::Matrix4f transformation;
00862
00863
00864
00865
00866
00867 std::vector<cv::DMatch> matches_r;
00868 std::vector<cv::KeyPoint> kp1,kp2;
00869 kp1 = keyframe_q.keypoints;
00870 kp2 = keyframe_t.keypoints;
00871 cv::Mat fundemental = rmatcher.match(matches_r,kp1,kp2,keyframe_q.descriptors,keyframe_t.descriptors);
00872 if(matches_r.size() < n_matches_accept)
00873 {
00874 association_matrix_.at<uint8_t>(kf_idx_q, kf_idx_t) = 0;
00875
00876
00877 if(verbose_)
00878 printf("fail: Not enough matches [%d]\n", (int)matches_r.size());
00879 if(matches_r.size() == 0)
00880 continue;
00881 if (sac_save_results_)
00882 {
00883 std::vector<cv::Point2f> points1, points2;
00884 cv::Mat image1;
00885 keyframe_q.rgb_img.copyTo(image1);
00886 cv::Mat image2;
00887 keyframe_t.rgb_img.copyTo(image2);
00888
00889 for (std::vector<cv::DMatch>::const_iterator it= matches_r.begin();
00890 it!= matches_r.end(); ++it) {
00891
00892
00893 float x= kp1[it->queryIdx].pt.x;
00894 float y= kp1[it->queryIdx].pt.y;
00895 points1.push_back(cv::Point2f(x,y));
00896 cv::circle(image1,cv::Point(x,y),3,cv::Scalar(255,255,255),3);
00897
00898 x= kp2[it->trainIdx].pt.x;
00899 y= kp2[it->trainIdx].pt.y;
00900 cv::circle(image2,cv::Point(x,y),3,cv::Scalar(255,255,255),3);
00901 points2.push_back(cv::Point2f(x,y));
00902 }
00903
00904
00905 std::vector<cv::Vec3f> lines1;
00906 cv::computeCorrespondEpilines(cv::Mat(points1),1,fundemental,lines1);
00907
00908 for (std::vector<cv::Vec3f>::const_iterator it= lines1.begin();
00909 it!=lines1.end(); ++it) {
00910
00911 cv::line(image2,cv::Point(0,-(*it)[2]/(*it)[1]),
00912 cv::Point(image2.cols,-((*it)[2]+(*it)[0]*image2.cols)/(*it)[1]),
00913 cv::Scalar(255,255,255));
00914 }
00915
00916 std::vector<cv::Vec3f> lines2;
00917 cv::computeCorrespondEpilines(cv::Mat(points2),2,fundemental,lines2);
00918
00919 for (std::vector<cv::Vec3f>::const_iterator it= lines2.begin();
00920 it!=lines2.end(); ++it) {
00921
00922 cv::line(image1,cv::Point(0,-(*it)[2]/(*it)[1]),
00923 cv::Point(image1.cols,-((*it)[2]+(*it)[0]*image1.cols)/(*it)[1]),
00924 cv::Scalar(255,255,255));
00925 }
00926 cv::Mat outImg,outImg1,outImg2;
00927 cv::Size size( image1.cols + image2.cols, MAX(image1.rows, image2.rows) );
00928 outImg.create( size, CV_MAKETYPE(image1.depth(), 3) );
00929 outImg1 = outImg( cv::Rect(0, 0, image1.cols, image1.rows) );
00930 outImg2 = outImg( cv::Rect(image1.cols, 0, image2.cols, image2.rows) );
00931 image1.copyTo( outImg1 );
00932 image2.copyTo( outImg2 );
00933 std::stringstream ss1;
00934 ss1 << kf_idx_q << "_to_" << kf_idx_t << "_fail_matches[" << matches_r.size() << "].png";
00935 cv::imwrite(output_path_ + "/" + ss1.str() , outImg);
00936 }
00937 continue;
00938 }
00939 DMatchVector best_inlier_matches;
00940
00941
00942 int iterations = pairwiseMatchingRANSAC(
00943 kf_idx_q, kf_idx_t, keyframes, best_inlier_matches, transformation);
00944 inlier_matches = best_inlier_matches;
00945 correspondence_matrix_.at<uint16_t>(kf_idx_q, kf_idx_t) = inlier_matches.size();
00946
00947
00948
00949
00950
00951
00952
00953
00954 if (inlier_matches.size() >= sac_min_inliers_)
00955 {
00956
00957 association_matrix_.at<uint8_t>(kf_idx_q, kf_idx_t) = 1;
00958
00959
00960
00961 KeyframeAssociation association;
00962 association.type = KeyframeAssociation::RANSAC;
00963 association.kf_idx_a = kf_idx_t;
00964 association.kf_idx_b = kf_idx_q;
00965 association.matches = inlier_matches;
00966 association.a2b = transformation;
00967 associations.push_back(association);
00968
00969
00970 if(verbose_)
00971 printf("pass [%d][%d]\n", iterations, (int)inlier_matches.size());
00972
00973
00974 if (sac_save_results_)
00975 {
00976 std::vector<cv::Point2f> points1, points2;
00977 cv::Mat image1;
00978 keyframe_q.rgb_img.copyTo(image1);
00979 cv::Mat image2;
00980 keyframe_t.rgb_img.copyTo(image2);
00981
00982 for (std::vector<cv::DMatch>::const_iterator it= inlier_matches.begin();
00983 it!= inlier_matches.end(); ++it) {
00984
00985
00986 float x= kp1[it->queryIdx].pt.x;
00987 float y= kp1[it->queryIdx].pt.y;
00988 points1.push_back(cv::Point2f(x,y));
00989 cv::circle(image1,cv::Point(x,y),3,cv::Scalar(255,255,255),3);
00990
00991 x= kp2[it->trainIdx].pt.x;
00992 y= kp2[it->trainIdx].pt.y;
00993 cv::circle(image2,cv::Point(x,y),3,cv::Scalar(255,255,255),3);
00994 points2.push_back(cv::Point2f(x,y));
00995 }
00996
00997
00998 std::vector<cv::Vec3f> lines1;
00999 cv::computeCorrespondEpilines(cv::Mat(points1),1,fundemental,lines1);
01000
01001 for (std::vector<cv::Vec3f>::const_iterator it= lines1.begin();
01002 it!=lines1.end(); ++it) {
01003
01004 cv::line(image2,cv::Point(0,-(*it)[2]/(*it)[1]),
01005 cv::Point(image2.cols,-((*it)[2]+(*it)[0]*image2.cols)/(*it)[1]),
01006 cv::Scalar(255,255,255));
01007 }
01008
01009 std::vector<cv::Vec3f> lines2;
01010 cv::computeCorrespondEpilines(cv::Mat(points2),2,fundemental,lines2);
01011
01012 for (std::vector<cv::Vec3f>::const_iterator it= lines2.begin();
01013 it!=lines2.end(); ++it) {
01014
01015 cv::line(image1,cv::Point(0,-(*it)[2]/(*it)[1]),
01016 cv::Point(image1.cols,-((*it)[2]+(*it)[0]*image1.cols)/(*it)[1]),
01017 cv::Scalar(255,255,255));
01018 }
01019 cv::Mat outImg,outImg1,outImg2;
01020 cv::Size size( image1.cols + image2.cols, MAX(image1.rows, image2.rows) );
01021 outImg.create( size, CV_MAKETYPE(image1.depth(), 3) );
01022 outImg1 = outImg( cv::Rect(0, 0, image1.cols, image1.rows) );
01023 outImg2 = outImg( cv::Rect(image1.cols, 0, image2.cols, image2.rows) );
01024 image1.copyTo( outImg1 );
01025 image2.copyTo( outImg2 );
01026 std::stringstream ss1;
01027 ss1 << kf_idx_q << "_to_" << kf_idx_t << "_OK[" << inlier_matches.size() << "].png";
01028 cv::imwrite(output_path_ + "/" + ss1.str() , outImg);
01029 }
01030 }
01031 else
01032 {
01033 if(matches_r.size() >= n_matches_accept)
01034 {
01035 std::vector<cv::DMatch> final_matches;
01036 for (u_int i=0; i<matches_r.size();i++)
01037 {
01038 if (keyframe_t.kp_valid[matches_r[i].trainIdx] && keyframe_q.kp_valid[matches_r[i].queryIdx])
01039 final_matches.push_back(matches_r[i]);
01040 }
01041 if(final_matches.size()==0)
01042 continue;
01043 association_matrix_.at<uint8_t>(kf_idx_q, kf_idx_t) = 1;
01044 KeyframeAssociation association;
01045 association.type = KeyframeAssociation::LANDMARKS;
01046 association.kf_idx_a = kf_idx_t;
01047 association.kf_idx_b = kf_idx_q;
01048 association.matches = final_matches;
01049 association.a2b = transformation;
01050 associations.push_back(association);
01051
01052 if(verbose_)
01053 printf("fail [%d][%d] - Accepted\n", iterations, (int)final_matches.size());
01054 }
01055 else
01056 {
01057 if(verbose_)
01058 printf("fail [%d][%d]\n", iterations, (int)inlier_matches.size());
01059 }
01060 if (sac_save_results_)
01061 {
01062
01063
01064
01065 cv::Mat img_matches;
01066 std::vector<cv::KeyPoint> q_pt;
01067 std::vector<cv::KeyPoint> t_pt;
01068 std::vector<int> q_,t_;
01069 int ct=0,cq=0;
01070 if(keyframe_q.keypoints.size() != keyframe_t.keypoints.size())
01071 continue;
01072 for(u_int k = 0; k<keyframe_q.keypoints.size();k++)
01073 {
01074 if(keyframe_q.kp_valid[k]==true)
01075 {
01076 q_pt.push_back(keyframe_q.keypoints[k]);
01077 q_.push_back(k-cq);
01078 }
01079 else
01080 {
01081 cq++;
01082 q_.push_back(-1);
01083 }
01084 if(keyframe_t.kp_valid[k]==true)
01085 {
01086 t_pt.push_back(keyframe_t.keypoints[k]);
01087 t_.push_back(k-ct);
01088 }
01089 else
01090 {
01091 ct++;
01092 t_.push_back(-1);
01093 }
01094 }
01095 for(u_int k=0;k<inlier_matches.size();k++)
01096 {
01097 if(q_[inlier_matches[k].queryIdx]==-1)
01098 {
01099 printf("OOOOOOOOO");
01100 }
01101 else
01102 {
01103 inlier_matches[k].queryIdx = q_[inlier_matches[k].queryIdx];
01104 }
01105 if(t_[inlier_matches[k].trainIdx]==-1)
01106 {
01107 printf("OOOOOOOOO");
01108 }
01109 else
01110 {
01111 inlier_matches[k].trainIdx = t_[inlier_matches[k].trainIdx];
01112 }
01113 }
01114
01115 cv::drawMatches(keyframe_q.rgb_img, q_pt,
01116 keyframe_t.rgb_img, t_pt,
01117 inlier_matches, img_matches);
01118
01119 std::stringstream ss1;
01120 ss1 << kf_idx_q << "_to_" << kf_idx_t << "_fail_RANSAC[" << inlier_matches.size() << "].png";
01121 cv::imwrite(output_path_ + "/" + ss1.str(), img_matches);
01122 }
01123
01124 }
01125 }
01126 }
01127 }
01128 }
01129 void KeyframeGraphDetector::buildCorrespondenceMatrix_rgb_Iterative(u_int kf_idx_q,
01130 const KeyframeVector& keyframes,
01131 KeyframeAssociationVector& associations)
01132 {
01133
01134 assert(candidate_matrix_.rows == candidate_matrix_.cols);
01135 int size = candidate_matrix_.rows;
01136 if(size > correspondence_matrix_.cols)
01137 {
01138 if(correspondence_matrix_.cols == 0)
01139 {
01140
01141 correspondence_matrix_ = cv::Mat::zeros(1000, 1000, CV_16UC1);
01142 association_matrix_ = cv::Mat::zeros(1000, 1000, CV_8UC1);
01143 }
01144 else
01145 {
01146 std::cout << "Max number of keyframes reached." << std::endl;
01147 return;
01148 }
01149 }
01150 RobustMatcher rmatcher;
01151 rmatcher.setConfidenceLevel(0.95);
01152 rmatcher.setMinDistanceToEpipolar(2.0);
01153 rmatcher.setRatio(1.00f);
01154 rmatcher.setVerbose(false);
01155 for (int kf_idx_t = 0; kf_idx_t < size; ++kf_idx_t)
01156 {
01157 RGBDKeyframe keyframe_q = keyframes[kf_idx_t];
01158 RGBDKeyframe keyframe_t = keyframes[kf_idx_q];
01159
01160 if (kf_idx_q == kf_idx_t)
01161 {
01162
01163
01164 correspondence_matrix_.at<uint16_t>(kf_idx_q, kf_idx_q) = keyframe_q.n_valid_keypoints;
01165
01166 association_matrix_.at<uint8_t>(kf_idx_q, kf_idx_q) = 1;
01167 }
01168 else
01169 {
01170
01171 if (candidate_matrix_.at<uint8_t>(kf_idx_q, kf_idx_t) != 0)
01172 {
01173 if(verbose_) printf("[RANSAC %d to %d]: ", kf_idx_q, kf_idx_t);
01174
01175
01176 Eigen::Matrix4f transformation;
01177
01178 std::vector<cv::DMatch> matches_r;
01179 std::vector<cv::KeyPoint> kp1,kp2;
01180 kp1 = keyframe_q.keypoints;
01181 kp2 = keyframe_t.keypoints;
01182 cv::Mat fundemental = rmatcher.match(matches_r,kp1,kp2,keyframe_q.descriptors,keyframe_t.descriptors);
01183 if(matches_r.size() < n_matches_accept)
01184 {
01185 if(verbose_)
01186 printf("fail: Not enough matches [%d]\n", (int)matches_r.size());
01187 continue;
01188 }
01189 std::vector<cv::Point3f> points3d,inliers_3d;
01190 std::vector<cv::Point2f> points2d_q,points2d_t,inliers_2d;
01191 cv::Mat intr = keyframe_t.intr;
01192 cv::Mat dist = keyframe_t.dist;
01193 cv::Mat rvec,tvec;
01194 std::vector<std::vector<float> > dists;
01195
01196 for (u_int i = 0; i < matches_r.size(); i++)
01197 {
01198 cv::DMatch match = matches_r[i];
01199 cv::KeyPoint p_q,p_t;
01200 p_q = kp1[match.queryIdx];
01201 p_t = kp2[match.trainIdx];
01202 cv::Point2f pq,pt;
01203 pq = p_q.pt;
01204 pt = p_t.pt;
01205 if(pq.x < 0 || pt.x < 0 || pq.x >= 640 || pt.x >= 640 || pt.y < 0 || pq.y < 0 || pt.y >= 480 || pq.y >= 480)
01206 continue;
01207 if(!keyframe_q.kp_valid[match.queryIdx])
01208 continue;
01209 points2d_q.push_back(pq);
01210 points2d_t.push_back(pt);
01211 std::vector<float> t_dist;
01212 t_dist.push_back(keyframe_q.kp_means[match.queryIdx][0]);
01213 t_dist.push_back(keyframe_q.kp_means[match.queryIdx][1]);
01214 t_dist.push_back(keyframe_q.kp_means[match.queryIdx][2]);
01215
01216 dists.push_back(t_dist);
01217 }
01218
01219 for(u_int i = 0; i < dists.size(); i++)
01220 {
01221 cv::Point3f pt;
01222 pt.x = dists[i][0];
01223 pt.y = dists[i][1];
01224 pt.z = dists[i][2];
01225 points3d.push_back(pt);
01226 }
01227
01228 assert(points3d.size() == points2d_t.size());
01229 if(points3d.size() < 30)
01230 {
01231 association_matrix_.at<uint8_t>(kf_idx_q, kf_idx_t) = 0;
01232
01233 if(verbose_)
01234 printf("fail: Not enough points [%d]\n", (int)points3d.size());
01235 continue;
01236 }
01237 std::vector<int> inliers;
01238
01239 cv::solvePnPRansac(points3d,points2d_t,intr,dist,rvec,tvec,false,200,4,100,inliers,CV_EPNP);
01240 for(u_int i = 0; i < inliers.size(); i++)
01241 {
01242 inliers_3d.push_back(points3d[inliers[i]]);
01243 inliers_2d.push_back(points2d_t[inliers[i]]);
01244 }
01245
01246 if(tvec.at<double>(0,0) == 0 && tvec.at<double>(0,1) == 0 && tvec.at<double>(0,2) == 0)
01247 {
01248 association_matrix_.at<uint8_t>(kf_idx_q, kf_idx_t) = 0;
01249
01250 if(verbose_)
01251 printf("fail: Bad estimate \n");
01252 continue;
01253 }
01254
01255 cv::Mat rmat;
01256 cv::Rodrigues(rvec,rmat);
01257
01258 std::vector<cv::Point2f> reproj_points;
01259 cv::projectPoints(inliers_3d,rvec,tvec,intr,dist,reproj_points);
01260 double error = 0;
01261 for(u_int i = 0; i < reproj_points.size(); i++)
01262 {
01263 error += std::abs(reproj_points[i].x - inliers_2d[i].x);
01264 error += std::abs(reproj_points[i].y - inliers_2d[i].y);
01265 }
01266 error /= reproj_points.size();
01267 if (error > 3)
01268 {
01269 association_matrix_.at<uint8_t>(kf_idx_q, kf_idx_t) = 0;
01270
01271 if(verbose_)
01272 printf("fail: Reprojection Error above threshold [%d]\n", (int)error);
01273 continue;
01274 }
01275 std::cout << error << std::endl;
01276 rmat = rmat.t();
01277 tvec = rmat*-tvec;
01278
01279 transformation(0,0) = rmat.at<double>(0,0);
01280 transformation(1,0) = rmat.at<double>(1,0);
01281 transformation(2,0) = rmat.at<double>(2,0);
01282 transformation(0,1) = rmat.at<double>(0,1);
01283 transformation(1,1) = rmat.at<double>(1,1);
01284 transformation(2,1) = rmat.at<double>(2,1);
01285 transformation(0,2) = rmat.at<double>(0,2);
01286 transformation(1,2) = rmat.at<double>(1,2);
01287 transformation(2,2) = rmat.at<double>(2,2);
01288 transformation(3,0) = transformation(3,1) = transformation(3,2) = 0;
01289 transformation(3,3) = 1;
01290 transformation(0,3) = tvec.at<double>(0,0);
01291 transformation(1,3) = tvec.at<double>(0,1);
01292 transformation(2,3) = tvec.at<double>(0,2);
01293 association_matrix_.at<uint8_t>(kf_idx_q, kf_idx_t) = 1;
01294
01295
01296 KeyframeAssociation association;
01297 association.type = KeyframeAssociation::RANSAC;
01298 association.kf_idx_a = kf_idx_t;
01299 association.kf_idx_b = kf_idx_q;
01300 association.matches = matches_r;
01301 association.a2b = transformation;
01302 associations.push_back(association);
01303
01304
01305 if(verbose_)
01306 printf("pass [-][%d]\n", (int)matches_r.size());
01307
01308 }
01309 }
01310 }
01311 }
01312
01313 void KeyframeGraphDetector::buildCorrespondenceMatrix_mine_Iterative(u_int kf_idx_q,
01314 const KeyframeVector& keyframes,
01315 KeyframeAssociationVector& associations)
01316 {
01317
01318 assert(candidate_matrix_.rows == candidate_matrix_.cols);
01319 int size = candidate_matrix_.rows;
01320 if(size > correspondence_matrix_.cols)
01321 {
01322 if(correspondence_matrix_.cols == 0)
01323 {
01324
01325 correspondence_matrix_ = cv::Mat::zeros(1000, 1000, CV_16UC1);
01326 association_matrix_ = cv::Mat::zeros(1000, 1000, CV_8UC1);
01327 }
01328 else
01329 {
01330 std::cout << "Max number of keyframes reached." << std::endl;
01331 return;
01332 }
01333 }
01334 RobustMatcher rmatcher;
01335 rmatcher.setConfidenceLevel(0.98);
01336 rmatcher.setMinDistanceToEpipolar(2.0);
01337 rmatcher.setRatio(1.00f);
01338 rmatcher.setVerbose(false);
01339 for (int kf_idx_t = 0; kf_idx_t < size; ++kf_idx_t)
01340 {
01341 const RGBDKeyframe& keyframe_q = keyframes[kf_idx_q];
01342 const RGBDKeyframe& keyframe_t = keyframes[kf_idx_t];
01343
01344 if (kf_idx_q == kf_idx_t)
01345 {
01346
01347
01348 correspondence_matrix_.at<uint16_t>(kf_idx_q, kf_idx_q) = keyframe_q.n_valid_keypoints;
01349
01350 association_matrix_.at<uint8_t>(kf_idx_q, kf_idx_q) = 1;
01351 }
01352 else
01353 {
01354
01355 if (candidate_matrix_.at<uint8_t>(kf_idx_q, kf_idx_t) != 0)
01356 {
01357 if(verbose_) printf("[RANSAC %d to %d]: ", kf_idx_q, kf_idx_t);
01358
01359 std::vector<cv::DMatch> inlier_matches;
01360
01361
01362 Eigen::Matrix4f transformation;
01363
01364 std::vector<cv::DMatch> matches_r;
01365 std::vector<cv::KeyPoint> kp1,kp2;
01366 kp1 = keyframe_q.keypoints;
01367 kp2 = keyframe_t.keypoints;
01368 cv::Mat fundemental = rmatcher.match(matches_r,kp1,kp2,keyframe_q.descriptors,keyframe_t.descriptors);
01369 if(matches_r.size() < n_matches_accept)
01370 {
01371 association_matrix_.at<uint8_t>(kf_idx_q, kf_idx_t) = 0;
01372
01373 if(verbose_)
01374 printf("fail: Not enough matches [%d]\n", (int)matches_r.size());
01375 continue;
01376 }
01377 DMatchVector best_inlier_matches;
01378 int iterations = pairwiseMatchingRANSAC(
01379 kf_idx_q, kf_idx_t, keyframes, best_inlier_matches, transformation,matches_r);
01380 inlier_matches = best_inlier_matches;
01381 correspondence_matrix_.at<uint16_t>(kf_idx_q, kf_idx_t) = inlier_matches.size();
01382
01383 if (inlier_matches.size() >= sac_min_inliers_)
01384 {
01385
01386 association_matrix_.at<uint8_t>(kf_idx_q, kf_idx_t) = 1;
01387
01388
01389
01390 KeyframeAssociation association;
01391 association.type = KeyframeAssociation::RANSAC;
01392 association.kf_idx_a = kf_idx_t;
01393 association.kf_idx_b = kf_idx_q;
01394 association.matches = inlier_matches;
01395 association.a2b = transformation;
01396 associations.push_back(association);
01397
01398
01399 if(verbose_)
01400 printf("pass [%d][%d]\n", iterations, (int)inlier_matches.size());
01401 }
01402 else
01403 {
01404 if(verbose_)
01405 printf("fail: Not enough matches [%d]\n", (int)inlier_matches.size());
01406 }
01407
01408 }
01409 }
01410 }
01411 }
01412
01413
01414 void KeyframeGraphDetector::getCandidateMatches(
01415 const RGBDFrame& frame_q, const RGBDFrame& frame_t,
01416 cv::FlannBasedMatcher& matcher,
01417 DMatchVector& candidate_matches)
01418 {
01419
01420
01421
01422
01423 if (matcher_use_desc_ratio_test_)
01424 {
01425 std::vector<DMatchVector> all_matches2;
01426
01427 matcher.knnMatch(
01428 frame_q.descriptors, all_matches2, 2);
01429
01430 for (unsigned int m_idx = 0; m_idx < all_matches2.size(); ++m_idx)
01431 {
01432 const cv::DMatch& match1 = all_matches2[m_idx][0];
01433 const cv::DMatch& match2 = all_matches2[m_idx][1];
01434
01435 double ratio = match1.distance / match2.distance;
01436
01437
01438 if (ratio < matcher_max_desc_ratio_)
01439 {
01440 int idx_q = match1.queryIdx;
01441 int idx_t = match1.trainIdx;
01442
01443 if (frame_t.kp_valid[idx_t] && frame_q.kp_valid[idx_q])
01444 candidate_matches.push_back(match1);
01445 }
01446 }
01447 }
01448 else
01449 {
01450 DMatchVector all_matches;
01451
01452 matcher.match(
01453 frame_q.descriptors, all_matches);
01454
01455 for (unsigned int m_idx = 0; m_idx < all_matches.size(); ++m_idx)
01456 {
01457 const cv::DMatch& match = all_matches[m_idx];
01458
01459
01460 if (match.distance < matcher_max_desc_dist_)
01461 {
01462 int idx_q = match.queryIdx;
01463 int idx_t = match.trainIdx;
01464
01465 if (frame_t.kp_valid[idx_t] && frame_q.kp_valid[idx_q])
01466 candidate_matches.push_back(match);
01467 }
01468 }
01469 }
01470 }
01471
01472
01473 int KeyframeGraphDetector::pairwiseMatching(
01474 int kf_idx_q, int kf_idx_t,
01475 const KeyframeVector& keyframes,
01476 DMatchVector& best_inlier_matches,
01477 Eigen::Matrix4f& best_transformation)
01478 {
01479 int iterations;
01480
01481 if (pairwise_matching_method_ == PAIRWISE_MATCHING_RANSAC)
01482 {
01483 iterations = pairwiseMatchingRANSAC(
01484 kf_idx_q, kf_idx_t, keyframes, best_inlier_matches, best_transformation);
01485 }
01486 else if (pairwise_matching_method_ == PAIRWISE_MATCHING_BFSAC)
01487 {
01488 iterations = pairwiseMatchingBFSAC(
01489 kf_idx_q, kf_idx_t, keyframes, best_inlier_matches, best_transformation);
01490 }
01491
01492 return iterations;
01493 }
01494
01495
01496 int KeyframeGraphDetector::pairwiseMatchingBFSAC(
01497 int kf_idx_q, int kf_idx_t,
01498 const KeyframeVector& keyframes,
01499 DMatchVector& best_inlier_matches,
01500 Eigen::Matrix4f& best_transformation)
01501 {
01502
01503 int min_sample_size = 3;
01504
01505 const RGBDFrame& frame_t = keyframes[kf_idx_t];
01506 const RGBDFrame& frame_q = keyframes[kf_idx_q];
01507 cv::FlannBasedMatcher& matcher = matchers_[kf_idx_t];
01508
01509
01510 DMatchVector candidate_matches;
01511 getCandidateMatches(frame_q, frame_t, matcher, candidate_matches);
01512 if (candidate_matches.size() < min_sample_size) return 0;
01513
01514
01515
01516 PointCloudFeature features_t, features_q;
01517
01518 features_t.resize(candidate_matches.size());
01519 features_q.resize(candidate_matches.size());
01520
01521 for (int m_idx = 0; m_idx < candidate_matches.size(); ++m_idx)
01522 {
01523 const cv::DMatch& match = candidate_matches[m_idx];
01524 int idx_q = match.queryIdx;
01525 int idx_t = match.trainIdx;
01526
01527 PointFeature& p_t = features_t[m_idx];
01528 p_t.x = frame_t.kp_means[idx_t](0,0);
01529 p_t.y = frame_t.kp_means[idx_t](1,0);
01530 p_t.z = frame_t.kp_means[idx_t](2,0);
01531
01532 PointFeature& p_q = features_q[m_idx];
01533 p_q.x = frame_q.kp_means[idx_q](0,0);
01534 p_q.y = frame_q.kp_means[idx_q](1,0);
01535 p_q.z = frame_q.kp_means[idx_q](2,0);
01536 }
01537
01538
01539
01540 TransformationEstimationSVD svd;
01541 Eigen::Matrix4f transformation;
01542 best_inlier_matches.clear();
01543 int iterations = 0;
01544
01545 for (int i = 0; i < candidate_matches.size(); ++i)
01546 for (int j = i+1; j < candidate_matches.size(); ++j)
01547 for (int k = j+1; k < candidate_matches.size(); ++k)
01548 {
01549
01550 IntVector inlier_idx;
01551 inlier_idx.push_back(i);
01552 inlier_idx.push_back(j);
01553 inlier_idx.push_back(k);
01554
01555
01556 std::vector<cv::DMatch> inlier_matches;
01557 inlier_matches.push_back(candidate_matches[i]);
01558 inlier_matches.push_back(candidate_matches[j]);
01559 inlier_matches.push_back(candidate_matches[k]);
01560
01561
01562 svd.estimateRigidTransformation(
01563 features_q, inlier_idx,
01564 features_t, inlier_idx,
01565 transformation);
01566
01567
01568 PointCloudFeature features_q_tf;
01569 pcl::transformPointCloud(features_q, features_q_tf, transformation);
01570
01571 for (int m_idx = 0; m_idx < candidate_matches.size(); ++m_idx)
01572 {
01573
01574 const PointFeature& p_t = features_t[m_idx];
01575 const PointFeature& p_q = features_q_tf[m_idx];
01576 float eucl_dist_sq = distEuclideanSq(p_t, p_q);
01577
01578 if (eucl_dist_sq < sac_max_eucl_dist_sq_)
01579 {
01580 inlier_idx.push_back(m_idx);
01581 inlier_matches.push_back(candidate_matches[m_idx]);
01582
01583
01584 if (sac_reestimate_tf_)
01585 {
01586 svd.estimateRigidTransformation(
01587 features_q, inlier_idx,
01588 features_t, inlier_idx,
01589 transformation);
01590 pcl::transformPointCloud(features_q, features_q_tf, transformation);
01591 }
01592 }
01593 }
01594
01595
01596 if (inlier_matches.size() > best_inlier_matches.size())
01597 {
01598 svd.estimateRigidTransformation(
01599 features_q, inlier_idx,
01600 features_t, inlier_idx,
01601 transformation);
01602
01603 best_transformation = transformation;
01604 best_inlier_matches = inlier_matches;
01605 }
01606
01607 iterations++;
01608 }
01609
01610 return iterations;
01611 }
01612
01613
01614 int KeyframeGraphDetector::pairwiseMatchingRANSAC(
01615 int kf_idx_q, int kf_idx_t,
01616 const KeyframeVector& keyframes,
01617 DMatchVector& best_inlier_matches,
01618 Eigen::Matrix4f& best_transformation)
01619 {
01620
01621 int min_sample_size = 3;
01622
01623
01624 const RGBDFrame& frame_t = keyframes[kf_idx_t];
01625 const RGBDFrame& frame_q = keyframes[kf_idx_q];
01626 cv::FlannBasedMatcher& matcher = matchers_[kf_idx_t];
01627
01628 DMatchVector candidate_matches;
01629 getCandidateMatches(frame_q, frame_t, matcher, candidate_matches);
01630
01631
01632 if (candidate_matches.size() < min_sample_size) return 0;
01633 if (candidate_matches.size() < sac_min_inliers_) return 0;
01634
01635
01636
01637 PointCloudFeature features_t, features_q;
01638
01639 features_t.resize(candidate_matches.size());
01640 features_q.resize(candidate_matches.size());
01641
01642 for (int m_idx = 0; m_idx < candidate_matches.size(); ++m_idx)
01643 {
01644 const cv::DMatch& match = candidate_matches[m_idx];
01645 int idx_q = match.queryIdx;
01646 int idx_t = match.trainIdx;
01647
01648 PointFeature& p_t = features_t[m_idx];
01649 p_t.x = frame_t.kp_means[idx_t](0,0);
01650 p_t.y = frame_t.kp_means[idx_t](1,0);
01651 p_t.z = frame_t.kp_means[idx_t](2,0);
01652
01653 PointFeature& p_q = features_q[m_idx];
01654 p_q.x = frame_q.kp_means[idx_q](0,0);
01655 p_q.y = frame_q.kp_means[idx_q](1,0);
01656 p_q.z = frame_q.kp_means[idx_q](2,0);
01657 }
01658
01659
01660
01661 TransformationEstimationSVD svd;
01662 Eigen::Matrix4f transformation;
01663 best_inlier_matches.clear();
01664 int iteration = 0;
01665
01666 std::set<int> mask;
01667
01668 while(true)
01669
01670 {
01671
01672 IntVector sample_idx;
01673 get3RandomIndices(candidate_matches.size(), mask, sample_idx);
01674
01675
01676 IntVector inlier_idx;
01677 std::vector<cv::DMatch> inlier_matches;
01678
01679 for (unsigned int s_idx = 0; s_idx < sample_idx.size(); ++s_idx)
01680 {
01681 int m_idx = sample_idx[s_idx];
01682 inlier_idx.push_back(m_idx);
01683 inlier_matches.push_back(candidate_matches[m_idx]);
01684 }
01685
01686
01687 svd.estimateRigidTransformation(
01688 features_q, inlier_idx,
01689 features_t, inlier_idx,
01690 transformation);
01691
01692
01693 PointCloudFeature features_q_tf;
01694 pcl::transformPointCloud(features_q, features_q_tf, transformation);
01695
01696 for (int m_idx = 0; m_idx < candidate_matches.size(); ++m_idx)
01697 {
01698
01699 const PointFeature& p_t = features_t[m_idx];
01700 const PointFeature& p_q = features_q_tf[m_idx];
01701 float eucl_dist_sq = distEuclideanSq(p_t, p_q);
01702
01703 if (eucl_dist_sq < sac_max_eucl_dist_sq_)
01704 {
01705 inlier_idx.push_back(m_idx);
01706 inlier_matches.push_back(candidate_matches[m_idx]);
01707
01708
01709 if (sac_reestimate_tf_)
01710 {
01711 svd.estimateRigidTransformation(
01712 features_q, inlier_idx,
01713 features_t, inlier_idx,
01714 transformation);
01715 pcl::transformPointCloud(features_q, features_q_tf, transformation);
01716 }
01717 }
01718 }
01719
01720
01721 if (inlier_matches.size() > best_inlier_matches.size())
01722 {
01723 svd.estimateRigidTransformation(
01724 features_q, inlier_idx,
01725 features_t, inlier_idx,
01726 transformation);
01727
01728 best_transformation = transformation;
01729 best_inlier_matches = inlier_matches;
01730 }
01731
01732 double best_inlier_ratio = (double) best_inlier_matches.size() /
01733 (double) candidate_matches.size();
01734
01735
01736 if(best_inlier_matches.size() < sac_min_inliers_)
01737 {
01738 if (iteration >= ransac_max_iterations_) break;
01739 }
01740
01741 else
01742 {
01743 double h = log_one_minus_ransac_confidence_ /
01744 log(1.0 - pow(best_inlier_ratio, min_sample_size));
01745
01746 if (iteration > (int)(h+1)) break;
01747 if (iteration >= 2*ransac_max_iterations_) break;
01748 }
01749
01750 iteration++;
01751 }
01752
01753 return iteration;
01754 }
01755
01756 int KeyframeGraphDetector::pairwiseMatchingRANSAC(
01757 int kf_idx_q, int kf_idx_t,
01758 const KeyframeVector& keyframes,
01759 DMatchVector& best_inlier_matches,
01760 Eigen::Matrix4f& best_transformation,std::vector<cv::DMatch> matches)
01761 {
01762
01763 int min_sample_size = 3;
01764
01765
01766 const RGBDFrame& frame_t = keyframes[kf_idx_t];
01767 const RGBDFrame& frame_q = keyframes[kf_idx_q];
01768
01769 DMatchVector candidate_matches;
01770
01771 for (u_int i = 0; i< matches.size();i++) {
01772 int idx_q = matches[i].queryIdx;
01773 int idx_t = matches[i].trainIdx;
01774 if (frame_t.kp_valid[idx_t] && frame_q.kp_valid[idx_q])
01775 candidate_matches.push_back(matches[i]);
01776 }
01777
01778 if (candidate_matches.size() < sac_min_inliers_)
01779 return 0;
01780 if (candidate_matches.size() < min_sample_size)
01781 return 0;
01782
01783
01784
01785
01786 PointCloudFeature features_t, features_q;
01787
01788 features_t.resize(candidate_matches.size());
01789 features_q.resize(candidate_matches.size());
01790
01791 for (int m_idx = 0; m_idx < candidate_matches.size(); ++m_idx)
01792 {
01793 const cv::DMatch& match = candidate_matches[m_idx];
01794 int idx_q = match.queryIdx;
01795 int idx_t = match.trainIdx;
01796
01797 PointFeature& p_t = features_t[m_idx];
01798 p_t.x = frame_t.kp_means[idx_t](0,0);
01799 p_t.y = frame_t.kp_means[idx_t](1,0);
01800 p_t.z = frame_t.kp_means[idx_t](2,0);
01801
01802 PointFeature& p_q = features_q[m_idx];
01803 p_q.x = frame_q.kp_means[idx_q](0,0);
01804 p_q.y = frame_q.kp_means[idx_q](1,0);
01805 p_q.z = frame_q.kp_means[idx_q](2,0);
01806 }
01807
01808
01809
01810 TransformationEstimationSVD svd;
01811 Eigen::Matrix4f transformation;
01812 best_inlier_matches.clear();
01813 int iteration = 0;
01814
01815 std::set<int> mask;
01816
01817 while(true)
01818
01819 {
01820
01821 IntVector sample_idx;
01822 get3RandomIndices(candidate_matches.size(), mask, sample_idx);
01823
01824
01825 IntVector inlier_idx;
01826 std::vector<cv::DMatch> inlier_matches;
01827
01828 for (unsigned int s_idx = 0; s_idx < sample_idx.size(); ++s_idx)
01829 {
01830 int m_idx = sample_idx[s_idx];
01831 inlier_idx.push_back(m_idx);
01832 inlier_matches.push_back(candidate_matches[m_idx]);
01833 }
01834
01835
01836 svd.estimateRigidTransformation(
01837 features_q, inlier_idx,
01838 features_t, inlier_idx,
01839 transformation);
01840
01841
01842 PointCloudFeature features_q_tf;
01843 pcl::transformPointCloud(features_q, features_q_tf, transformation);
01844
01845 for (int m_idx = 0; m_idx < candidate_matches.size(); ++m_idx)
01846 {
01847
01848 const PointFeature& p_t = features_t[m_idx];
01849 const PointFeature& p_q = features_q_tf[m_idx];
01850 float eucl_dist_sq = distEuclideanSq(p_t, p_q);
01851
01852 if (eucl_dist_sq < sac_max_eucl_dist_sq_)
01853 {
01854 inlier_idx.push_back(m_idx);
01855 inlier_matches.push_back(candidate_matches[m_idx]);
01856
01857
01858 if (sac_reestimate_tf_)
01859 {
01860 svd.estimateRigidTransformation(
01861 features_q, inlier_idx,
01862 features_t, inlier_idx,
01863 transformation);
01864 pcl::transformPointCloud(features_q, features_q_tf, transformation);
01865 }
01866 }
01867 }
01868
01869
01870 if (inlier_matches.size() > best_inlier_matches.size())
01871 {
01872 svd.estimateRigidTransformation(
01873 features_q, inlier_idx,
01874 features_t, inlier_idx,
01875 transformation);
01876
01877 best_transformation = transformation;
01878 best_inlier_matches = inlier_matches;
01879 }
01880
01881 double best_inlier_ratio = (double) best_inlier_matches.size() /
01882 (double) candidate_matches.size();
01883
01884
01885 if(best_inlier_matches.size() < sac_min_inliers_)
01886 {
01887 if (iteration >= ransac_max_iterations_) break;
01888 }
01889
01890 else
01891 {
01892 double h = log_one_minus_ransac_confidence_ /
01893 log(1.0 - pow(best_inlier_ratio, min_sample_size));
01894
01895 if (iteration > (int)(h+1)) break;
01896 if (iteration >= 2*ransac_max_iterations_) break;
01897
01898 }
01899
01900 iteration++;
01901 }
01902
01903 return iteration;
01904 }
01905
01906 }