00001
00063 #include <cstdlib>
00064
00065 #include <cob_3d_mapping_common/label_defines.h>
00066 #include <cob_3d_evaluation_features/label_results.h>
00067
00068 #include <boost/program_options.hpp>
00069 #include <fstream>
00070 #include <math.h>
00071
00072 #include <pcl/io/pcd_io.h>
00073 #include <pcl/point_types.h>
00074
00075 #include <pcl/filters/voxel_grid.h>
00076 #include <pcl/filters/passthrough.h>
00077 #include <pcl/kdtree/kdtree_flann.h>
00078 #include <pcl/surface/mls.h>
00079 #include <pcl/features/normal_3d.h>
00080 #include <pcl/features/principal_curvatures.h>
00081 #include <pcl/features/rsd.h>
00082 #include <pcl/features/fpfh.h>
00083
00084 #include <pcl/visualization/pcl_visualizer.h>
00085 #include <pcl/visualization/point_cloud_handlers.h>
00086
00087 #include <opencv2/ml/ml.hpp>
00088 #include <opencv2/highgui/highgui.hpp>
00089
00090 using namespace std;
00091 using namespace pcl;
00092
00093 typedef visualization::PointCloudColorHandlerRGBField<PointXYZRGB> ColorHdlRGB;
00094
00095
00096 float pass_depth_;
00097
00098 bool rsd_enable_;
00099 bool rsd_mls_enable_;
00100 bool rsd_vox_enable_;
00101 float rsd_vox_;
00102 float rsd_rn_;
00103 float rsd_rf_;
00104
00105 float r_limit_;
00106 float r_low;
00107 float r_high;
00108 float r_r1;
00109 float r_r2;
00110
00111 bool pc_enable_;
00112 bool pc_mls_enable_;
00113 bool pc_vox_enable_;
00114 float pc_vox_;
00115 float pc_rn_;
00116 float pc_rf_;
00117
00118 float c_low;
00119 float c_high;
00120 float c_r1;
00121 float c_r2;
00122
00123 bool fpfh_enable_;
00124 bool fpfh_mls_enable_;
00125 bool fpfh_vox_enable_;
00126 float fpfh_vox_;
00127 float fpfh_rn_;
00128 float fpfh_rf_;
00129
00130 string file_in_;
00131 string fpfh_svm_model_;
00132 string camera_pos_;
00133 bool quiet_;
00134
00135 string fl2label(const float & f, const size_t & precision=3)
00136 {
00137 if (f == 0)
00138 return string(precision, '0');
00139
00140 stringstream ss;
00141 ss << f;
00142 string s = ss.str();
00143 s = s.substr(2,s.length());
00144 if (precision > s.length())
00145 s += string(precision - s.length(), '0');
00146 return (s);
00147 }
00148
00149 void readOptions(int argc, char* argv[])
00150 {
00151 using namespace boost::program_options;
00152
00153 string config_file;
00154 options_description cmd("Command line options");
00155 options_description cfg("Config file options");
00156
00157 cmd.add_options()
00158 ("help", "produce help message")
00159 ("config,c", value<string>(&config_file)->default_value("config/accuracy_evaluator.cfg"),
00160 "name of a file for configuration.")
00161 ("in,i", value<string>(&file_in_), "labeled input pcd file")
00162 ("svm_model,s", value<string>(&fpfh_svm_model_), "set svm to use svm")
00163 ("camera,C", value<string>(&camera_pos_), "specify a file for initial camera position")
00164 ("quiet,Q", "disable visualization")
00165 ;
00166 cfg.add_options()
00167 ("pass.depth", value<float>(&pass_depth_), "set depth of passthrough filter")
00168
00169 ("rsd.enabled", value<bool>(&rsd_enable_), "enable rsd estimation")
00170 ("rsd.enable_mls", value<bool>(&rsd_mls_enable_), "enable surface smoothing for rsd")
00171 ("rsd.enable_vox", value<bool>(&rsd_vox_enable_), "enable voxelgrid filtering for rsd")
00172 ("rsd.voxel_size", value<float>(&rsd_vox_), "set a voxelgrid size for rsd")
00173 ("rsd.limit_rmax", value<float>(&r_limit_), "set the radius limit for rsd feature values")
00174 ("rsd.rn", value<float>(&rsd_rn_), "set the normal estimation radius for rsd")
00175 ("rsd.rf", value<float>(&rsd_rf_), "feature estimation radius for rsd")
00176 ("rsd.r_low", value<float>(&r_low), "")
00177 ("rsd.r_high", value<float>(&r_high), "")
00178 ("rsd.r_r1", value<float>(&r_r1), "sphere / cylinder")
00179 ("rsd.r_r2", value<float>(&r_r2), "edge / corner")
00180
00181 ("pc.enabled", value<bool>(&pc_enable_), "enable principal curvature estimation")
00182 ("pc.enable_mls", value<bool>(&pc_mls_enable_), "enable surface smoothing for pc")
00183 ("pc.enable_vox", value<bool>(&pc_vox_enable_), "enable voxelgrid filtering for pc")
00184 ("pc.voxel_size", value<float>(&pc_vox_), "set a voxelgrid size for pc")
00185 ("pc.rn", value<float>(&pc_rn_), "set the normal estimation radius for pc")
00186 ("pc.rf", value<float>(&pc_rf_), "feature estimation radius for pc")
00187 ("pc.c_low", value<float>(&c_low), "")
00188 ("pc.c_high", value<float>(&c_high), "")
00189 ("pc.c_r1", value<float>(&c_r1), "sphere / cylinder")
00190 ("pc.c_r2", value<float>(&c_r2), "edge / corner")
00191
00192 ("fpfh.enabled", value<bool>(&fpfh_enable_), "enable fpfh estimation")
00193 ("fpfh.enable_mls", value<bool>(&fpfh_mls_enable_), "enable surface smoothing for fpfh")
00194 ("fpfh.enable_vox", value<bool>(&fpfh_vox_enable_), "enable voxelgrid filtering for fpfh")
00195 ("fpfh.voxel_size", value<float>(&fpfh_vox_), "set a voxelgrid size for fpfh")
00196 ("fpfh.rn", value<float>(&fpfh_rn_), "set the normal estimation radius for fpfh")
00197 ("fpfh.rf", value<float>(&fpfh_rf_), "feature estimation radius for fpfh")
00198 ;
00199
00200 positional_options_description p_opt;
00201 p_opt.add("in", 1);
00202 cmd.add(cfg);
00203
00204 variables_map vm;
00205 store(command_line_parser(argc, argv)
00206 .options(cmd)
00207 .positional(p_opt).run(), vm);
00208 notify(vm);
00209
00210 if (vm.count("help"))
00211 {
00212 cout << cmd << endl;
00213 exit(0);
00214 }
00215 if (vm.count("quiet")) quiet_ = true;
00216 else quiet_ = false;
00217
00218 ifstream ifs(config_file.c_str());
00219 if (!ifs)
00220 cout << "cannot open config file: " << config_file << endl;
00221 else
00222 {
00223 store(parse_config_file(ifs, cmd), vm);
00224 notify(vm);
00225 }
00226 }
00227
00236 void processFPFH(const PointCloud<PointXYZRGB>::Ptr in,
00237 PointCloud<PointXYZRGB>::Ptr ref_out,
00238 PointCloud<PointXYZRGB>::Ptr fpfh_out)
00239 {
00240 PointCloud<Normal>::Ptr n(new PointCloud<Normal>());
00241 PointCloud<FPFHSignature33>::Ptr fpfh(new PointCloud<FPFHSignature33>());
00242
00243
00244 cout << "FPFH: Pass (with " << in->points.size() << " points)" << endl;
00245 PassThrough<PointXYZRGB> pass;
00246 pass.setInputCloud(in);
00247 pass.setFilterFieldName("z");
00248 pass.setFilterLimits(0.0f, pass_depth_);
00249 pass.filter(*ref_out);
00250
00251
00252 if (fpfh_vox_enable_)
00253 {
00254 cout << "FPFH: Voxel (with " << ref_out->points.size() << " points)" << endl;
00255 VoxelGrid<PointXYZRGB> vox;
00256 vox.setInputCloud(ref_out);
00257 vox.setLeafSize(fpfh_vox_, fpfh_vox_, fpfh_vox_);
00258 vox.filter(*ref_out);
00259 }
00260
00261 #ifdef PCL_VERSION_COMPARE //fuerte
00262 pcl::search::KdTree<PointXYZRGB>::Ptr tree (new pcl::search::KdTree<PointXYZRGB>());
00263 #else //electric
00264 pcl::KdTreeFLANN<PointXYZRGB>::Ptr tree (new pcl::KdTreeFLANN<PointXYZRGB> ());
00265 #endif
00266
00267 tree->setInputCloud(ref_out);
00268
00269
00270 if(fpfh_mls_enable_)
00271 {
00272 cout << "FPFH: MLS (with " << ref_out->points.size() << " points)" << endl;
00273
00274 #ifdef PCL_VERSION_COMPARE
00275 std::cerr << "MLS has changed completely in PCL 1.7! Requires redesign of entire program" << std::endl;
00276 exit(0);
00277 #else
00278 MovingLeastSquares<PointXYZRGB, Normal> mls;
00279 mls.setInputCloud(ref_out);
00280 mls.setOutputNormals(n);
00281 mls.setPolynomialFit(true);
00282 mls.setPolynomialOrder(2);
00283 mls.setSearchMethod(tree);
00284 mls.setSearchRadius(fpfh_rn_);
00285 mls.reconstruct(*ref_out);
00286 #endif
00287 cout << "FPFH: flip normals (with " << ref_out->points.size() << " points)" << endl;
00288 for (size_t i = 0; i < ref_out->points.size(); ++i)
00289 {
00290 flipNormalTowardsViewpoint(ref_out->points[i], 0.0f, 0.0f, 0.0f,
00291 n->points[i].normal[0],
00292 n->points[i].normal[1],
00293 n->points[i].normal[2]);
00294 }
00295 }
00296 else
00297 {
00298 cout << "FPFH: Normals (with " << ref_out->points.size() << " points)" << endl;
00299 NormalEstimation<PointXYZRGB, Normal> norm;
00300 norm.setInputCloud(ref_out);
00301 norm.setSearchMethod(tree);
00302 norm.setRadiusSearch(fpfh_rn_);
00303 norm.compute(*n);
00304 }
00305
00306
00307 #ifdef PCL_VERSION_COMPARE //fuerte
00308 tree.reset(new pcl::search::KdTree<PointXYZRGB>());
00309 #else //electric
00310 tree.reset(new KdTreeFLANN<PointXYZRGB> ());
00311 #endif
00312 tree->setInputCloud(ref_out);
00313 cout << "FPFH: estimation (with " << ref_out->points.size() << " points)" << endl;
00314 FPFHEstimation<PointXYZRGB, Normal, FPFHSignature33> fpfhE;
00315 fpfhE.setInputCloud(ref_out);
00316 fpfhE.setInputNormals(n);
00317 fpfhE.setSearchMethod(tree);
00318 fpfhE.setRadiusSearch(fpfh_rf_);
00319 fpfhE.compute(*fpfh);
00320
00321 cout << "FPFH: classification " << endl;
00322 *fpfh_out = *ref_out;
00323
00324 CvSVM svm;
00325 svm.load(fpfh_svm_model_.c_str());
00326 cv::Mat fpfh_histo(1, 33, CV_32FC1);
00327
00328 int exp_rgb, pre_rgb, predict;
00329 cob_3d_mapping_common::LabelResults stats(fl2label(fpfh_rn_),fl2label(fpfh_rf_),fpfh_mls_enable_);
00330 for (size_t idx = 0; idx < ref_out->points.size(); idx++)
00331 {
00332 exp_rgb = *reinterpret_cast<int*>(&ref_out->points[idx].rgb);
00333 memcpy(fpfh_histo.ptr<float>(0), fpfh->points[idx].histogram, sizeof(fpfh->points[idx].histogram));
00334 predict = (int)svm.predict(fpfh_histo);
00335
00336 switch(predict)
00337 {
00338 case SVM_PLANE:
00339 pre_rgb = LBL_PLANE;
00340 if (exp_rgb != LBL_PLANE && exp_rgb != LBL_UNDEF) stats.fp[EVAL_PLANE]++;
00341 break;
00342 case SVM_EDGE:
00343 pre_rgb = LBL_EDGE;
00344 if (exp_rgb != LBL_EDGE && exp_rgb != LBL_UNDEF) stats.fp[EVAL_EDGE]++;
00345 if (exp_rgb != LBL_COR && exp_rgb != LBL_EDGE && exp_rgb != LBL_UNDEF) stats.fp[EVAL_EDGECORNER]++;
00346 break;
00347 case SVM_COR:
00348 pre_rgb = LBL_COR;
00349 if (exp_rgb != LBL_COR && exp_rgb != LBL_UNDEF) stats.fp[EVAL_COR]++;
00350 if (exp_rgb != LBL_COR && exp_rgb != LBL_EDGE && exp_rgb != LBL_UNDEF) stats.fp[EVAL_EDGECORNER]++;
00351 break;
00352 case SVM_SPH:
00353 pre_rgb = LBL_SPH;
00354 if (exp_rgb != LBL_SPH && exp_rgb != LBL_UNDEF) stats.fp[EVAL_SPH]++;
00355 if (exp_rgb != LBL_SPH && exp_rgb != LBL_CYL && exp_rgb != LBL_UNDEF) stats.fp[EVAL_CURVED]++;
00356 break;
00357 case SVM_CYL:
00358 pre_rgb = LBL_CYL;
00359 if (exp_rgb != LBL_CYL && exp_rgb != LBL_UNDEF) stats.fp[EVAL_CYL]++;
00360 if (exp_rgb != LBL_SPH && exp_rgb != LBL_CYL && exp_rgb != LBL_UNDEF) stats.fp[EVAL_CURVED]++;
00361 break;
00362 default:
00363 pre_rgb = LBL_UNDEF;
00364 break;
00365 }
00366
00367 switch(exp_rgb)
00368 {
00369 case LBL_PLANE:
00370 if (pre_rgb != exp_rgb) stats.fn[EVAL_PLANE]++;
00371 stats.exp[EVAL_PLANE]++;
00372 break;
00373 case LBL_EDGE:
00374 if (pre_rgb != exp_rgb)
00375 {
00376 stats.fn[EVAL_EDGE]++;
00377 if (pre_rgb != LBL_COR) stats.fn[EVAL_EDGECORNER]++;
00378 }
00379 stats.exp[EVAL_EDGE]++;
00380 stats.exp[EVAL_EDGECORNER]++;
00381 break;
00382 case LBL_COR:
00383 if (pre_rgb != exp_rgb)
00384 {
00385 stats.fn[EVAL_COR]++;
00386 if (pre_rgb != LBL_EDGE) stats.fn[EVAL_EDGECORNER]++;
00387 }
00388 stats.exp[EVAL_COR]++;
00389 stats.exp[EVAL_EDGECORNER]++;
00390 break;
00391 case LBL_SPH:
00392 if (pre_rgb != exp_rgb)
00393 {
00394 stats.fn[EVAL_SPH]++;
00395 if (pre_rgb != LBL_CYL) stats.fn[EVAL_CURVED]++;
00396 }
00397 stats.exp[EVAL_SPH]++;
00398 stats.exp[EVAL_CURVED]++;
00399 break;
00400 case LBL_CYL:
00401 if (pre_rgb != exp_rgb)
00402 {
00403 stats.fn[EVAL_CYL]++;
00404 if (pre_rgb != LBL_SPH) stats.fn[EVAL_CURVED]++;
00405 }
00406 stats.exp[EVAL_CYL]++;
00407 stats.exp[EVAL_CURVED]++;
00408 break;
00409 default:
00410 stats.undef++;
00411 break;
00412 }
00413 fpfh_out->points[idx].rgb = *reinterpret_cast<float*>(&pre_rgb);
00414 }
00415 cout << "FPFH:\n" << stats << endl << endl;
00416 }
00417
00418 void processPC(const PointCloud<PointXYZRGB>::Ptr in,
00419 PointCloud<PointXYZRGB>::Ptr ref_out,
00420 PointCloud<PointXYZRGB>::Ptr pc_out)
00421 {
00422 PointCloud<Normal>::Ptr n(new PointCloud<Normal>());
00423 PointCloud<PrincipalCurvatures>::Ptr pc(new PointCloud<PrincipalCurvatures>());
00424
00425
00426 cout << "PC: Pass (with " << in->points.size() << " points)" << endl;
00427 PassThrough<PointXYZRGB> pass;
00428 pass.setInputCloud(in);
00429 pass.setFilterFieldName("z");
00430 pass.setFilterLimits(0.0f, pass_depth_);
00431 pass.filter(*ref_out);
00432
00433
00434 if (pc_vox_enable_)
00435 {
00436 cout << "PC: Voxel (with " << ref_out->points.size() << " points)" << endl;
00437 VoxelGrid<PointXYZRGB> vox;
00438 vox.setInputCloud(ref_out);
00439 vox.setLeafSize(pc_vox_, pc_vox_, pc_vox_);
00440 vox.filter(*ref_out);
00441 }
00442
00443 #ifdef PCL_VERSION_COMPARE //fuerte
00444 pcl::search::KdTree<PointXYZRGB>::Ptr tree (new pcl::search::KdTree<PointXYZRGB>());
00445 #else //electric
00446 KdTreeFLANN<PointXYZRGB>::Ptr tree (new pcl::KdTreeFLANN<PointXYZRGB> ());
00447 #endif
00448 tree->setInputCloud(ref_out);
00449
00450
00451 if(pc_mls_enable_)
00452 {
00453 cout << "PC: MLS (with " << ref_out->points.size() << " points)" << endl;
00454
00455 #ifdef PCL_VERSION_COMPARE
00456 std::cerr << "MLS has changed completely in PCL 1.7! Requires redesign of entire program" << std::endl;
00457 exit(0);
00458 #else
00459 MovingLeastSquares<PointXYZRGB, Normal> mls;
00460 mls.setInputCloud(ref_out);
00461 mls.setOutputNormals(n);
00462 mls.setPolynomialFit(true);
00463 mls.setPolynomialOrder(2);
00464 mls.setSearchMethod(tree);
00465 mls.setSearchRadius(pc_rn_);
00466 mls.reconstruct(*ref_out);
00467 #endif
00468 cout << "PC: flip normals (with " << ref_out->points.size() << " points)" << endl;
00469 for (size_t i = 0; i < ref_out->points.size(); ++i)
00470 {
00471 flipNormalTowardsViewpoint(ref_out->points[i], 0.0f, 0.0f, 0.0f,
00472 n->points[i].normal[0],
00473 n->points[i].normal[1],
00474 n->points[i].normal[2]);
00475 }
00476 }
00477 else
00478 {
00479 cout << "PC: Normals (with " << ref_out->points.size() << " points)" << endl;
00480 NormalEstimation<PointXYZRGB, Normal> norm;
00481 norm.setInputCloud(ref_out);
00482 norm.setSearchMethod(tree);
00483 norm.setRadiusSearch(pc_rn_);
00484 norm.compute(*n);
00485 }
00486
00487
00488 #ifdef PCL_VERSION_COMPARE //fuerte
00489 tree.reset(new pcl::search::KdTree<PointXYZRGB>());
00490 #else //electric
00491 tree.reset(new KdTreeFLANN<PointXYZRGB> ());
00492 #endif
00493 tree->setInputCloud(ref_out);
00494 cout << "PC: estimation (with " << ref_out->points.size() << " points)" << endl;
00495 PrincipalCurvaturesEstimation<PointXYZRGB, Normal, PrincipalCurvatures> pcE;
00496 pcE.setInputCloud(ref_out);
00497 pcE.setInputNormals(n);
00498 pcE.setSearchMethod(tree);
00499 pcE.setRadiusSearch(pc_rf_);
00500 pcE.compute(*pc);
00501
00502 cout << "PC: classification " << endl;
00503 *pc_out = *ref_out;
00504
00505 int exp_rgb, pre_rgb;
00506 float c_max,c_min;
00507 cob_3d_mapping_common::LabelResults stats(fl2label(pc_rn_),fl2label(pc_rf_),pc_mls_enable_);
00508
00509
00510 for (size_t idx = 0; idx < ref_out->points.size(); idx++)
00511 {
00512 exp_rgb = *reinterpret_cast<int*>(&ref_out->points[idx].rgb);
00513 c_max = pc->points[idx].pc1;
00514 c_min = pc->points[idx].pc2;
00515
00516 if ( c_max < c_low )
00517 {
00518 pre_rgb = LBL_PLANE;
00519 if (exp_rgb != LBL_PLANE && exp_rgb != LBL_UNDEF) stats.fp[EVAL_PLANE]++;
00520 }
00521 else if (c_max > c_high)
00522 {
00523 if (c_max < c_r2 * c_min)
00524 {
00525 pre_rgb = LBL_COR;
00526 if (exp_rgb != LBL_COR && exp_rgb != LBL_UNDEF) stats.fp[EVAL_COR]++;
00527 }
00528 else
00529 {
00530 pre_rgb = LBL_EDGE;
00531 if (exp_rgb != LBL_EDGE && exp_rgb != LBL_UNDEF) stats.fp[EVAL_EDGE]++;
00532 }
00533
00534 if (exp_rgb != LBL_COR && exp_rgb != LBL_EDGE && exp_rgb != LBL_UNDEF)
00535 stats.fp[EVAL_EDGECORNER]++;
00536 }
00537 else
00538 {
00539 if (c_max < c_r1 * c_min)
00540 {
00541 pre_rgb = LBL_SPH;
00542 if (exp_rgb != LBL_SPH && exp_rgb != LBL_UNDEF) stats.fp[EVAL_SPH]++;
00543 }
00544 else
00545 {
00546 pre_rgb = LBL_CYL;
00547 if (exp_rgb != LBL_CYL && exp_rgb != LBL_UNDEF) stats.fp[EVAL_CYL]++;
00548 }
00549
00550 if (exp_rgb != LBL_SPH && exp_rgb != LBL_CYL && exp_rgb != LBL_UNDEF)
00551 stats.fp[EVAL_CURVED]++;
00552 }
00553
00554 switch(exp_rgb)
00555 {
00556 case LBL_PLANE:
00557 if (pre_rgb != exp_rgb) stats.fn[EVAL_PLANE]++;
00558 stats.exp[EVAL_PLANE]++;
00559 break;
00560 case LBL_EDGE:
00561 if (pre_rgb != exp_rgb)
00562 {
00563 stats.fn[EVAL_EDGE]++;
00564 if (pre_rgb != LBL_COR) stats.fn[EVAL_EDGECORNER]++;
00565 }
00566 stats.exp[EVAL_EDGE]++;
00567 stats.exp[EVAL_EDGECORNER]++;
00568 break;
00569 case LBL_COR:
00570 if (pre_rgb != exp_rgb)
00571 {
00572 stats.fn[EVAL_COR]++;
00573 if (pre_rgb != LBL_EDGE) stats.fn[EVAL_EDGECORNER]++;
00574 }
00575 stats.exp[EVAL_COR]++;
00576 stats.exp[EVAL_EDGECORNER]++;
00577 break;
00578 case LBL_SPH:
00579 if (pre_rgb != exp_rgb)
00580 {
00581 stats.fn[EVAL_SPH]++;
00582 if (pre_rgb != LBL_CYL) stats.fn[EVAL_CURVED]++;
00583 }
00584 stats.exp[EVAL_SPH]++;
00585 stats.exp[EVAL_CURVED]++;
00586 break;
00587 case LBL_CYL:
00588 if (pre_rgb != exp_rgb)
00589 {
00590 stats.fn[EVAL_CYL]++;
00591 if (pre_rgb != LBL_SPH) stats.fn[EVAL_CURVED]++;
00592 }
00593 stats.exp[EVAL_CYL]++;
00594 stats.exp[EVAL_CURVED]++;
00595 break;
00596 default:
00597 stats.undef++;
00598 break;
00599 }
00600 pc_out->points[idx].rgb = *reinterpret_cast<float*>(&pre_rgb);
00601 }
00602 cout << "PC:\n" << stats << endl << endl;
00603 }
00604
00605 void processRSD(const PointCloud<PointXYZRGB>::Ptr in,
00606 PointCloud<PointXYZRGB>::Ptr ref_out,
00607 PointCloud<PointXYZRGB>::Ptr rsd_out)
00608 {
00609 PointCloud<Normal>::Ptr n(new PointCloud<Normal>());
00610 PointCloud<PrincipalRadiiRSD>::Ptr rsd(new PointCloud<PrincipalRadiiRSD>());
00611
00612
00613 cout << "RSD: Pass (with " << in->points.size() << " points)" << endl;
00614 PassThrough<PointXYZRGB> pass;
00615 pass.setInputCloud(in);
00616 pass.setFilterFieldName("z");
00617 pass.setFilterLimits(0.0f, pass_depth_);
00618 pass.filter(*ref_out);
00619
00620
00621 if (rsd_vox_enable_)
00622 {
00623 cout << "RSD: Voxel (with " << ref_out->points.size() << " points)" << endl;
00624 VoxelGrid<PointXYZRGB> vox;
00625 vox.setInputCloud(ref_out);
00626 vox.setLeafSize(rsd_vox_, rsd_vox_, rsd_vox_);
00627 vox.filter(*ref_out);
00628 }
00629
00630 #ifdef PCL_VERSION_COMPARE //fuerte
00631 pcl::search::KdTree<PointXYZRGB>::Ptr tree (new pcl::search::KdTree<PointXYZRGB>());
00632 #else //electric
00633 KdTreeFLANN<PointXYZRGB>::Ptr tree (new pcl::KdTreeFLANN<PointXYZRGB> ());
00634 #endif
00635 tree->setInputCloud(ref_out);
00636
00637
00638 if(rsd_mls_enable_)
00639 {
00640 cout << "RSD: MLS (with " << ref_out->points.size() << " points)" << endl;
00641
00642 #ifdef PCL_VERSION_COMPARE
00643 std::cerr << "MLS has changed completely in PCL 1.7! Requires redesign of entire program" << std::endl;
00644 exit(0);
00645 #else
00646 MovingLeastSquares<PointXYZRGB, Normal> mls;
00647 mls.setInputCloud(ref_out);
00648 mls.setOutputNormals(n);
00649 mls.setPolynomialFit(true);
00650 mls.setPolynomialOrder(2);
00651 mls.setSearchMethod(tree);
00652 mls.setSearchRadius(rsd_rn_);
00653 mls.reconstruct(*ref_out);
00654 #endif
00655
00656 cout << "RSD: flip normals (with " << ref_out->points.size() << " points)" << endl;
00657 for (size_t i = 0; i < ref_out->points.size(); ++i)
00658 {
00659 flipNormalTowardsViewpoint(ref_out->points[i], 0.0f, 0.0f, 0.0f,
00660 n->points[i].normal[0],
00661 n->points[i].normal[1],
00662 n->points[i].normal[2]);
00663 }
00664 }
00665 else
00666 {
00667 cout << "RSD: Normals (with " << ref_out->points.size() << " points)" << endl;
00668 NormalEstimation<PointXYZRGB, Normal> norm;
00669 norm.setInputCloud(ref_out);
00670 norm.setSearchMethod(tree);
00671 norm.setRadiusSearch(rsd_rn_);
00672 norm.compute(*n);
00673 }
00674
00675 tree->setInputCloud(ref_out);
00676
00677
00678 cout << "RSD: estimation (with " << ref_out->points.size() << " points)" << endl;
00679 RSDEstimation<PointXYZRGB, Normal, PrincipalRadiiRSD> rsdE;
00680 rsdE.setInputCloud(ref_out);
00681 rsdE.setInputNormals(n);
00682 rsdE.setSearchMethod(tree);
00683 rsdE.setPlaneRadius(r_limit_);
00684 rsdE.setRadiusSearch(rsd_rf_);
00685 rsdE.compute(*rsd);
00686
00687 cout << "RSD: classification " << endl;
00688 *rsd_out = *ref_out;
00689
00690
00691 int exp_rgb, pre_rgb;
00692 float r_max,r_min;
00693 cob_3d_mapping_common::LabelResults stats(fl2label(rsd_rn_),fl2label(rsd_rf_),rsd_mls_enable_);
00694 for (size_t idx = 0; idx < ref_out->points.size(); idx++)
00695 {
00696 exp_rgb = *reinterpret_cast<int*>(&ref_out->points[idx].rgb);
00697 r_max = rsd->points[idx].r_max;
00698 r_min = rsd->points[idx].r_min;
00699
00700 if ( r_min > r_high )
00701 {
00702 pre_rgb = LBL_PLANE;
00703 if (exp_rgb != LBL_PLANE && exp_rgb != LBL_UNDEF) stats.fp[EVAL_PLANE]++;
00704 }
00705 else if (r_min < r_low)
00706 {
00707 if (r_max < r_r2 * r_min)
00708 {
00709 pre_rgb = LBL_COR;
00710 if (exp_rgb != LBL_COR && exp_rgb != LBL_UNDEF) stats.fp[EVAL_COR]++;
00711 }
00712 else
00713 {
00714 pre_rgb = LBL_EDGE;
00715 if (exp_rgb != LBL_EDGE && exp_rgb != LBL_UNDEF) stats.fp[EVAL_EDGE]++;
00716 }
00717
00718 if (exp_rgb != LBL_COR && exp_rgb != LBL_EDGE && exp_rgb != LBL_UNDEF)
00719 stats.fp[EVAL_EDGECORNER]++;
00720 }
00721 else
00722 {
00723 if (r_max < r_r1 * r_min)
00724 {
00725 pre_rgb = LBL_SPH;
00726 if (exp_rgb != LBL_SPH && exp_rgb != LBL_UNDEF) stats.fp[EVAL_SPH]++;
00727 }
00728 else
00729 {
00730 pre_rgb = LBL_CYL;
00731 if (exp_rgb != LBL_CYL && exp_rgb != LBL_UNDEF) stats.fp[EVAL_CYL]++;
00732 }
00733
00734 if (exp_rgb != LBL_SPH && exp_rgb != LBL_CYL && exp_rgb != LBL_UNDEF)
00735 stats.fp[EVAL_CURVED]++;
00736 }
00737
00738 switch(exp_rgb)
00739 {
00740 case LBL_PLANE:
00741 if (pre_rgb != exp_rgb) stats.fn[EVAL_PLANE]++;
00742 stats.exp[EVAL_PLANE]++;
00743 break;
00744 case LBL_EDGE:
00745 if (pre_rgb != exp_rgb)
00746 {
00747 stats.fn[EVAL_EDGE]++;
00748 if (pre_rgb != LBL_COR) stats.fn[EVAL_EDGECORNER]++;
00749 }
00750 stats.exp[EVAL_EDGE]++;
00751 stats.exp[EVAL_EDGECORNER]++;
00752 break;
00753 case LBL_COR:
00754 if (pre_rgb != exp_rgb)
00755 {
00756 stats.fn[EVAL_COR]++;
00757 if (pre_rgb != LBL_EDGE) stats.fn[EVAL_EDGECORNER]++;
00758 }
00759 stats.exp[EVAL_COR]++;
00760 stats.exp[EVAL_EDGECORNER]++;
00761 break;
00762 case LBL_SPH:
00763 if (pre_rgb != exp_rgb)
00764 {
00765 stats.fn[EVAL_SPH]++;
00766 if (pre_rgb != LBL_CYL) stats.fn[EVAL_CURVED]++;
00767 }
00768 stats.exp[EVAL_SPH]++;
00769 stats.exp[EVAL_CURVED]++;
00770 break;
00771 case LBL_CYL:
00772 if (pre_rgb != exp_rgb)
00773 {
00774 stats.fn[EVAL_CYL]++;
00775 if (pre_rgb != LBL_SPH) stats.fn[EVAL_CURVED]++;
00776 }
00777 stats.exp[EVAL_CYL]++;
00778 stats.exp[EVAL_CURVED]++;
00779 break;
00780 default:
00781 stats.undef++;
00782 break;
00783 }
00784 rsd_out->points[idx].rgb = *reinterpret_cast<float*>(&pre_rgb);
00785 }
00786 cout << "RSD:\n" << stats << endl << endl;
00787 }
00788
00789
00790 int main(int argc, char** argv)
00791 {
00792 readOptions(argc, argv);
00793
00794 PointCloud<PointXYZRGB>::Ptr p_raw(new PointCloud<PointXYZRGB>());
00795 PointCloud<PointXYZRGB>::Ptr p_rsd_out(new PointCloud<PointXYZRGB>());
00796 PointCloud<PointXYZRGB>::Ptr p_rsd_ref(new PointCloud<PointXYZRGB>());
00797 PointCloud<PointXYZRGB>::Ptr p_pc_out(new PointCloud<PointXYZRGB>());
00798 PointCloud<PointXYZRGB>::Ptr p_pc_ref(new PointCloud<PointXYZRGB>());
00799 PointCloud<PointXYZRGB>::Ptr p_fpfh_out(new PointCloud<PointXYZRGB>());
00800 PointCloud<PointXYZRGB>::Ptr p_fpfh_ref(new PointCloud<PointXYZRGB>());
00801
00802 PCDReader r;
00803 if(r.read(file_in_, *p_raw) == -1)
00804 cout << "Could not read file " << file_in_ << endl;
00805 cout << "Read pcd file \"" << file_in_ << "\" (Points: " << p_raw->points.size() << ", width: "
00806 << p_raw->width << ", height: " << p_raw->height << ")" << endl;
00807
00808 cout << "Headline: \n\n"<< cob_3d_mapping_common::writeHeader() << endl << endl;
00809
00810 if (rsd_enable_)
00811 processRSD(p_raw, p_rsd_ref, p_rsd_out);
00812 if (pc_enable_)
00813 processPC(p_raw, p_pc_ref, p_pc_out);
00814 if (fpfh_enable_)
00815 processFPFH(p_raw, p_fpfh_ref, p_fpfh_out);
00816
00817 if (quiet_) return (0);
00818
00819 boost::shared_ptr<visualization::PCLVisualizer> v;
00820 if (camera_pos_ != "")
00821 {
00822 int argc_dummy = 3;
00823 char *argv_dummy[] = {(char*)argv[0], "-cam", (char*)camera_pos_.c_str(), NULL};
00824 v.reset(new visualization::PCLVisualizer(argc_dummy, argv_dummy, file_in_));
00825 }
00826 else
00827 {
00828 v.reset(new visualization::PCLVisualizer(file_in_));
00829 }
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841 int v1(0);
00842 ColorHdlRGB col_hdl1(p_rsd_ref);
00843 v->createViewPort(0.0, 0.5, 0.5, 1.0, v1);
00844 v->setBackgroundColor(255,255,255, v1);
00845 v->addPointCloud<PointXYZRGB>(p_rsd_ref, col_hdl1, "raw", v1);
00846
00847
00848 int v2(0);
00849 ColorHdlRGB col_hdl2(p_fpfh_out);
00850 v->createViewPort(0.0, 0.0, 0.5, 0.5, v2);
00851 v->setBackgroundColor(255,255,255, v2);
00852 v->addPointCloud<PointXYZRGB>(p_fpfh_out, col_hdl2, "fpfh", v2);
00853
00854
00855 int v3(0);
00856 ColorHdlRGB col_hdl3(p_rsd_out);
00857 v->createViewPort(0.5, 0.5, 1.0, 1.0, v3);
00858 v->setBackgroundColor(255,255,255, v3);
00859 v->addPointCloud<PointXYZRGB>(p_rsd_out, col_hdl3, "rsd", v3);
00860
00861
00862 int v4(0);
00863 ColorHdlRGB col_hdl4(p_pc_out);
00864 v->createViewPort(0.5, 0.0, 1.0, 0.5, v4);
00865 v->setBackgroundColor(255,255,255, v4);
00866 v->addPointCloud<PointXYZRGB>(p_pc_out, col_hdl4, "pc", v4);
00867
00868
00869 while(!v->wasStopped())
00870 {
00871 v->spinOnce(100);
00872 usleep(100000);
00873 }
00874 return(0);
00875 }