graph_builder.h
Go to the documentation of this file.
00001 //part of the source code of master thesis of Jiri Divis, source code written by Jiri Divis
00015 #ifndef VSLAM_GRAPH_BUILDER_H_INCLUDED
00016 #define VSLAM_GRAPH_BUILDER_H_INCLUDED
00017 #include "pose_graph.h" 
00018 #include "graph_utils.h"  
00019 #include "landmark_manager.h"
00020 #include "emat_estimation.h"
00021 #include "grid.h" 
00022 
00023 #include <algorithm>
00024 #include <tr1/functional>
00025 #include <string>
00026 namespace vslam{
00027 
00028 /*------------------------------------------------------------------------------------------*/
00029 //Local matching stuff.
00030 /*------------------------------------------------------------------------------------------*/
00059 template<class PoseGraphT> void findLocalMatchesSE3(
00060         const PoseGraphT& g, 
00061         typename graph_traits<PoseGraphT>::vertex_descriptor vd1, 
00062         typename graph_traits<PoseGraphT>::vertex_descriptor vd2,
00063         shared_ptr<RobustFeatureMatcher> rmatcher,
00064         vector<cv::DMatch>& matches){
00065     assert(matches.size()==0);
00066     typename graph_traits<PoseGraphT>::vertex_descriptor vd0;
00067     typename graph_traits<PoseGraphT>::adjacency_iterator vi, vi_end;
00068     for(tie(vi, vi_end) = adjacent_vertices(vd1 , g); vi!=vi_end; ++vi){
00069         if(*vi!=vd2){
00070             vd0=*vi;
00071             break; //we take first neighbouring edge to determine vd0
00072         }
00073     }
00074     if(vi==vi_end) return;
00075 
00076     typename property_map<PoseGraphT, vertex_kp_t>::const_type kp_pmap = get(vertex_kp, g);
00077     typename property_map<PoseGraphT, vertex_desc_t>::const_type desc_pmap = get(vertex_desc, g);
00078     Grid grid2(60,60, kp_pmap[vd2]);
00079 
00080     for(size_t i=0; i<kp_pmap[vd1].size(); i++) {
00081         int j = getFeatureIdx(g, i, vd1, vd2);
00082         int h = getFeatureIdx(g, i, vd1, vd0);
00083         if(j==BAD_INDEX){
00084             Vector3d pt_c2;
00085             Vector2d c2Pixel;
00086             if(h != BAD_INDEX){
00087                 pt_c2 = get(vertex_transform, g, vd2) * triangulatePointWrtWorldPos(
00088                         g, FeatureID<PoseGraphT>(vd0, h), FeatureID<PoseGraphT>(vd1, i));
00089                 c2Pixel = PanoImCoord::fromHomogenous(pt_c2).getPixel();
00090             } else{
00091                 pt_c2 = PanoImCoord::fromPixel(
00092                         Vector2d(kp_pmap[vd1][i].pt.x, kp_pmap[vd1][i].pt.y)).getHomogenous();
00093                 pt_c2 = (getEdgeTransform(g, vd1, vd2).rotation_matrix() * pt_c2).eval();
00094                 c2Pixel = PanoImCoord::fromHomogenous(pt_c2).getPixel();
00095             }
00096             vector<int> keypoint_idxs_c2 = grid2.getNearKeypoints(grid2.getCell(c2Pixel));
00097 
00098             vector<cv::KeyPoint> keypoints2_sel=getArrayIdices(kp_pmap[vd2], keypoint_idxs_c2);
00099             cv::Mat descriptors2_sel=getArrayIdices<cv::Mat>(desc_pmap[vd2], keypoint_idxs_c2);
00100 
00101             vector<cv::DMatch> matches_tmp;
00102             RobustFeatureMatcherStats stats;
00103             rmatcher->nonsymetricalMatch(keypoints2_sel, mkContainer<vector>(kp_pmap[vd1][i]),  
00104                     descriptors2_sel,
00105                     getArrayIdices<cv::Mat>(desc_pmap[vd1], mkContainer<vector>((int)i)), 
00106                     stats, matches_tmp);
00107             if(matches_tmp.size()>=1){
00108                 cv::DMatch tmp = matches_tmp[0];
00109                 tmp.queryIdx=keypoint_idxs_c2[matches_tmp[0].trainIdx];
00110                 tmp.trainIdx=i;
00111                 matches.push_back(tmp);
00112             }
00113         }
00114     }
00115 }
00116 
00117 template<class PoseGraphT> void findLocalMatchesSO3(
00118         const PoseGraphT& g, 
00119         typename graph_traits<PoseGraphT>::vertex_descriptor tvd, 
00120         typename graph_traits<PoseGraphT>::vertex_descriptor qvd,
00121         shared_ptr<RobustFeatureMatcher> rmatcher,
00122         Vector2d grid_dim,
00123         bool skip_landmarks,
00124         vector<cv::DMatch>& matches){
00125     assert(matches.size()==0);
00126 
00127     typename property_map<PoseGraphT, vertex_kp_t>::const_type kp_pmap = get(vertex_kp, g);
00128     typename property_map<PoseGraphT, vertex_desc_t>::const_type desc_pmap = get(vertex_desc, g);
00129     Grid grid2(grid_dim(0), grid_dim(1), kp_pmap[qvd]);
00130 
00131     for(size_t i=0; i<kp_pmap[tvd].size(); i++) {
00132         int j = getFeatureIdx(g, i, tvd, qvd);
00133         if(j!=BAD_INDEX) continue;
00134         if(skip_landmarks && (get(vertex_fix_idx, g, tvd)[i]!=BAD_INDEX)) continue;
00135 
00136         Vector2d ctvd_pixel = Vector2d(kp_pmap[tvd][i].pt.x, kp_pmap[tvd][i].pt.y);
00137         Vector3d pt_ct = PanoImCoord::fromPixel(ctvd_pixel).getHomogenous();
00138         Vector3d pt_cq = getEdgeTransform(g, tvd, qvd).rotation_matrix() * pt_ct;
00139         Vector2d cqvd_pixel = PanoImCoord::fromHomogenous(pt_cq).getPixel();
00140         vector<int> keypoint_idxs_c2 = grid2.getNearKeypoints(grid2.getCell(cqvd_pixel));
00141 
00142         vector<cv::KeyPoint> keypointsq_sel=getArrayIdices(kp_pmap[qvd], keypoint_idxs_c2);
00143         cv::Mat descriptorsq_sel=getArrayIdices<cv::Mat>(desc_pmap[qvd], keypoint_idxs_c2);
00144 
00145         vector<cv::DMatch> matches_tmp;
00146         RobustFeatureMatcherStats stats;
00147         rmatcher->nonsymetricalMatch(
00148                 keypointsq_sel, 
00149                 mkContainer<vector>(kp_pmap[tvd][i]),  
00150                 descriptorsq_sel,
00151                 getArrayIdices<cv::Mat>(desc_pmap[tvd], mkContainer<vector>((int)i)), 
00152                 stats, 
00153                 matches_tmp);
00154 
00155         if(matches_tmp.size()>=1){
00156             cv::DMatch tmp = matches_tmp[0];
00157             tmp.queryIdx=keypoint_idxs_c2[matches_tmp[0].trainIdx];
00158             tmp.trainIdx=i;
00159             matches.push_back(tmp);
00160         }
00161     }
00162 }
00164 
00166 
00167 
00168 /*------------------------------------------------------------------------------------------*/
00171 
00172 /*------------------------------------------------------------------------------------------*/
00175 
00176 //see declaration for comment
00177 template<class PoseGraphT> 
00178 bool OneDetectorNodeBuilder<PoseGraphT>::build(const cv::Mat & image, int image_seq_num, 
00179         uint64_t pose_timestamp, typename graph_traits<PoseGraphT>::vertex_descriptor& vd, PoseGraphT& g){
00180     using namespace boost;
00181     ros::WallTime nodebuilder_start_time = ros::WallTime::now();
00182     assert(!image.empty());
00183     vd = add_vertex(g);
00184     get(vertex_seq, g, vd) = image_seq_num;
00185     get(vertex_timestamp, g, vd) = pose_timestamp;
00186     vector<cv::KeyPoint> & keypoints = get(vertex_kp, g, vd);
00187     cv::Mat & descriptors = get(vertex_desc, g, vd);
00188     if(feature_2d_detector){ //hack for non-common feature detector interface
00189         (*feature_2d_detector)(image, mask, keypoints, descriptors, false);
00190     } else{
00191         detector->detect(image, keypoints, mask);
00192     }
00193     int detected_kpts = keypoints.size();
00194     vector<int> keep_kp_idx;
00195     if(nms_options.do_nms){
00196         nonMaximaSuppresion(keypoints, nms_options.target_num_points, keep_kp_idx);
00197         keypoints=getArrayIdices<cv::KeyPoint>(keypoints, keep_kp_idx);
00198     }
00199     if(feature_2d_detector && nms_options.do_nms){
00200         descriptors=getArrayIdices<cv::Mat>(descriptors, keep_kp_idx);
00201     } else{
00202         extractor->compute(image, keypoints, descriptors);
00203     }
00204 
00205     vector<int> & pt3_idx = get(vertex_fix_idx, g, vd);
00206     pt3_idx = vector<int>(keypoints.size());
00207     std::fill_n(pt3_idx.begin(), keypoints.size(), BAD_INDEX);
00208     get(vertex_debug_info, g, vd).double_propmap["num_kpts"]=detected_kpts;
00209     get(vertex_debug_info, g, vd).double_propmap["num_kpts_nms"]=keypoints.size();
00210     ROS_INFO_STREAM_NAMED("PoseGraph", "constructed node for image number " << image_seq_num <<
00211             ". Detected " << detected_kpts << " keypoints. " <<
00212             "Out of this: " << keypoints.size() << " were retained adter NMS.");
00213 
00214     ros::WallDuration nodebuilder_duration = ros::WallTime::now() - nodebuilder_start_time;
00215     get(vertex_debug_info, g, vd).double_propmap["timings_nodebuilder_d"]=
00216             nodebuilder_duration.toSec();
00217     return true;
00218 }
00219 
00220 
00221 template<class PoseGraphT> void OneDetectorNodeBuilder<PoseGraphT>::demolish( PoseGraphT& g, 
00222         Points<PoseGraphT>& points, typename graph_traits<PoseGraphT>::vertex_descriptor & vd){
00223     vector<cv::KeyPoint> & keypoints = get(vertex_kp, g, vd);
00224     vector<int> & fixed_points = get(vertex_fix_idx, g, vd);
00225     for(size_t i = 0; i<keypoints.size(); i++){
00226         if(fixed_points[i] != BAD_INDEX){
00227             //points.getPoint(fixed_points[i]).deleteObservation(g, vd);
00228             points.deleteLmObs(g, FeatureID<PoseGraphT>(vd, i)); //XXX
00229         }
00230     }
00231 
00232     typename graph_traits<PoseGraphT>::adjacency_iterator vi, vi_end;
00233     for(tie(vi, vi_end) = adjacent_vertices(vd , g); vi!=vi_end; ++vi){
00234         remove_edge(*vi, vd, g);
00235         remove_edge(vd, *vi, g);
00236     }
00237 
00238     get(vertex_debug_info, g, vd).double_propmap["deleted"]= 1.0;
00239     get(vertex_debug_info, g, vd).double_propmap.clear();
00240 }
00241 
00243 /*------------------------------------------------------------------------------------------*/
00244 
00245 /*------------------------------------------------------------------------------------------*/
00249 template<class G> void setRelTranslationError(
00250         double r_min, double r_max, 
00251         typename graph_traits<G>::vertex_descriptor vs, 
00252         typename graph_traits<G>::vertex_descriptor vt, 
00253         G& g){
00254     double dist = get(edge_transform, g, edge(vs, vt, g).first).translation().norm();
00255     double error = (dist*r_max - dist*r_min) / (dist*r_max);
00256     get(edge_rel_scale_error, g, edge(vs, vt, g).first) = error;
00257     get(edge_rel_scale_error, g, edge(vt, vs, g).first) = error;
00258 }
00259 
00260 
00261 
00267 
00268 
00280 template<class G> void MonoFtrClassEdgeBuilder<G>::compute3viewStructure( VertexD vad, VertexD vbd, 
00281         VertexD vcd, G & g, IdxPoint3dVec& common_pts_3d, SE3& scaled_T_vbd_vcd){
00282     using namespace boost;
00283     typename property_map<G, edge_kp_idx_map_t>::type ekpimap = get(edge_kp_idx_map, g);
00284     //typename property_map<G, edge_transform_t>::type etrmap = get(edge_transform, g);
00285     EdgeD edba = edge(vbd, vad, g).first;
00286     EdgeD edbc = edge(vbd, vcd, g).first;
00287     const map<int, int>& ba_idx = ekpimap[edba];
00288     const map<int, int>& bc_idx = ekpimap[edbc];
00289     Points3dSTL pts_ab;
00290     //computeStructure(etrmap[edba], computeMatches(vbd, vad, g), pts_ab);
00291     computeStructure(getEdgeTransform(g, vbd, vad), computeMatches(vbd, vad, g), pts_ab);
00292     //XXX filter out matches that do not need to be computed
00293     vector<int> common_idx = switchCont<vector>(getCommon(
00294             transformF<int>(mapToList(ba_idx), getFirst),
00295             transformF<int>(mapToList(bc_idx), getFirst)));
00296     Points3dSTL pts_ba_common = switchCont<vector>(transformF<Vector3d>(
00297             getByIdx(indexBy(transformF<int>(mapToList(ba_idx), getFirst), pts_ab), common_idx), 
00298             getSecond));
00299 
00300     Points3dSTL pts_bc;
00301     //computeStructure(etrmap[edbc] , computeMatches(vbd, vcd, g), pts_bc);
00302     computeStructure(getEdgeTransform(g, vbd, vcd) , computeMatches(vbd, vcd, g), pts_bc);
00303     Points3dSTL pts_bc_common = switchCont<vector>(transformF<Vector3d>(
00304             getByIdx(indexBy(transformF<int>(mapToList(bc_idx), getFirst), pts_bc), common_idx), 
00305             getSecond));
00306     double r_low, r_hi;
00307     double ab_to_bc_ratio;
00308     computeScale(pts_ba_common, pts_bc_common, r_low, ab_to_bc_ratio, r_hi);
00309     setRelTranslationError(r_low, r_hi, vbd, vcd, g);
00310     Points3dSTL::const_iterator pts_ba_common_it = pts_bc_common.begin();
00311     Points3dSTL::const_iterator pts_bc_common_it = pts_ba_common.begin();
00312     BOOST_FOREACH(int i, common_idx){
00313         common_pts_3d.push_back(std::make_pair(i, *pts_bc_common_it));
00314         ++pts_ba_common_it;
00315         ++pts_bc_common_it;
00316     }
00317     //scaled_T_vbd_vcd = SE3(etrmap[edbc].rotation_matrix(), 
00318     //        etrmap[edbc].translation() * ab_to_bc_ratio);
00319     scaled_T_vbd_vcd = SE3(getEdgeTransform(g, vbd, vcd).rotation_matrix(), 
00320             getEdgeTransform(g, vbd, vcd).translation() * ab_to_bc_ratio);
00321     //cout << "AAA" << ab_to_bc_ratio << endl;
00322     //cout << "AAA" << etrmap[edbc];
00323     //cout << "AAA" << scaled_T_vbd_vcd;
00324 }
00325 
00326 
00342 template<class G> void MonoFtrClassEdgeBuilder<G>::matchScaleFindNewLandmarks(
00343         VertexD vsrc, VertexD vdest, Points<G> & points, G & g){
00344     using namespace boost;
00345     typename graph_traits<G>::adjacency_iterator vi, vi_end;
00346     int new_track_count=0;
00347     //first, only scale is computed.
00348     for(tie(vi, vi_end) = adjacent_vertices(vsrc , g); vi!=vi_end; ++vi){
00349         if(*vi != vdest){
00350             IdxPoint3dVec common_pts_3d_vsrc; //common features in the three views
00351             SE3 scaled_T_vsrc_vdest;
00352             compute3viewStructure(*vi, vsrc, vdest, g, common_pts_3d_vsrc, scaled_T_vsrc_vdest);
00353             if(get(vertex_keyframe_flag, g, *vi)){
00354                 get(edge_transform, g, edge(vsrc, vdest, g).first) = scaled_T_vsrc_vdest;
00355                 get(edge_transform, g, edge(vdest, vsrc, g).first) = scaled_T_vsrc_vdest.inverse();
00356                 get(vertex_transform, g, vdest) = scaled_T_vsrc_vdest * get(vertex_transform, g, vsrc);
00357             }
00358         }
00359     }
00360 
00361     //second, find new landmarks
00362     for(tie(vi, vi_end) = adjacent_vertices(vsrc , g); vi!=vi_end; ++vi){
00363         if(*vi != vdest){
00364             //this is done only to get common_pts_3d_vsrc
00365             IdxPoint3dVec common_pts_3d_vsrc; 
00366             SE3 scaled_T_vsrc_vdest; //dummy
00367             compute3viewStructure(*vi, vsrc, vdest, g, common_pts_3d_vsrc, scaled_T_vsrc_vdest);
00368             
00369             IdxPoint3dVec::const_iterator common_pts_3d_it = common_pts_3d_vsrc.begin();
00370             while(common_pts_3d_it!=common_pts_3d_vsrc.end()){
00371                 FeatureID<G> srcf = FeatureID<G>(vsrc, common_pts_3d_it->first);
00372                 FeatureID<G> destf = FeatureID<G>(vdest, getFeatureIdx(g, srcf, vdest));
00373                 FeatureID<G> vif = FeatureID<G>(*vi, getFeatureIdx(g, srcf, *vi));
00374 
00375                 //new landmark with 3 features
00376                 if(!isLandmakFeature(g, vif) && !isLandmakFeature(g, srcf) && 
00377                         !isLandmakFeature(g, destf)){
00378                     if(points.fixNewLandmark(vif, srcf, destf, g)){
00379                         new_track_count++;
00380                     }
00381                 }
00382                 ++common_pts_3d_it;;
00383             }
00384         }
00385     }
00386     std::string num_new_lms_key="num_new_lms";
00387     map<std::string, double> & pmap = get(vertex_debug_info, g, vsrc).double_propmap;
00388     if(pmap.find(num_new_lms_key) == pmap.end()){
00389         pmap[num_new_lms_key]= new_track_count;
00390     } else{
00391         get(vertex_debug_info, g, vdest).double_propmap[num_new_lms_key]=new_track_count;
00392     }
00393     ROS_INFO_STREAM_NAMED("EdgeBulder", "# of new tracks: " << new_track_count);
00394     get(vertex_debug_info, g, vsrc).double_propmap["tracks_new"]=new_track_count;
00395 }
00397 
00398 
00399 
00400 
00409 template<class G> void MonoFtrClassEdgeBuilder<G>::computeScale(VertexD convd, VertexD newvd, 
00410         G & g, Points<G>& points, SE3& scaled_T_vbd_vcd){
00411 
00412     scaled_T_vbd_vcd = SE3(scaled_T_vbd_vcd.rotation_matrix(), 
00413             scaled_T_vbd_vcd.translation().normalized());
00414     VertexD vad, vbd, vcd;
00415 
00416     //find last keyframe
00417     bool found_neighbour = false;
00418     typename graph_traits<G>::adjacency_iterator vi, vi_end;
00419     for(tie(vi, vi_end) = adjacent_vertices(convd , g); vi!=vi_end; ++vi){
00420         if(*vi != newvd){
00421             found_neighbour = true;
00422             vad = *vi;
00423             vbd = convd;
00424             vcd = newvd;
00425             if(get(vertex_keyframe_flag, g, *vi)) break;
00426         }
00427     }
00428 
00429     double total2;
00430     if(found_neighbour){
00431         //set up data for model estimation
00432         vector<int> common_b_idx = common_feature_tracks<vector>(g, vad, vbd, vcd); 
00433         int count=0;
00434         ALIGNED<ScaleObservation>::vector data;
00435         ALIGNED<ScaleObservation>::vector data_lm;
00436         for(size_t i = 0; i<common_b_idx.size(); i++){
00437             ScaleObservation datum;
00438             FeatureID<G> vbd_f(vbd, common_b_idx[i]);
00439             FeatureID<G> vcd_f(
00440                     vcd, 
00441                     (get(edge_kp_idx_map, g, edge(vbd, vcd, g).first).find(common_b_idx[i]))->second);
00442             datum.k_proj_measurement = getFeaturePixel(g, vbd_f);
00443             datum.n_proj_measurement = getFeaturePixel(g, vcd_f);
00444             datum.T_wk = get(vertex_transform, g, vbd);
00445             datum.T_kn = scaled_T_vbd_vcd;
00446             int fix_idx_i = get(vertex_fix_idx, g, vbd)[common_b_idx[i]];
00447             if(fix_idx_i!=BAD_INDEX && points.getPoint(fix_idx_i).initialized){
00448                 datum.lm_estimate_kk_k = 
00449                         get(vertex_transform, g, vbd) *points.getPoint(fix_idx_i).global;
00450                 data_lm.push_back(datum);
00451             } else{
00453                 datum.lm_estimate_kk_k = 
00454                        get(vertex_transform, g, vbd) * triangulatePointWrtWorldPos(g, vbd_f, vcd_f);
00455                 if(count < 1) data_lm.push_back(datum);
00456                 count++;
00457             }
00458             data.push_back(datum);
00459         }
00460 
00461         //do model estimation
00462         const double reproj_error_tolerance = 5;
00463         ScaleReprojectionError error_func;
00464         typedef MDErrorFuncAdaptor<ScaleReprojectionError> AErrorFuncT;
00465         AErrorFuncT adapted_error_func(error_func);
00466         typedef RealErrorMaxErrorAccumulator<AErrorFuncT> ErrorAccumT; 
00467         ErrorAccumT error_accum(adapted_error_func, reproj_error_tolerance);
00468         shared_ptr<ModelBuilder<ErrorAccumT::ModelClassT> > mbuilder(
00469                 new ScaleModelBuilder<ErrorAccumT>(error_accum));
00470 
00471         ROS_INFO_STREAM_NAMED("EdgeBulder", "# total common features for scale matching: " <<
00472                 data.size() << " " << data_lm.size());
00473         //shared_ptr<Model<double, ScaleObservation> > model, best_model;
00474 
00475         typedef Model<double, ScaleObservation> ModelT;
00476         typedef DataSelector<typename ModelT::DataVec> DataSelectorT;
00477         //shared_ptr<DataSelectorT> selector(new AllCombinationsSelector<typename ModelT::DataVec>(
00478         //        data, mbuilder->getSize()));
00479         shared_ptr<DataSelectorT> selector(new RandomDataSelector<typename ModelT::DataVec>(
00480                 data, mbuilder->getSize(), 100));
00481         shared_ptr<ModelT> best_model = ranSaC<ErrorAccumT>(mbuilder, selector, data);
00482         assert(best_model);
00483         total2 = best_model->getModel();
00484         ROS_INFO_STREAM_NAMED("EdgeBulder", "# of scale-match inliers: " << 
00485                 best_model->getInlierCount() << " " << best_model->getError());
00486     } else{
00487         //fallback
00488         total2=1.0;
00489     }
00490     //save the results or the normalized translation
00491     SE3 tmp(scaled_T_vbd_vcd.unit_quaternion(),  
00492             total2 *scaled_T_vbd_vcd.translation());
00493     scaled_T_vbd_vcd = tmp;
00494     get(edge_transform, g, edge(convd, newvd, g).first) = scaled_T_vbd_vcd;
00495     get(edge_transform, g, edge(newvd, convd, g).first) = scaled_T_vbd_vcd.inverse();
00496     get(vertex_transform, g, newvd) = 
00497             scaled_T_vbd_vcd * get(vertex_transform, g, convd);
00498 }
00499 
00500 
00501 
00502 
00503 
00504 
00517 template<class G> void EdgeBuilder<G>::featureSelection(
00518         G& g,
00519         VertexD vd, 
00520         int target_num, 
00521         vector<int>& keep_idxs, 
00522         vector<cv::KeyPoint>& sel_keypoints,
00523         cv::Mat& sel_descriptors){
00524     keep_idxs.clear();
00525     sel_keypoints.clear();
00526 
00527     nonMaximaSuppresion(get(vertex_kp, g, vd), target_num, keep_idxs);
00528     sel_keypoints=   getArrayIdices(get(vertex_kp, g, vd), keep_idxs);
00529     sel_descriptors= getArrayIdices<cv::Mat>(get(vertex_desc, g, vd), keep_idxs);
00530 
00531     ROS_INFO_STREAM_NAMED("EdgeBuilder", "Using " << keep_idxs.size() << 
00532             " features in image " << printVertexId(g, vd) << " for grobal matching.");
00533 }
00534 
00547 template<class G> bool MonoFtrClassEdgeBuilder<G>::unguidedMatching(
00548         const vector<cv::KeyPoint>& sel_tvd_keypoints,
00549         const vector<cv::KeyPoint>& sel_qvd_keypoints,
00550         const cv::Mat& sel_tvd_descriptors,
00551         const cv::Mat& sel_qvd_descriptors,
00552         SE3& T_tvd_qvd,
00553         std::vector<cv::DMatch>& global_dmatches_c1c2){
00554     std::vector<cv::DMatch> global_dmatches_c1c2_0;
00555 
00556     RobustFeatureMatcherStats stats;
00557     rmatcher->symaetricalMatch(sel_tvd_keypoints, sel_qvd_keypoints,
00558                 sel_tvd_descriptors, sel_qvd_descriptors, stats, global_dmatches_c1c2_0);
00559     ROS_INFO_STREAM_NAMED("EdgeBuilder", "# non-symetrical matches: " << stats.ratio_qt);
00560     ROS_INFO_STREAM_NAMED("EdgeBuilder", "# symetrical matches: " << stats.symetry);
00561     ImageMatchVec global_matches_c1c2 = 
00562             imageMatchCoords(sel_tvd_keypoints, sel_qvd_keypoints, global_dmatches_c1c2_0);
00563     if(!rmatcher->ransacTest(
00564             global_matches_c1c2, global_dmatches_c1c2_0, stats, global_dmatches_c1c2, T_tvd_qvd)){
00565         ROS_WARN_NAMED("PoseGraph", "Model estimation failed. RanSac did not return model.");
00566         return false;
00567     } else{
00568         ROS_INFO_STREAM_NAMED("PoseGraph.EdgeBuilder", "# RanSaC-filtered matches: " << stats.ransac);
00569         return true;
00570     }
00571 }
00572 
00573 
00585 template<class ErrorAccumT> typename ErrorAccumT::ErrorT outlierRemoval(
00586         const Matrix3d& E,
00587         const ErrorAccumT& ea, 
00588         const ImageMatchVec& matches_c1c2, 
00589         const vector<cv::DMatch>& dmatches_c1c2,
00590         vector<cv::DMatch>& filtered_matches_c1c2){ 
00591     ALIGNED<Matrix3d>::vector Ematrices;
00592     Ematrices.push_back(E);
00593     shared_ptr<EMatrixModel> model = 
00594             DummyModelBuilder<ErrorAccumT>( ea, Ematrices)(ImageMatchVec());
00595     model->compute(matches_c1c2);
00596     MaskVec::const_iterator itIn= model->getInlierMask().begin();
00597     std::vector<cv::DMatch>::const_iterator itM = dmatches_c1c2.begin();
00598     while(itIn!= model->getInlierMask().end()) {
00599         if (*itIn) { // it is a valid match
00600             filtered_matches_c1c2.push_back(*itM);
00601         }
00602         ++itIn, ++itM;
00603     }
00604     return model->getError();
00605 }
00606 
00607 
00616 template<class G> void MonoFtrClassEdgeBuilder<G>::guidedMatching(
00617         G& g,
00618         VertexD qvd, 
00619         VertexD tvd){ 
00620     ROS_INFO_NAMED("EdgeBuilder", "Starting local matching."); 
00621     PerformanceLogger<G> pl(g, qvd, "local_matching");
00622     typename property_map<G, vertex_kp_t>::type vkp_pmap = get(vertex_kp, g);
00623     vector<cv::DMatch> local_dmatches0, local_dmatches;
00624     vector<int> retain_idxs;
00625     findLocalMatchesSO3(g, tvd, qvd, rmatcher, Vector2d(60, 60), false, local_dmatches);
00626     if(local_dmatches.size() > 0){
00627         for(size_t i = 0 ; i< local_dmatches.size();i++){
00628             if(filter_index_pair_duplicates(local_dmatches[i], tvd, qvd, g)){
00629                 retain_idxs.push_back(i);
00630             }
00631         }
00632         local_dmatches=getArrayIdices(local_dmatches, retain_idxs);
00633         ROS_INFO_STREAM_NAMED("PoseGraph.EdgeBuilder", 
00634                 "# non-symetrical matches (excl global): " << local_dmatches.size());
00635         ImageMatchVec matches_c1c2 = 
00636                 imageMatchCoords(vkp_pmap[tvd], vkp_pmap[qvd], local_dmatches);
00638         RealErrorMaxErrorAccumulator<AngleError> ea(AngleError(), ((M_PI / 180.0)*1.0)); 
00639         SE3 T_tvd_qvd = getEdgeTransform(g, tvd, qvd);
00640         outlierRemoval(
00641                 sE3ToE(T_tvd_qvd), 
00642                 ea, 
00643                 matches_c1c2, 
00644                 local_dmatches, 
00645                 local_dmatches0);
00646         std::for_each(local_dmatches0.begin(), local_dmatches0.end(), std::tr1::bind(
00647                 add_idx_pair_from_dmatch<G>, std::tr1::placeholders::_1, tvd, qvd, 
00648                 std::tr1::ref(g)));
00649         int tmp = get(edge_kp_idx_map, g, edge(qvd, tvd, g).first).size();
00650         ROS_INFO_STREAM_NAMED("EdgeBuilder", 
00651                 "# matches satisfying 2-view constraint (excl. global): " <<  local_dmatches0.size());
00652         ROS_INFO_STREAM_NAMED("EdgeBuilder", 
00653                 "# matches satisfying 2-view constraint (incl. global): " <<  tmp);
00654         get(vertex_debug_info, g, qvd).double_propmap["num_2view_match_kpts_tot"]=tmp;
00655         get(vertex_debug_info, g, qvd).double_propmap["num_2view_match_kpts_loc"]=
00656                 local_dmatches0.size();
00657 
00658     } else{
00659         ROS_INFO_NAMED("PoseGraph", "Did not find any new mactehs.");
00660     }
00661 }
00662 
00663 
00664 
00665 
00666 
00667 //documented in header
00668 template<class G> bool MonoFtrClassEdgeBuilder<G>::buildImpl(
00669         const VertexD & convd, const VertexD & newvd, Points<G> & points, G & g) {
00670     using namespace boost;
00671     ROS_INFO_STREAM_NAMED("PoseGraph", "Constructing edge (" << printVertexId(g, convd) << 
00672             ", " << printVertexId(g, newvd) << ").");
00673     PerformanceLogger<G> edge_builder_pl(g, newvd, "edge_builder");
00674 
00675     std::vector<cv::DMatch> global_dmatches_con_new,dmatches_con_new_0; 
00676     SE3 T_con_new;
00677 
00678     //feature selection
00679     vector<int> gm_convd_keep_idx, gm_newvd_keep_idx;
00680     vector<cv::KeyPoint> gm_convd_keypoints, gm_newvd_keypoints;
00681     cv::Mat gm_newvd_descriptors, gm_convd_descriptors;
00682     {
00683         PerformanceLogger<G> pl(g, newvd, "feature_selection");
00684         EdgeBuilder<G>::featureSelection(
00685                 g, convd, 700, gm_convd_keep_idx, gm_convd_keypoints, gm_convd_descriptors);
00686         EdgeBuilder<G>::featureSelection(
00687                 g, newvd, 700, gm_newvd_keep_idx, gm_newvd_keypoints, gm_newvd_descriptors);
00688     }
00689 
00690     //global unguided on selected fetures + model estimation from computed matches.
00691     {
00692         PerformanceLogger<G> edge_builder_pl(g, newvd, "global_matching");
00693         if(!unguidedMatching(gm_convd_keypoints,  gm_newvd_keypoints,
00694                     gm_convd_descriptors, gm_newvd_descriptors, T_con_new, global_dmatches_con_new)){
00695             return false;
00696         }
00697     }
00698     {
00699         bool status;
00700         status=add_edge(newvd, convd, g).second;
00701         status=status && add_edge(convd, newvd, g).second;
00702         assert(status);
00703     }
00704     setEdgeTransform(T_con_new, convd, newvd, g);
00705     dmatches_con_new_0=remapDMatchIdxs(global_dmatches_con_new, gm_convd_keep_idx, gm_newvd_keep_idx);
00706     std::for_each(dmatches_con_new_0.begin(), dmatches_con_new_0.end(), std::tr1::bind(
00707             add_idx_pair_from_dmatch<G>, std::tr1::placeholders::_1, convd, newvd, std::tr1::ref(g)));
00708     
00709     //guided matching
00710     guidedMatching(g, newvd, convd);
00711 
00713     if(minEdgeDisparityAngle(g, convd, newvd) < (M_PI/180.0)*1.5){ //XXX
00714         ROS_WARN_NAMED("PoseGraph", "edge construction failed. Disparity too small.");
00715         ROS_WARN_STREAM_NAMED("PoseGraph", "disparity:" << 
00716             minEdgeDisparityAngle(g, convd, newvd) / M_PI * 180.0);
00717         remove_edge(newvd, convd, g);
00718         remove_edge(convd, newvd, g);
00719         return false;
00720     }
00721     ROS_WARN_STREAM_NAMED("PoseGraph", "disparity:" << 
00722             minEdgeDisparityAngle(g, convd, newvd) / M_PI * 180.0);
00723     
00724 
00725     SE3 scaled_T_vsrc_vdest = get(edge_transform, g, edge(convd, newvd, g).first);
00726     computeScale(convd, newvd, g, points, scaled_T_vsrc_vdest);
00727 
00728     //update landmarks
00729     {
00730         PerformanceLogger<G> pl(g, newvd, "lm_accounting");
00731         findNewLandmarks(convd, newvd, points, g); //XXX
00732         //matchScaleFindNewLandmarks(convd, newvd, points, g); //XXX
00733         extendLandmarks(convd, newvd, points, g);
00734     }
00735     ROS_INFO_STREAM_NAMED("PoseGraph", "Done constructing edge");
00736     return true;
00737 }
00738 
00739 /*------------------------------------------------------------------------------------------*/
00740 
00741 std::tr1::shared_ptr<RobustFeatureMatcher> constructRMatcher(
00742         std::tr1::shared_ptr<cv::DescriptorMatcher> _dmatcher,
00743         std::tr1::shared_ptr<EMatrixModelBuilder> _minbuilder, 
00744         std::tr1::shared_ptr<EMatrixModelBuilder> _builder){ 
00745     return std::tr1::shared_ptr<RobustFeatureMatcher>(
00746         new RobustFeatureMatcher( _dmatcher, _minbuilder, _builder));
00747 }
00748 
00749 
00750 
00755 /*------------------------------------------------------------------------------------------*/
00756 
00757 
00758 
00759 
00760 
00761 }//namespace vslam
00762 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines


pose_estimation
Author(s): Jiri Divis/jiridivis@gmail.com
autogenerated on Wed Mar 27 2013 21:00:12