Go to the documentation of this file.00001
00011 #ifndef VSLAM_MODEL_ESTIMATION_H_INCLUDED
00012 #define VSLAM_MODEL_ESTIMATION_H_INCLUDED
00013
00014 #include "model.h"
00015 #include "error_func.h"
00016 #include "utils.h"
00017 #include <Eigen/Dense>
00018 #include "sfm_utils.h"
00019 #include "lihartley5pt/interface.h"
00020
00021
00022
00034 struct ImageMatchClass{
00035 typedef ALIGNED<ImageMatchClass>::vector ImageMatchClassVec;
00036 const Vector3d im_c1, im_c2;
00037 ImageMatchClass(const Vector3d& a, const Vector3d& b) : im_c1(a), im_c2(b) { }
00038 ImageMatch getAsImageMatch(){
00039 return std::make_pair(im_c1, im_c2);
00040 }
00041 };
00042
00043
00050 template<class ErrorAccumClassT>
00051 class Point3dModelFromLandmarkObservationPairBuilder : public GeneralizedModelBuilder<ErrorAccumClassT>{
00052 public:
00053 typedef Model<Vector3d, LandmarkObservation> Point3dModel;
00054
00055 Point3dModelFromLandmarkObservationPairBuilder(const ErrorAccumClassT& _error_accum) :
00056 GeneralizedModelBuilder<ErrorAccumClassT>(_error_accum) { }
00057
00058 virtual shared_ptr<Point3dModel> operator()(const Point3dModel::DataVec & selected){
00059 assert(selected.size()==getSize());
00060 LandmarkObservation oa = selected[0];
00061 LandmarkObservation ob = selected[1];
00062 Vector3d pt_c1;
00063 Vector3d oa_bproj, ob_bproj;
00064 oa_bproj = PanoImCoord::fromPixel(oa.pixel).getHomogenous();
00065 ob_bproj = PanoImCoord::fromPixel(ob.pixel).getHomogenous();
00066 computeStructureForcePositiveDepth( ob.T_cw.inverse() * oa.T_cw,
00067 ImageMatchClass(oa_bproj, ob_bproj).getAsImageMatch(), pt_c1);
00068 Vector3d pt_w = oa.T_cw * pt_c1;
00069 return shared_ptr<Point3dModel>(new SingleSolutionModel<ErrorAccumClassT>(
00070 getSize(), selected, pt_w, this->error_accum));
00071 }
00072 virtual unsigned int getSize() const { return 2; }
00073 };
00074
00076
00077
00078
00081
00082
00083 class ScaleObservation{
00084 public:
00085 Vector2d k_proj_measurement;
00086 Vector2d n_proj_measurement;
00087 Vector3d lm_estimate_kk_k;
00088 SE3 T_wk;
00089 SE3 T_kn;
00090
00091 };
00092
00093
00094
00095 class ScaleReprojectionError : public DatumErrorFunc<double, ScaleObservation, Vector2d> {
00096 private:
00097 LandmarkToPoseReprojectionError lm_reprojection_error;
00098 public:
00099 virtual Vector2d operator()(const double& model, const ScaleObservation& datum) const{
00100 SE3 T_kn(datum.T_kn.unit_quaternion(), model * datum.T_kn.translation());
00101 LandmarkObservation lm_obs((T_kn * datum.T_wk).inverse(), datum.n_proj_measurement);
00102 return lm_reprojection_error(datum.T_wk.inverse() * datum.lm_estimate_kk_k, lm_obs);
00103 }
00104 };
00105
00106
00107 template<class ErrorAccumClassT>
00108 class ScaleModelBuilder : public GeneralizedModelBuilder<ErrorAccumClassT>{
00109 public:
00110 typedef typename ErrorAccumClassT::ModelClassT ScaleModel;
00111
00112 ScaleModelBuilder(const ErrorAccumClassT& _error_accum) :
00113 GeneralizedModelBuilder<ErrorAccumClassT>(_error_accum) { }
00114
00115 virtual shared_ptr<ScaleModel> operator()(const typename ScaleModel::DataVec & selected){
00116 assert(selected.size()==this->getSize());
00117 ScaleObservation datum = selected[0];
00118 Vector3d estimate_kn_k;
00119 computeStructureForcePositiveDepth(
00120 datum.T_kn,
00121 computeMatch(datum.k_proj_measurement, datum.n_proj_measurement),
00122 estimate_kn_k);
00123 return shared_ptr<ScaleModel>(new SingleSolutionModel<ErrorAccumClassT>(
00124 getSize(),
00125 selected,
00126 (datum.lm_estimate_kk_k.norm() / estimate_kn_k.norm()),
00127 this->error_accum));
00128 }
00129
00130 virtual unsigned int getSize() const { return 1; }
00131 };
00132
00134
00135
00137
00138
00139
00142
00145
00146
00148 template<class ContainerT> class DataSelector{
00149 public:
00153 virtual shared_ptr<ContainerT> select() = 0;
00154 };
00155
00156
00157 template<class ContainerT> class RandomDataSelector : public DataSelector<ContainerT>{
00158 const ContainerT data;
00159 int model_size;
00160 int num_iterations;
00161 int iterations;
00162
00163 public:
00164 RandomDataSelector(const ContainerT& _data, int _model_size, int _num_iterations) :
00165 data(_data), model_size(_model_size) {
00166 num_iterations=_num_iterations;
00167 iterations=0;
00168 }
00169
00170 virtual shared_ptr<ContainerT> select(){
00171 if(iterations > num_iterations) return shared_ptr<ContainerT>();
00172
00173 std::set<int> selected_idx;
00174 assert(static_cast<int>(data.size())>=model_size);
00175 while(static_cast<int>(selected_idx.size()) < model_size){
00176 boost::uniform_int<> interval(0,data.size() - 1);
00177 selected_idx.insert(interval(rng_mt19937));
00178 }
00179 shared_ptr<ContainerT> selected(new ContainerT());
00180 for(std::set<int>::iterator it=selected_idx.begin(); it!=selected_idx.end(); it++){
00181 selected->push_back(data[*it]);
00182 }
00183 ++iterations;
00184 return selected;
00185 }
00186 };
00187
00188 template<class ContainerT> class PairSelectorFromTwoSets : public DataSelector<ContainerT>{
00189 private:
00190 const ContainerT data1, data2;
00191 typename ContainerT::const_iterator it1, it2;
00192 bool past_end;
00193
00194 PairSelectorFromTwoSets(const ContainerT& _data1, const ContainerT& _data2) :
00195 data1(_data1), data2(_data2){
00196 it1=data1.begin();
00197 it2=data2.begin();
00198 past_end=false;
00199 }
00200
00201 virtual shared_ptr<ContainerT> select(){
00202 if(past_end) return 0;
00203
00204 shared_ptr<ContainerT> selected_data(new ContainerT());
00205 selected_data->push_back(*it1);
00206 selected_data->push_back(*it2);
00207
00208 it2++;
00209 if(it2==data2.end()){
00210 it1++;
00211 if(it1==data1.end()){
00212 past_end=true;
00213 } else{
00214 it2=data2.begin();
00215 }
00216 }
00217
00218 return selected_data;
00219 }
00220 };
00221
00222
00223 template<class ContainerT> class AllCombinationsSelector : public DataSelector<ContainerT>{
00224 private:
00225 const ContainerT data;
00226 std::deque<typename ContainerT::const_iterator> state;
00227 bool past_end;
00228 int model_size;
00229
00230 typedef typename ContainerT::const_iterator T;
00231
00232 void next(){
00233 T it = state.back();
00234 state.pop_back();
00235 ++it;
00236 if(it == data.end()){
00237 if(state.size()==0){
00238 past_end=true;
00239 } else{
00240 next();
00241 }
00242 state.push_back(data.begin());
00243 } else{
00244 state.push_back(it);
00245 }
00246 }
00247 public:
00248 AllCombinationsSelector(const ContainerT& _data, int _model_size) :
00249 data(_data), model_size(_model_size){
00250 assert(static_cast<int>(data.size()) > model_size);
00251 for(int i=0; i < model_size;i++){
00252 typename ContainerT::const_iterator it = data.begin();
00253 for(int j=0; j<i; j++){
00254 it++;
00255 }
00256 state.push_back(it);
00257 }
00258 past_end=false;
00259 }
00260
00261 virtual shared_ptr<ContainerT> select(){
00262 if(past_end){
00263 return shared_ptr<ContainerT>();
00264 } else{
00265 shared_ptr<ContainerT> selected_data(new ContainerT());
00266 BOOST_FOREACH(T it, state){
00267 selected_data->push_back(*it);
00268 }
00269 next();
00270 return selected_data;
00271 }
00272 }
00273 };
00274
00276
00277
00278
00282 template<class ErrorAccumClassT> class RanSaCOptions{
00283 private:
00284 int iterations;
00285 shared_ptr<double> inlier_ratio;
00286 shared_ptr<int> min_inliers;
00287 public:
00288 RanSaCOptions(int _iterations, double _inlier_ratio = 0.35) :
00289 iterations(_iterations), inlier_ratio(new double(_inlier_ratio)) {
00290 assert(_inlier_ratio < 1.0);
00291 }
00292
00293 RanSaCOptions(int _iterations, int _min_inliers) :
00294 iterations(_iterations),
00295 min_inliers(new int(_min_inliers)) {}
00296
00297 int getMinInliers(
00298 shared_ptr<ModelBuilder<ErrorAccumClassT> > mbuilder, int data_size) const{
00299 int val;
00300 if(min_inliers){
00301 val = *min_inliers;
00302 } else{
00303 val = static_cast<int>(data_size * *inlier_ratio);
00304 }
00305 val = std::max(val, mbuilder->getSize());
00306 return val;
00307 }
00308
00309 int getIterations() const{
00310 return iterations;
00311 }
00312 };
00313
00314
00321 template<class ErrorAccumClassT> shared_ptr<typename ErrorAccumClassT::ModelClassT> ranSaC(
00322 shared_ptr<ModelBuilder<typename ErrorAccumClassT::ModelClassT> > model_builder,
00323 shared_ptr<DataSelector<typename ErrorAccumClassT::ModelClassT::DataVec> > data_selector,
00324 const typename ErrorAccumClassT::ModelClassT::DataVec & data){
00325 typedef typename ErrorAccumClassT::ModelClassT ModelT;
00326 assert(model_builder);
00327 assert(data_selector);
00328 assert(data.size()>= model_builder->getSize());
00329 shared_ptr<ModelT> model, best_model;
00330 shared_ptr<typename ModelT::DataVec> selected = data_selector->select();
00331 while(selected){
00332 shared_ptr<ModelT> model = model_builder->operator()(*selected);
00333 if(model){
00334 model->compute(data);
00335 if (!best_model || (best_model->getInlierCount() < model->getInlierCount())){
00336 best_model = model;
00337 }
00338 }
00339 selected = data_selector->select();
00340 }
00341 return best_model;
00342 }
00343
00345
00346
00348
00349 #endif