00001
00063 #ifndef SEGMENTATION_QUAD_REGR_H_
00064 #define SEGMENTATION_QUAD_REGR_H_
00065
00066
00067 #include <visualization_msgs/MarkerArray.h>
00068 #include "../point_types.h"
00069 #include "quad_regression_algo.h"
00070
00071 namespace Segmentation
00072 {
00073
00074
00075
00076
00080 template <typename Point, typename PointLabel, typename Parent>
00081 class Segmentation_QuadRegression : public GeneralSegmentation<Point, PointLabel>, public Parent
00082 {
00083
00084 void back_check_repeat();
00085
00086 boost::shared_ptr<const pcl::PointCloud<PointLabel> > compute_labeled_pc();
00087 boost::shared_ptr<const pcl::PointCloud<PointLabel> > compute_reconstructed_pc();
00088
00089 public:
00091 virtual ~Segmentation_QuadRegression() {
00092 }
00093
00095 virtual boost::shared_ptr<const pcl::PointCloud<PointLabel> > getOutputCloud() {
00096 return compute_labeled_pc();
00097 }
00098
00100 virtual boost::shared_ptr<const pcl::PointCloud<PointLabel> > getReconstructedOutputCloud() {
00101 return compute_reconstructed_pc();
00102 }
00103
00105 virtual void setInputCloud (const boost::shared_ptr<const pcl::PointCloud<Point> > &cloud)
00106 {
00107 this->Parent::setInputCloud(cloud);
00108 }
00109
00110 virtual bool compute();
00111
00112 virtual bool extractImages();
00113
00115 operator cob_3d_mapping_msgs::ShapeArray() const;
00116
00118 operator visualization_msgs::Marker() const;
00119
00120
00121 void compute_accuracy(float &mean, float &var, float &mean_weighted, float &var_weighted, size_t &used, size_t &mem, size_t &points, float &avg_dist, const boost::shared_ptr<const pcl::PointCloud<PointLabel> > &labeled_pc, double &true_positive, double &false_positive);
00122
00124 std::istream &serialize(std::istream &is);
00126 std::ostream &serialize(std::ostream &is) const;
00127 };
00128
00129 #include "impl/quad_regression.hpp"
00130
00131 #if 0
00132
00133 #define getInd(x, y) ((x)+(y)*levels_[i].w)
00134 #define getInd1(x, y) ((x)+(y)*levels_[i-1].w)
00135 #define getInd2(x, y) ((x)+(y)*levels_[i+2].w)
00136 #define getInd3(x, y) ((x)+(y)*levels_[i+1].w)
00137 #define getIndPC(x, y) ((x)+(y)*pc.width)
00138
00142 template <typename Point, typename PointLabel>
00143 class Segmentation_QuadRegression : public GeneralSegmentation<Point, PointLabel>
00144 {
00145
00146
00150 struct SKINECTPARAMS {
00151 float f,dx,dy;
00152 };
00153
00154
00155 const unsigned int MIN_LOD;
00156 const unsigned int FINAL_LOD;
00157 const unsigned int GO_DOWN_TO_LVL;
00158
00159
00160 boost::shared_ptr<const pcl::PointCloud<Point> > input_;
00161
00162 std::vector<SubStructure::ParamC> levels_;
00163 std::vector<Segmentation::S_POLYGON> polygons_;
00164 int *ch_;
00165 SKINECTPARAMS kinect_params_;
00166
00167 bool *outline_check_;
00168 size_t outline_check_size_;
00169 float filter_;
00170 bool only_planes_;
00171
00172 #ifdef STOP_TIME
00173 double execution_time_quadtree_, execution_time_growing_, execution_time_polyextraction_;
00174 #endif
00175
00176 void prepare(const pcl::PointCloud<Point> &pc);
00177 void getKinectParams(const pcl::PointCloud<Point> &pc);
00178
00179 void buildTree(const pcl::PointCloud<Point> &pc);
00180 void calc();
00181 void back_check_repeat();
00182
00183 void grow(SubStructure::Model &model, const int i, const int x, const int y);
00184 void grow(SubStructure::VISITED_LIST<SubStructure::SVALUE> &list, SubStructure::Model &model, const int i, const int mark, bool first_lvl);
00185
00186 inline bool filterOccupied(const int i, const int x, const int y, const int mark) const {
00187 if(i>=(int)levels_.size())
00188 return false;
00189 if(levels_[i].data[getInd(x,y)].occopied==mark)
00190 return true;
00191 return filterOccupied(i+1,x/2,y/2,mark);
00192 }
00193
00194 inline int otherOccupied(const int i, const int x, const int y, const int mark) const {
00195 if(i>=(int)levels_.size() || x<0 || y<0 || x>=(int)levels_[i].w || y>=(int)levels_[i].h)
00196 return -1;
00197 if(levels_[i].data[getInd(x,y)].occopied>=0 && levels_[i].data[getInd(x,y)].occopied!=mark)
00198 return levels_[i].data[getInd(x,y)].occopied;
00199 return otherOccupied(i+1,x/2,y/2,mark);
00200 }
00201
00202 inline int isOccupied(const int i, const int x, const int y) const {
00203 if(i>=(int)levels_.size())
00204 return -1;
00205 if(levels_[i].data[getInd(x,y)].occopied>=0)
00206 return levels_[i].data[getInd(x,y)].occopied;
00207 return isOccupied(i+1,x/2,y/2);
00208 }
00209
00210 inline bool checkModelAt(const SubStructure::Model &model, const int i, const int x, const int y, const float thr) const {
00211 if(i==0)
00212 return model.check_tangent(levels_[i].data[getInd(x,y)], thr);
00213
00214 return
00215 model.check_tangent(levels_[i-1].data[getInd1(2*x,2*y)], thr) &&
00216 model.check_tangent(levels_[i-1].data[getInd1(2*x,2*y+1)], thr) &&
00217 model.check_tangent(levels_[i-1].data[getInd1(2*x+1,2*y)], thr) &&
00218 model.check_tangent(levels_[i-1].data[getInd1(2*x+1,2*y+1)], thr);
00219 }
00220
00221 inline void addPoint(const int i, const int x, const int y, const int mark, S_POLYGON &poly, const SubStructure::Model &model, const float v=0.f) {
00222
00223 #if 0
00224 for(int xx=-1; xx<2; xx++)
00225 for(int yy=-1; yy<2; yy++)
00226 if(x+xx>=0 && y+yy>=0 && x+xx<(int)levels_[i].w && y+yy<(int)levels_[i].h
00227 && filterOccupied(i,x+xx,y+yy,mark)
00228
00229 ){
00230 Eigen::Vector3f p;
00231 p(0) = levels_[i].data[getInd(x+xx,y+yy)].model_(0,1)/levels_[i].data[getInd(x+xx,y+yy)].model_(0,0);
00232 p(1) = levels_[i].data[getInd(x+xx,y+yy)].model_(0,3)/levels_[i].data[getInd(x+xx,y+yy)].model_(0,0);
00233 p(2) = levels_[i].data[getInd(x+xx,y+yy)].z_(0)/levels_[i].data[getInd(x+xx,y+yy)].model_(0,0);
00234
00235
00236
00237
00238
00239
00240 p.head<2>() = poly.nextPoint(p);
00241
00242
00243
00244
00245
00246
00247 if(!pcl_isfinite(p.sum())) continue;
00248 p(2) = v;
00249 poly.segments_.back().push_back(p);
00250 return;
00251 }
00252 for(int xx=-1; xx<2; xx++)
00253 for(int yy=-1; yy<2; yy++)
00254 if(x+xx>=0 && y+yy>=0 && x+xx<(int)levels_[i].w && y+yy<(int)levels_[i].h
00255 && poly.model_.check_tangent(levels_[i].data[getInd(x+xx,y+yy)],0.02f)){
00256 Eigen::Vector3f p;
00257 p(0) = levels_[i].data[getInd(x+xx,y+yy)].model_(0,1)/levels_[i].data[getInd(x+xx,y+yy)].model_(0,0);
00258 p(1) = levels_[i].data[getInd(x+xx,y+yy)].model_(0,3)/levels_[i].data[getInd(x+xx,y+yy)].model_(0,0);
00259 p(2) = levels_[i].data[getInd(x+xx,y+yy)].z_(0)/levels_[i].data[getInd(x+xx,y+yy)].model_(0,0);
00260
00261
00262
00263
00264
00265
00266
00267 if(!pcl_isfinite(p.sum())) continue;
00268 p(2) = v;
00269 poly.segments_.back().push_back(p);
00270 return;
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 #endif
00292
00293 #ifdef DO_NOT_DOWNSAMPLE_
00294 const int fact=1;
00295 #else
00296 const int fact=2;
00297 #endif
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 Eigen::Vector3f p = poly.project2plane(((x<<(i+fact-1))-kinect_params_.dx)/kinect_params_.f,
00316 ((y<<(i+fact-1))-kinect_params_.dy)/kinect_params_.f,
00317 model,v);
00318
00319 #if 0
00320 poly.segments_.back().push_back(p);
00321 #ifdef USE_BOOST_POLYGONS_
00322 poly.segments2d_.back().push_back(BoostPoint(x,y));
00323 #elif defined(BACK_CHECK_REPEAT)
00324 Eigen::Vector2i p2;
00325 p2(0) = x;
00326 p2(1) = y;
00327 poly.segments2d_.back().push_back(p2);
00328 #endif
00329
00330 return;
00331 #endif
00332
00333 Eigen::Vector3f vp = poly.project2world(p.head<2>());
00334
00335 float d = poly.middle_(2);
00336 d*=d;
00337
00338 static const int rel_motion_pattern[][2] = { {0,0}, {-1,-1}, {-1,0}, {-1,1}, {0,-1}, {0,1}, {1,-1}, {1,0}, {1,1}
00339
00340
00341 };
00342
00343
00344 const pcl::PointCloud<Point> &pc = *input_;
00345
00346
00347 for(size_t i=0; i<sizeof(rel_motion_pattern)/sizeof(rel_motion_pattern[0]); i++) {
00348 int xx=rel_motion_pattern[i][0];
00349 int yy=rel_motion_pattern[i][1];
00350
00351 if(fact*x+xx>=0 && fact*y+yy>=0 && fact*x+xx<(int)pc.width && fact*y+yy<(int)pc.height) {
00352 Eigen::Vector3f p = poly.project2plane((((fact*x+xx)<<(i))-kinect_params_.dx)/kinect_params_.f,
00353 (((fact*y+yy)<<(i))-kinect_params_.dy)/kinect_params_.f,
00354 model,v);
00355
00356 if( (poly.project2world(p.head<2>())-pc[getIndPC(fact*x+xx,fact*y+yy)].getVector3fMap()).squaredNorm()<std::max(0.0005f,0.0005f*d)
00357 && (poly.project2world(p.head<2>())-vp).squaredNorm()<0.02f)
00358 {
00359 poly.segments_.back().push_back(p);
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 #ifdef USE_BOOST_POLYGONS_
00374 poly.segments2d_.back().push_back(BoostPoint(x,y));
00375 #elif defined(BACK_CHECK_REPEAT)
00376 Eigen::Vector2i p2;
00377 p2(0) = x+xx/fact;
00378 p2(1) = y+yy/fact;
00379 poly.segments2d_.back().push_back(p2);
00380 #endif
00381
00382 return;
00383 }
00384 }
00385
00386 }
00387 #if 0
00388 for(int xx=-8; xx<9; xx++)
00389 for(int yy=-8; yy<9; yy++)
00390 if(fact*x+xx>=0 && fact*y+yy>=0 && fact*x+xx<(int)pc.width && fact*y+yy<(int)pc.height) {
00391 Eigen::Vector3f p = poly.project2plane((((fact*x+xx)<<(i))-kinect_params_.dx)/kinect_params_.f,
00392 (((fact*y+yy)<<(i))-kinect_params_.dy)/kinect_params_.f,
00393 model,v);
00394
00395 if( (poly.project2world(p.head<2>())-pc[getIndPC(fact*x+xx,fact*y+yy)].getVector3fMap()).squaredNorm()<std::max(0.0005f,0.0005f*d)
00396 && (poly.project2world(p.head<2>())-vp).squaredNorm()<0.02f)
00397 {
00398 poly.segments_.back().push_back(p);
00399
00400
00401
00402
00403
00404
00405
00406 #ifdef USE_BOOST_POLYGONS_
00407 poly.segments2d_.back().push_back(BoostPoint(x,y));
00408 #elif defined(BACK_CHECK_REPEAT)
00409 Eigen::Vector2i p2;
00410 p2(0) = x+xx/fact;
00411 p2(1) = y+yy/fact;
00412 poly.segments2d_.back().push_back(p2);
00413 #endif
00414
00415 return;
00416 }
00417 }
00418 #endif
00419
00420 if(poly.normalAt(p.head<2>())(2)>0.5f)
00421 {
00422 poly.segments_.back().push_back(p);
00423 #ifdef USE_BOOST_POLYGONS_
00424 poly.segments2d_.back().push_back(BoostPoint(x,y));
00425 #elif defined(BACK_CHECK_REPEAT)
00426 Eigen::Vector2i p2;
00427 p2(0) = x;
00428 p2(1) = y;
00429 poly.segments2d_.back().push_back(p2);
00430 #endif
00431 }
00432 }
00433
00434 int getPos(int *ch, const int xx, const int yy, const int w, const int h);
00435
00436 void outline(int *ch, const int w, const int h, std::vector<SubStructure::SXY> &out, const int i, S_POLYGON &poly, const SubStructure::Model &model, const int mark);
00437
00438 boost::shared_ptr<const pcl::PointCloud<PointLabel> > compute_labeled_pc();
00439 boost::shared_ptr<const pcl::PointCloud<PointLabel> > compute_reconstructed_pc();
00440
00441 public:
00443 Segmentation_QuadRegression();
00444
00446 virtual ~Segmentation_QuadRegression() {
00447 delete [] ch_;
00448 delete [] outline_check_;
00449 }
00450
00452 virtual void setInputCloud (const boost::shared_ptr<const pcl::PointCloud<Point> > &cloud)
00453 {
00454 input_ = cloud;
00455 if(levels_.size()==0)
00456 prepare(*cloud);
00457 else if(kinect_params_.f == 0.f)
00458 getKinectParams(*cloud);
00459 }
00460
00462 virtual boost::shared_ptr<const pcl::PointCloud<PointLabel> > getOutputCloud() {
00463 return compute_labeled_pc();
00464 }
00465
00467 virtual boost::shared_ptr<const pcl::PointCloud<PointLabel> > getReconstructedOutputCloud() {
00468 return compute_reconstructed_pc();
00469 }
00470
00471 virtual bool compute();
00472
00473 virtual bool extractImages();
00474
00476 operator cob_3d_mapping_msgs::ShapeArray() const;
00477
00479 operator visualization_msgs::Marker() const;
00480
00482 const std::vector<Segmentation::S_POLYGON> &getPolygons() const {return polygons_;}
00483
00484
00485 void compute_accuracy(float &mean, float &var, size_t &used, size_t &mem, size_t &points, float &avg_dist);
00486
00487 #ifdef STOP_TIME
00488 void getExecutionTimes(double &quadtree, double &growing, double &extraction)
00489 {
00490 quadtree = execution_time_quadtree_;
00491 extraction = execution_time_polyextraction_;
00492 growing = execution_time_growing_ - extraction;
00493 }
00494 #endif
00495
00496 void setFilter(const float f) {filter_=f;}
00497 void setOnlyPlanes(const bool b) {only_planes_=b;}
00498
00499 };
00500
00501 #include "impl/quad_regression.hpp"
00502
00503 #undef getInd
00504 #undef getInd1
00505 #undef getInd2
00506 #undef getIndPC
00507 #endif
00508 }
00509
00510 #endif