test_segmentation.cpp
Go to the documentation of this file.
00001 
00059 /*
00060  * test_segmentation.cpp
00061  *
00062  *  Created on: 18.06.2012
00063  *      Author: josh
00064  */
00065 
00066 //#define USE_COLOR
00067 
00068 //includes needed for testing
00069 #include <ros/console.h>
00070 #include <ros/assert.h>
00071 #include <gtest/gtest.h>
00072 
00073 #include <pcl/io/pcd_io.h>
00074 #include <rosbag/bag.h>
00075 
00076 //includes needed for segmentation (things to test)
00077 #include <cob_3d_segmentation/general_segmentation.h>
00078 #include <cob_3d_segmentation/quad_regression/quad_regression.h>
00079 #include <cob_3d_segmentation/ransac/ransac.h>
00080 #include <cob_3d_segmentation/marching_cubes/marching_cubes.h>
00081 #if PCL_MINOR_VERSION >= 6
00082 #include <cob_3d_segmentation/multi_plane/multi_plane.h>
00083 #endif
00084 
00085 
00086 
00090 class Testing_PCDLoader
00091 {
00092   std::vector<std::string> pc2s_fn_;
00093 
00094   static bool _load(const std::string &fn, sensor_msgs::PointCloud2 &pc2) {
00095     pc2.header.frame_id = fn; 
00096 
00097     if(!pcl::io::loadPCDFile(fn,pc2))
00098       return true;
00099     else
00100       ROS_ERROR("failed to load pcd file %s",fn.c_str());
00101 
00102     return false;
00103   }
00104 
00105   Testing_PCDLoader()
00106   {
00107     load("test/kitchen01_far_raw.pcd");
00108     load("test/office01_close_raw.pcd");
00109     load("test/office01_far_raw.pcd");
00110     load("test/shelves01_close_raw.pcd");
00111     load("test/shelves01_far_raw.pcd");
00112     load("test/table01_close1m_raw.pcd");
00113     load("test/table01_far_raw.pcd");
00114   }
00115 
00116 public:
00117 
00119   static Testing_PCDLoader &get() {
00120     static Testing_PCDLoader t;
00121     return t;
00122   }
00123 
00124   void load(const std::string &fn) {
00125     pc2s_fn_.push_back(fn);
00126   }
00127 
00128   template <typename Point>
00129   bool getPC(const size_t ind, typename pcl::PointCloud<Point>::Ptr pc, std::string &fn) const
00130   {
00131     pc->clear();
00132     if(ind<pc2s_fn_.size())
00133     {
00134       sensor_msgs::PointCloud2 pc2;
00135       if(_load(pc2s_fn_[ind],pc2))
00136       {
00137       pcl::fromROSMsg(pc2,*pc);
00138       fn = pc2.header.frame_id;
00139       }
00140       return true;
00141     }
00142     return false;
00143   }
00144 
00145   template <typename Point>
00146   void writePC(const std::string &pc_fn, typename pcl::PointCloud<Point>::ConstPtr pc) const
00147   {
00148     const ::testing::TestInfo* const test_info =
00149       ::testing::UnitTest::GetInstance()->current_test_info();
00150 
00151     if(pc->size()<1) {
00152         ROS_ERROR("cannot save empty pc (%s_%s_%s)", test_info->test_case_name(), test_info->name(), pc_fn.c_str());
00153         return;
00154     }
00155 
00156     char fn[512];
00157     sprintf(fn,"test/labeled/pc_%s_%s_%s.pcd",test_info->test_case_name(), test_info->name(), pc_fn.c_str());
00158     pcl::io::savePCDFile(fn,*pc);
00159   }
00160 };
00161 
00166 class PrecisionStopWatch {
00167   struct timeval precisionClock;
00168 
00169 public:
00170   PrecisionStopWatch() {
00171     gettimeofday(&precisionClock, NULL);
00172   };
00173 
00174   void precisionStart() {
00175     gettimeofday(&precisionClock, NULL);
00176   };
00177 
00178   double precisionStop() {
00179     struct timeval precisionClockEnd;
00180     gettimeofday(&precisionClockEnd, NULL);
00181     double d= ((double)precisionClockEnd.tv_sec + 1.0e-6 * (double)precisionClockEnd.tv_usec) - ((double)precisionClock.tv_sec + 1.0e-6 * (double)precisionClock.tv_usec);
00182     precisionStart();
00183     return d;
00184   };
00185 };
00186 
00190 class Testing_CSV
00191 {
00192   FILE *fp;
00193   int row, col;
00194 public:
00195   Testing_CSV(std::string fn):row(0),col(0)
00196   {
00197     const ::testing::TestInfo* const test_info =
00198       ::testing::UnitTest::GetInstance()->current_test_info();
00199     fn = "test/results/csv_"+std::string(test_info->test_case_name())+"_"+std::string(test_info->name())+"_"+fn+".csv";
00200     fp = fopen(fn.c_str(),"w");
00201   }
00202 
00203   ~Testing_CSV()
00204   {
00205     if(fp) fclose(fp);
00206   }
00207 
00208   void add(const std::string &str)
00209   {
00210     if(col>0) fputc('\t',fp);
00211     fwrite(str.c_str(),str.size(),1,fp);
00212     ++col;
00213   }
00214 
00215   template<typename T>
00216   void add(const T v)
00217   {
00218     std::stringstream ss(std::stringstream::out);
00219     ss<<v;
00220     add(ss.str());
00221   }
00222 
00223   void next()
00224   {
00225     if(col>0)
00226     {
00227       fputc('\n',fp);
00228       col=0;
00229       ++row;
00230     }
00231     fflush(fp);
00232   }
00233 
00234   static Testing_CSV create_table(const std::string &fn, std::string cols)
00235   {
00236     Testing_CSV csv(fn);
00237     size_t pos;
00238     while(cols.size()>0)
00239     {
00240       pos=cols.find(",");
00241       if(pos!=std::string::npos)
00242       {
00243         csv.add(std::string(cols.begin(),cols.begin()+pos));
00244         cols.erase(cols.begin(), cols.begin()+(pos+1));
00245       }
00246       else
00247       {
00248         csv.add(cols);
00249         break;
00250       }
00251     }
00252     csv.next();
00253     return csv;
00254   }
00255 };
00256 
00257 
00258 
00259 
00260 /*******************************TESTING STARTS HERE********************************/
00261 
00262 template <typename Point, typename PointLabel>
00263 void segment_pointcloud(GeneralSegmentation<Point, PointLabel> *seg, typename pcl::PointCloud<Point>::Ptr &pc, const std::string &fn)
00264 {
00265   EXPECT_TRUE(seg!=NULL);
00266   EXPECT_TRUE(pc->size()>0);
00267 
00268   //for documentation
00269   static Testing_CSV csv = Testing_CSV::create_table("execution_time","filename,execution time in seconds");
00270   double took=0.;
00271 
00272   seg->setInputCloud(pc);
00273 
00274   PrecisionStopWatch psw;
00275   EXPECT_TRUE(
00276       seg->compute()
00277       );
00278   ROS_INFO("segmentation took %f", took=psw.precisionStop());
00279   csv.add(fn);
00280   csv.add(took);
00281   csv.next();
00282 
00283   Testing_PCDLoader::get().writePC<PointLabel>(fn, seg->getOutputCloud());
00284 }
00285 
00286 template <int Degree>
00287 void test_QPPF()
00288 {
00289   typedef pcl::PointXYZ Point;
00290   typedef PointXYZRGBLabel PointL;
00291 
00292   pcl::PointCloud<Point>::Ptr pc(new pcl::PointCloud<Point>);
00293   static Segmentation::Segmentation_QuadRegression<Point, PointL, Segmentation::QPPF::QuadRegression<Degree, Point, Segmentation::QPPF::CameraModel_Kinect<Point> > > seg;
00294 
00295   static Testing_CSV csv = Testing_CSV::create_table("accuracy","filename,mean,variance,weighted mean,weighted variance,average distance,used points, memory for representation,points,true positive rate, false positive rate,execution time: quadtree,execution time: growing,execution time: extraction,number of segments");
00296 
00297   ROS_INFO("starting segmentation");
00298   size_t ind=0;
00299   std::string fn;
00300   while(Testing_PCDLoader::get().getPC<Point>(ind++, pc, fn))
00301   {
00302     if(pc->size()<1) continue;
00303 
00304     pcl::PointCloud<PointL>::Ptr labeled_pc(new pcl::PointCloud<PointL>);
00305     bool loaded = false;
00306     try {
00307       loaded = Testing_PCDLoader::get().getPC<PointL>(ind-1, labeled_pc, fn);
00308     } catch(...) {
00309     }
00310     if(!loaded) {
00311         ROS_INFO("will not evaluate segmentation");
00312         labeled_pc.reset();}
00313 
00314     ROS_INFO("processing pc %d ...",(int)ind-1);
00315     std::string fn_short(fn.begin()+(fn.find_last_of("/")+1),fn.end());
00316 
00317     //for(size_t i=0; i<pc->size(); i++) if(pcl_isfinite((*pc)[i].z)) (*pc)[i].z = (*pc)[i].x*(*pc)[i].y;
00318 
00319     segment_pointcloud<Point,PointL>(&seg,pc, fn_short);
00320 
00321     seg.extractImages();
00322 
00323     Testing_PCDLoader::get().writePC<PointL>("reconstructed_"+fn_short, seg.getReconstructedOutputCloud());
00324 
00325     float mean, var, mean_weighted, var_weighted, dist;
00326     double et_quadtree, et_growing, et_extraction;
00327     double true_positive, false_positive;
00328     size_t used, mem, points;
00329     seg.compute_accuracy(mean, var, mean_weighted, var_weighted, used, mem, points, dist, labeled_pc, true_positive, false_positive);
00330 #ifdef STOP_TIME
00331     seg.getExecutionTimes(et_quadtree, et_growing, et_extraction);
00332 #endif
00333 
00334     csv.add(fn_short);
00335     csv.add(mean);
00336     csv.add(var_weighted);
00337     csv.add(mean_weighted);
00338     csv.add(var);
00339     csv.add(dist);
00340     csv.add(used);
00341     csv.add(mem);
00342     csv.add(points);
00343     csv.add(true_positive);
00344     csv.add(false_positive);
00345 #ifdef STOP_TIME
00346     csv.add(et_quadtree);
00347     csv.add(et_growing);
00348     csv.add(et_extraction);
00349 #endif
00350     csv.add(seg.getPolygons().size());
00351     csv.next();
00352 
00353     //saving ros msgs to bag-file
00354     rosbag::Bag bag_out;
00355     bag_out.open("test/labeled/"+fn_short+".bag", rosbag::bagmode::Write);
00356     bag_out.write("shapes_array", ros::Time(1342850029.582334425+0.1), (cob_3d_mapping_msgs::ShapeArray)seg);
00357     bag_out.write("shapes_array", ros::Time(1342850029.582334425+0.2), (cob_3d_mapping_msgs::ShapeArray)seg);
00358     bag_out.write("shapes_array", ros::Time(1342850029.582334425+0.4), (cob_3d_mapping_msgs::ShapeArray)seg);
00359   }
00360 }
00361 
00362 TEST(Segmentation, quad_regression1)
00363 { test_QPPF<1>(); }
00364 TEST(Segmentation, quad_regression2)
00365 { test_QPPF<2>(); }
00366 TEST(Segmentation, quad_regression3)
00367 { test_QPPF<3>(); }
00368 TEST(Segmentation, quad_regression4)
00369 { test_QPPF<4>(); }
00370 //TEST(Segmentation, quad_regression6)
00371 //{ test_QPPF<6>(); }
00372 
00373 //degree 10 didn't work on my nb
00374 
00375 TEST(Segmentation, ransac)
00376 {
00377   return;
00378   typedef pcl::PointXYZRGB Point;
00379   typedef PointXYZRGBLabel PointL;
00380 
00381   pcl::PointCloud<Point>::Ptr pc(new pcl::PointCloud<Point>);
00382   Segmentation::Segmentation_RANSAC<Point,PointL> seg;
00383 
00384   static Testing_CSV csv = Testing_CSV::create_table("accuracy","filename,mean,variance,average distance,used points, memory for representation,points,true positive rate, false positive rate");
00385 
00386   ROS_INFO("starting segmentation");
00387   size_t ind=0;
00388   std::string fn;
00389   while(Testing_PCDLoader::get().getPC<Point>(ind++, pc, fn))
00390   {
00391     if(pc->size()<1) continue;
00392     ROS_INFO("processing pc %d ...",(int)ind-1);
00393     std::string fn_short(fn.begin()+(fn.find_last_of("/")+1),fn.end());
00394     segment_pointcloud<Point,PointL>(&seg,pc, fn_short);
00395 
00396     pcl::PointCloud<PointL>::Ptr labeled_pc(new pcl::PointCloud<PointL>);
00397     try {
00398       Testing_PCDLoader::get().getPC<PointL>(ind-1, labeled_pc, fn);
00399     } catch(...) {}
00400 
00401     Testing_PCDLoader::get().writePC<PointL>("reconstructed_"+fn_short, seg.getReconstructedOutputCloud());
00402 
00403     float mean, var, mean_weighted, var_weighted, dist;
00404     double true_positive, false_positive;
00405     size_t used, mem, points;
00406     seg.compute_accuracy(mean, var, mean_weighted, var_weighted, used, mem, points, dist, labeled_pc, true_positive, false_positive);
00407 
00408     csv.add(fn_short);
00409     csv.add(mean);
00410     csv.add(var);
00411     csv.add(dist);
00412     csv.add(used);
00413     csv.add(mem);
00414     csv.add(points);
00415     csv.add(true_positive);
00416     csv.add(false_positive);
00417     csv.next();
00418   }
00419 }
00420 
00421 #if PCL_MINOR_VERSION >= 6
00422 TEST(Segmentation, multi_plane)
00423 {
00424   typedef pcl::PointXYZRGB Point;
00425   typedef pcl::PointXYZRGBNormal PointN;
00426   typedef PointXYZRGBLabel PointL;
00427 
00428   pcl::PointCloud<Point>::Ptr pc(new pcl::PointCloud<Point>);
00429   Segmentation::Segmentation_MultiPlane<Point,PointN,PointL> seg;
00430 
00431   static Testing_CSV csv = Testing_CSV::create_table("accuracy","filename,mean,variance,average distance,used points, memory for representation,points,true positive rate, false positive rate");
00432 
00433   ROS_INFO("starting segmentation");
00434   size_t ind=0;
00435   std::string fn;
00436   while(Testing_PCDLoader::get().getPC<Point>(ind++, pc, fn))
00437   {
00438     if(pc->size()<1) continue;
00439     ROS_INFO("processing pc %d ...",(int)ind-1);
00440     std::string fn_short(fn.begin()+(fn.find_last_of("/")+1),fn.end());
00441     segment_pointcloud<Point,PointL>(&seg,pc, fn_short);
00442 
00443     pcl::PointCloud<PointL>::Ptr labeled_pc(new pcl::PointCloud<PointL>);
00444     try {
00445       Testing_PCDLoader::get().getPC<PointL>(ind-1, labeled_pc, fn);
00446     } catch(...) {}
00447 
00448     Testing_PCDLoader::get().writePC<PointL>("reconstructed_"+fn_short, seg.getReconstructedOutputCloud());
00449 
00450     float mean, var, mean_weighted, var_weighted, dist;
00451     double true_positive, false_positive;
00452     size_t used, mem, points;
00453     seg.compute_accuracy(mean, var, mean_weighted, var_weighted, used, mem, points, dist, labeled_pc, true_positive, false_positive);
00454 
00455     csv.add(fn_short);
00456     csv.add(mean);
00457     csv.add(var);
00458     csv.add(dist);
00459     csv.add(used);
00460     csv.add(mem);
00461     csv.add(points);
00462     csv.add(true_positive);
00463     csv.add(false_positive);
00464     csv.next();
00465   }
00466 }
00467 #endif
00468 
00469 TEST(Segmentation, marching_cubes)
00470 {
00471   typedef pcl::PointXYZRGB Point;
00472   typedef pcl::PointXYZRGBNormal PointN;
00473   typedef pcl::PointXYZRGB PointL;
00474 
00475   pcl::PointCloud<Point>::Ptr pc(new pcl::PointCloud<Point>);
00476   Segmentation::Segmentation_MarchingCubes<Point,PointN,PointL> seg;
00477 
00478   static Testing_CSV csv = Testing_CSV::create_table("accuracy","filename,mean,variance,average distance,used points, memory for representation,points");
00479 
00480   ROS_INFO("starting segmentation");
00481   size_t ind=0;
00482   std::string fn;
00483   while(Testing_PCDLoader::get().getPC<Point>(ind++, pc, fn))
00484   {
00485     if(pc->size()<1) continue;
00486     ROS_INFO("processing pc %d ...",(int)ind-1);
00487     std::string fn_short(fn.begin()+(fn.find_last_of("/")+1),fn.end());
00488     segment_pointcloud<Point,PointL>(&seg,pc, fn_short);
00489 
00490     Testing_PCDLoader::get().writePC<PointL>("reconstructed_"+fn_short, seg.getReconstructedOutputCloud());
00491 
00492     float mean, var, dist;
00493     size_t used, mem, points;
00494     seg.compute_accuracy(mean, var, used, mem, points, dist);
00495 
00496     csv.add(fn_short);
00497     csv.add(mean);
00498     csv.add(var);
00499     csv.add(dist);
00500     csv.add(used);
00501     csv.add(mem);
00502     csv.add(points);
00503     csv.next();
00504   }
00505 }
00506 
00507 
00508 int main(int argc, char **argv){
00509   ros::Time::init();
00510 
00511   if(argc>1 && strcmp(argv[1],"--help")==0)
00512   {
00513     printf("usage:\n\t- without any options tests segmentation\n\t- with additional pcd files\n");
00514     return 0;
00515   }
00516 
00517   for(int i=1; i<argc; i++)
00518     Testing_PCDLoader::get().load(argv[i]);
00519 
00520   testing::InitGoogleTest(&argc, argv);
00521   return RUN_ALL_TESTS();
00522 }


cob_3d_segmentation
Author(s): Georg Arbeiter
autogenerated on Wed Aug 26 2015 11:03:03