graph_utils.h
Go to the documentation of this file.
00001 //part of the source code of master thesis, source code produced by Jiri Divis
00005 #ifndef VSLAM_GRAPH_UTILS_H_INCLUDED
00006 #define VSLAM_GRAPH_UTILS_H_INCLUDED
00007 #include "utils.h"
00008 #include "pose_graph.h"
00009 
00010 namespace vslam{
00013 
00020 /*------------------------------------------------------------------------------------------*/
00028 
00029 
00030 template<class G> int getFeatureIdx(const G& g, int source_idx, 
00031         typename graph_traits<G>::vertex_descriptor source_vd, 
00032         typename graph_traits<G>::vertex_descriptor target_vd){
00033     using namespace boost;
00034     assert(edge(source_vd, target_vd, g).second);
00035     typename graph_traits<G>::edge_descriptor ed = edge(source_vd, target_vd, g).first;
00036     map<int, int>::const_iterator it = 
00037             get(edge_kp_idx_map, g, ed).find(source_idx);
00038     if(it != get(edge_kp_idx_map, g, ed).end()){
00039         return it->second;
00040     } else{
00041         return BAD_INDEX;
00042     }
00043 }
00044 
00046 template<class G> int getFeatureIdx(const G& g, FeatureID<G> srcf,
00047         typename graph_traits<G>::vertex_descriptor target_vd){
00048     return getFeatureIdx(g, srcf.vidx, srcf.vd, target_vd); 
00049 }
00050 
00052 template<typename G> void remove_idx_pair(
00053         int sidx,
00054         typename graph_traits<G>::vertex_descriptor src, 
00055         typename graph_traits<G>::vertex_descriptor dest, 
00056         G& g){
00057     using namespace boost;
00058     typename property_map<G, edge_kp_idx_map_t>::type epmap = get(edge_kp_idx_map, g);
00059     int didx = epmap[edge(src, dest, g).first][sidx];
00060     epmap[edge(src, dest, g).first].erase(sidx);
00061     epmap[edge(dest, src, g).first].erase(didx);
00062 }
00063 
00065 template<typename G> void add_idx_pair(
00066         int src_idx, int dest_idx, 
00067         typename graph_traits<G>::vertex_descriptor src, 
00068         typename graph_traits<G>::vertex_descriptor dest, G& g){
00069     using namespace boost;
00070     typename property_map<G, edge_kp_idx_map_t>::type epmap = get(edge_kp_idx_map, g);
00071     assert((size_t)dest_idx < get(vertex_kp, g, dest).size());
00072     assert((size_t)src_idx < get(vertex_kp, g, src).size());
00073     epmap[edge(src, dest, g).first][src_idx] = dest_idx;
00074     epmap[edge(dest, src, g).first][dest_idx] = src_idx;
00075 }
00076 
00078 template<typename G> void add_idx_pair_from_dmatch(
00079         const cv::DMatch& dmatch,
00080         typename graph_traits<G>::vertex_descriptor tvd, 
00081         typename graph_traits<G>::vertex_descriptor qvd, 
00082         G& g){
00083     add_idx_pair(dmatch.trainIdx, dmatch.queryIdx, tvd, qvd, g);
00084 }
00085 
00087 template<typename G> bool filter_index_pair_duplicates(
00088         const cv::DMatch& dmatch, 
00089         typename graph_traits<G>::vertex_descriptor src, 
00090         typename graph_traits<G>::vertex_descriptor dest, G& g){
00091     using namespace boost;
00092     bool add = (getFeatureIdx(g, dmatch.trainIdx, src, dest) == BAD_INDEX);
00093     add = add && (getFeatureIdx(g, dmatch.queryIdx, dest, src) == BAD_INDEX);
00094     return add;
00095 }
00096 
00100 inline vector<cv::DMatch> remapDMatchIdxs(
00101         const vector<cv::DMatch>& dmatches, const vector<int>& tidx, const vector<int>& qidx){
00102     vector<cv::DMatch> result;
00103     result.reserve(dmatches.size());
00104     for(vector<cv::DMatch>::const_iterator it=dmatches.begin(); it!= dmatches.end(); ++it){
00105         cv::DMatch tmp = *it;
00106         tmp.trainIdx = tidx[it->trainIdx];
00107         tmp.queryIdx = qidx[it->queryIdx];
00108         result.push_back(tmp);
00109     }
00110     return result;
00111 }
00112 
00113 inline cv::DMatch dmatchFromPair(const pair<int, int>& p){
00114     return cv::DMatch(p.first, p.second, 0.1);
00115 }
00116 
00117 inline pair<int, int> pairFromDMatch(const cv::DMatch& dmatch){
00118     return make_pair(dmatch.trainIdx, dmatch.queryIdx);
00119 }
00120 
00127 template<template<class, class> class CT, class G> CT<int, std::allocator<int> > 
00128 common_feature_tracks(
00129         G&g, 
00130         typename graph_traits<G>::vertex_descriptor vad, 
00131         typename graph_traits<G>::vertex_descriptor vbd, 
00132         typename graph_traits<G>::vertex_descriptor vcd){
00133     typename property_map<G, edge_kp_idx_map_t>::type ekpimap = get(edge_kp_idx_map, g);
00134     typedef typename graph_traits<G>::edge_descriptor EdgeD;
00135     EdgeD edba = edge(vbd, vad, g).first;
00136     EdgeD edbc = edge(vbd, vcd, g).first;
00137     CT<int, std::allocator<int> > common_b_idx = switchCont<CT>(getCommon(
00138             transformF<int>(mapToList(ekpimap[edba]), getFirst),
00139             transformF<int>(mapToList(ekpimap[edbc]), getFirst)));
00140     return common_b_idx;
00141 }
00143 /*------------------------------------------------------------------------------------------*/
00144 
00145 /*------------------------------------------------------------------------------------------*/
00148 
00149 
00151 template<class G> ImageMatch computeMatch(const G&g, FeatureID<G> source, FeatureID<G> target){
00152     using namespace boost;
00153     typename property_map<G, vertex_kp_t>::const_type kp_pmap = get(vertex_kp, g);
00154     cv::KeyPoint kp;
00155     kp = kp_pmap[source.vd][source.vidx];
00156     PanoImCoord c1 = PanoImCoord::fromPixel(Vector2d(kp.pt.x, kp.pt.y));
00157     kp = kp_pmap[target.vd][target.vidx];
00158     PanoImCoord c2 = PanoImCoord::fromPixel(Vector2d(kp.pt.x, kp.pt.y));
00159     return ImageMatch(c1.getHomogenous(), c2.getHomogenous());
00160 }
00161 
00162 template<class G> ImageMatch computeMatch(const G&g, int source_idx,
00163         typename graph_traits<G>::vertex_descriptor source_vd, 
00164         typename graph_traits<G>::vertex_descriptor target_vd){
00165     using namespace boost;
00166     int target_idx = getFeatureIdx(g, source_idx, source_vd, target_vd);
00167     return computeMatch(g, FeatureID<G>(source_vd, source_idx), FeatureID<G>(target_vd, target_idx));
00168 }
00169 
00170 
00171 
00172 template<typename G> ImageMatchVec computeMatches(
00173         typename graph_traits<G>::vertex_descriptor src, 
00174         typename graph_traits<G>::vertex_descriptor dest, 
00175         const G& g){
00176     using namespace boost;
00177     ImageMatchVec matches;
00178     typename property_map<G, vertex_kp_t>::const_type vkpmap = get(vertex_kp, g);
00179     for(vector<cv::KeyPoint>::size_type i=0; i<vkpmap[src].size(); i++){
00180         if(getFeatureIdx(g, i, src, dest)!=BAD_INDEX){
00181             matches.push_back(computeMatch(g, i, src, dest));
00182         }
00183     }
00184     return matches;
00185 }
00186 
00188 /*------------------------------------------------------------------------------------------*/
00189 
00190 /*------------------------------------------------------------------------------------------*/
00193 
00195 
00196 template<class PoseGraphT> SE3 getEdgeTransform(
00197         const PoseGraphT& g, 
00198         typename graph_traits<PoseGraphT>::vertex_descriptor vd1, 
00199         typename graph_traits<PoseGraphT>::vertex_descriptor vd2){
00200     return  get(vertex_transform, g, vd2) * get(vertex_transform, g, vd1).inverse();
00201 }
00202 
00204 template<class G> void setEdgeTransform(
00205         const SE3& T_tvd_qvd, 
00206         typename graph_traits<G>::vertex_descriptor tvd,
00207         typename graph_traits<G>::vertex_descriptor qvd,
00208         G& g){
00209     get(edge_transform, g, edge(tvd, qvd, g).first) = T_tvd_qvd;
00210     get(edge_transform, g, edge(qvd, tvd, g).first) = T_tvd_qvd.inverse();
00211     get(vertex_transform, g, qvd) = T_tvd_qvd * get(vertex_transform, g, tvd);
00212 }
00214 /*------------------------------------------------------------------------------------------*/
00215 
00216 /*------------------------------------------------------------------------------------------*/
00221 
00222 
00223 inline double vectorAngle(const Vector3d& vec1, const Vector3d& vec2){
00224     double d = (vec1.normalized() - vec2.normalized()).norm();
00225     double angle = asin(d/2.0) * 2.0;
00226     return angle;
00227 }
00228 
00229 template<class PoseGraphT> double disparityAngle( 
00230         const PoseGraphT& g, FeatureID<PoseGraphT> f1, FeatureID<PoseGraphT> f2){
00231     SE3 T_wv1 = get(vertex_transform, g, f1.vd);
00232     SE3 T_wv2 = get(vertex_transform, g, f2.vd);
00233     SE3 T_v1v2 = T_wv2 * T_wv1.inverse();
00234 
00235     ImageMatch m = computeMatch(g, f1, f2);
00236     m.first = (T_v1v2.rotation_matrix() * m.first).eval();
00237     return vectorAngle(m.first, m.second);
00238 }
00239 
00240 
00241 template<class PoseGraphT> double minEdgeDisparityAngle(
00242         PoseGraphT& g,
00243         typename graph_traits<PoseGraphT>::vertex_descriptor srcv,
00244         typename graph_traits<PoseGraphT>::vertex_descriptor destv){
00245     //vector<pair<FeatureID<PoseGraphT>, FeatureID<PoseGraphT> > > feature_pairs;
00246     vector<double> disparity_angles;
00247     const map<int, int> & src_dst_map = get(edge_kp_idx_map, g, edge(srcv, destv, g).first);
00248 
00249     for(map<int, int>::const_iterator it=src_dst_map.begin(); it!=src_dst_map.end(); ++ it){
00250         double angle =disparityAngle(g, FeatureID<PoseGraphT>(srcv, it->first), 
00251                 FeatureID<PoseGraphT>(destv, it->second));
00252         disparity_angles.push_back(angle);
00253     }
00254     std::sort(disparity_angles.begin(), disparity_angles.end());
00255     return disparity_angles[disparity_angles.size() - disparity_angles.size() / 10];
00256 }
00258 /*------------------------------------------------------------------------------------------*/
00259 
00260 /*------------------------------------------------------------------------------------------*/
00263 
00269 template<class G> Vector3d triangulatePointWrtWorld(const G& g, FeatureID<G> f1, FeatureID<G> f2){
00270     SE3 T_v1v2 = getEdgeTransform(g, f1.vd, f2.vd);
00271     ImageMatchVec matches;
00272     matches.push_back(computeMatch(g, f1, f2));
00273     Points3dSTL tr_pts;
00274     computeStructure(T_v1v2, matches, tr_pts);
00275     return get(vertex_transform, g, f1.vd).inverse() * tr_pts[0];
00276 }
00277 
00278 template<class G> Vector3d triangulatePointWrtWorldPos(const G& g, FeatureID<G> f1, FeatureID<G> f2){
00279     SE3 T_v1v2 = getEdgeTransform(g, f1.vd, f2.vd);
00280     ImageMatchVec matches;
00281     matches.push_back(computeMatch(g, f1, f2));
00282     Points3dSTL tr_pts;
00283     computeStructureForcePositiveDepths(T_v1v2, matches, tr_pts);
00284     return get(vertex_transform, g, f1.vd).inverse() * tr_pts[0];
00285 }
00286 
00287 inline bool isEstimateInFrontOfCamera(const LandmarkObservation& obs, const Vector3d& estimate){ 
00288     double angle = vectorAngle(
00289             obs.T_cw.inverse() * estimate, PanoImCoord::fromPixel(obs.pixel).getHomogenous());
00290     //std::cout << "Angle: " << angle << endl;
00291     if(angle < 0.5 * M_PI) return true;
00292     else return false;
00293 }
00295 /*------------------------------------------------------------------------------------------*/
00296 
00297 
00298 template<class G> void landmarkObservationsBySize(
00299         const G& g, 
00300         Points<G>& points, 
00301         typename graph_traits<G>::vertex_descriptor vd, 
00302         vector<vector<int> > & all_result,
00303         vector<vector<int> > & kf_result){
00304     const vector<cv::KeyPoint> & keypoints = get(vertex_kp, g, vd);
00305     const vector<int> & fix_map = get(vertex_fix_idx, g, vd);
00306     
00307     int maxlen=8;
00308     all_result.assign(maxlen+1, vector<int>());
00309     kf_result.assign(maxlen+1, vector<int>());
00310 
00311     for(int kp_idx=0; kp_idx< (int)keypoints.size(); kp_idx++){
00312         if(fix_map[kp_idx]!=BAD_INDEX && points.getPoint(fix_map[kp_idx]).initialized){
00313             int sz = points.getPoint(fix_map[kp_idx]).seen_from.size();
00314             for(sz=std::min(sz, maxlen); sz>0; sz--){
00315                 all_result[sz].push_back(fix_map[kp_idx]);
00316             }
00317             int count=0;
00318             typedef pair<typename Point<G>::VertexD, int> T;
00319             BOOST_FOREACH(T fc, points.getPoint(fix_map[kp_idx]).seen_from){
00320                 if(get(boost::vertex_keyframe_flag, g, fc.first)){
00321                     count++;
00322                 }
00323             }
00324             for(count=std::min(count, maxlen); count>0; count--){
00325                 kf_result[count].push_back(fix_map[kp_idx]);
00326             }
00327         }
00328     }
00329 }
00330 
00331 
00333 template<class G> Vector2d getFeaturePixel(const G& g, const FeatureID<G> f){
00334     cv::KeyPoint kp = get(vertex_kp, g, f.vd)[f.vidx];
00335     return Vector2d(kp.pt.x, kp.pt.y);
00336 }
00337 
00338 template<class G> 
00339 double maxFeatureDistance(const G& g, const Points<G>& points, typename Point<G>::VertexD v){
00340     const vector<int>& fix_idxs = get(vertex_fix_idx, g,  v);
00341     double max=0;
00342     for(size_t idx1=0; idx1 < fix_idxs.size(); idx1++){
00343         for(size_t idx2=0; idx2 < fix_idxs.size(); idx2++){
00344             if(fix_idxs[idx1]!=BAD_INDEX && fix_idxs[idx2]!=BAD_INDEX){
00345                 if(points.getPoint(fix_idxs[idx1]).initialized && points.getPoint(idx2).initialized){
00346                     double val = (getFeaturePixel(g, FeatureID<G>(v, idx1)) - 
00347                             getFeaturePixel(g, FeatureID<G>(v, idx2))).norm();
00348                     if(val > max){
00349                         max=val;
00350                     }
00351                 }
00352             }
00353         }
00354     }
00355     return max;
00356 }
00357 
00359 template<class G> std::string printVertexId(
00360         const G& g, typename graph_traits<G>::vertex_descriptor vd){
00361     std::ostringstream oss;
00362     oss << get(vertex_seq, g, vd);
00363     return oss.str();
00364 }
00365 
00366 
00367 
00368 
00370 
00372 
00373 }//namespace vslam
00374 
00375 
00376 
00377 #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