organized_segmentation_demo.cpp
Go to the documentation of this file.
00001 #include <pcl/common/angles.h>
00002 #include <pcl/apps/organized_segmentation_demo.h>
00003 //QT4
00004 #include <QApplication>
00005 #include <QMutexLocker>
00006 #include <QEvent>
00007 #include <QObject>
00008 #include <boost/make_shared.hpp>
00009 #include <boost/filesystem.hpp>
00010 
00011 #include <pcl/segmentation/extract_polygonal_prism_data.h>
00012 #include <pcl/surface/convex_hull.h>
00013 
00014 void
00015 displayPlanarRegions (std::vector<pcl::PlanarRegion<PointT>, Eigen::aligned_allocator<pcl::PlanarRegion<PointT> > > &regions, 
00016                       boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer)
00017 {
00018   char name[1024];
00019   unsigned char red [6] = {255,   0,   0, 255, 255,   0};
00020   unsigned char grn [6] = {  0, 255,   0, 255,   0, 255};
00021   unsigned char blu [6] = {  0,   0, 255,   0, 255, 255};
00022 
00023   pcl::PointCloud<PointT>::Ptr contour (new pcl::PointCloud<PointT>);
00024 
00025   for (size_t i = 0; i < regions.size (); i++)
00026   {
00027     Eigen::Vector3f centroid = regions[i].getCentroid ();
00028     Eigen::Vector4f model = regions[i].getCoefficients ();
00029     pcl::PointXYZ pt1 = pcl::PointXYZ (centroid[0], centroid[1], centroid[2]);
00030     pcl::PointXYZ pt2 = pcl::PointXYZ (centroid[0] + (0.5f * model[0]),
00031                                        centroid[1] + (0.5f * model[1]),
00032                                        centroid[2] + (0.5f * model[2]));
00033     sprintf (name, "normal_%d", unsigned (i));
00034     viewer->addArrow (pt2, pt1, 1.0, 0, 0, false, name);
00035     
00036     contour->points = regions[i].getContour ();
00037     sprintf (name, "plane_%02d", (int)i);
00038     pcl::visualization::PointCloudColorHandlerCustom <PointT> color (contour, red[i%6], grn[i%6], blu[i%6]);
00039     if(!viewer->updatePointCloud(contour, color, name))
00040       viewer->addPointCloud (contour, color, name);
00041     viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 5, name);
00042   }
00043 }
00044 
00045 void
00046 displayEuclideanClusters (const pcl::PointCloud<PointT>::CloudVectorType &clusters, 
00047                           boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer)
00048 {
00049   char name[1024];
00050   unsigned char red [6] = {255,   0,   0, 255, 255,   0};
00051   unsigned char grn [6] = {  0, 255,   0, 255,   0, 255};
00052   unsigned char blu [6] = {  0,   0, 255,   0, 255, 255};
00053 
00054   for (size_t i = 0; i < clusters.size (); i++)
00055   {
00056     sprintf (name, "cluster_%d",i);
00057     pcl::visualization::PointCloudColorHandlerCustom<PointT> color0(boost::make_shared<pcl::PointCloud<PointT> >(clusters[i]),red[i%6],grn[i%6],blu[i%6]);
00058     if (!viewer->updatePointCloud (boost::make_shared<pcl::PointCloud<PointT> >(clusters[i]),color0,name))
00059       viewer->addPointCloud (boost::make_shared<pcl::PointCloud<PointT> >(clusters[i]),color0,name);
00060     viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 5, name);
00061     viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, 0.3, name);
00062   }
00063 }
00064 
00065 void
00066 displayCurvature (pcl::PointCloud<PointT>& cloud, pcl::PointCloud<pcl::Normal>& normals, boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer)
00067 {
00068   pcl::PointCloud<pcl::PointXYZRGBA> curvature_cloud = cloud;
00069   for (size_t i  = 0; i < cloud.points.size (); i++)
00070   {
00071     if (normals.points[i].curvature < 0.04)
00072     {
00073       curvature_cloud.points[i].r = 0;
00074       curvature_cloud.points[i].g = 255;
00075       curvature_cloud.points[i].b = 0;
00076     }
00077     else
00078     {
00079       curvature_cloud.points[i].r = 255;
00080       curvature_cloud.points[i].g = 0;
00081       curvature_cloud.points[i].b = 0;
00082     }
00083   }
00084   
00085   if (!viewer->updatePointCloud (boost::make_shared<pcl::PointCloud<pcl::PointXYZRGBA> >(curvature_cloud), "curvature"))
00086     viewer->addPointCloud (boost::make_shared<pcl::PointCloud<pcl::PointXYZRGBA> >(curvature_cloud), "curvature");
00087   
00088 }
00089 
00090 void
00091 displayDistanceMap (pcl::PointCloud<PointT>& cloud, float* distance_map, boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer)
00092 {
00093   pcl::PointCloud<pcl::PointXYZRGBA> distance_map_cloud = cloud;
00094   for (size_t i  = 0; i < cloud.points.size (); i++)
00095   {
00096     if (distance_map[i] < 5.0)
00097     {
00098       distance_map_cloud.points[i].r = 255;
00099       distance_map_cloud.points[i].g = 0;
00100       distance_map_cloud.points[i].b = 0;
00101     }
00102     else
00103     {
00104       distance_map_cloud.points[i].r = 0;
00105       distance_map_cloud.points[i].g = 255;
00106       distance_map_cloud.points[i].b = 0;
00107     }
00108   }
00109   
00110   if (!viewer->updatePointCloud (boost::make_shared<pcl::PointCloud<pcl::PointXYZRGBA> >(distance_map_cloud), "distance_map"))
00111     viewer->addPointCloud (boost::make_shared<pcl::PointCloud<pcl::PointXYZRGBA> >(distance_map_cloud), "distance_map");
00112 }
00113 
00114 void
00115 removePreviousDataFromScreen (size_t prev_models_size, size_t prev_clusters_size, boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer)
00116 {
00117   char name[1024];
00118   for (size_t i = 0; i < prev_models_size; i++)
00119   {
00120     sprintf (name, "normal_%d", unsigned (i));
00121     viewer->removeShape (name);
00122     
00123     sprintf (name, "plane_%02d", int (i));
00124     viewer->removePointCloud (name);
00125   }
00126   
00127   for (size_t i = 0; i < prev_clusters_size; i++)
00128   {
00129     sprintf (name, "cluster_%d", int (i));
00130     viewer->removePointCloud (name);
00131   }
00132 }
00133 
00134 bool
00135 compareClusterToRegion (pcl::PlanarRegion<PointT>& region, pcl::PointCloud<PointT>& cluster)
00136 {
00137   Eigen::Vector4f model = region.getCoefficients ();
00138   pcl::PointCloud<PointT> poly;
00139   poly.points = region.getContour ();
00140   
00141   bool cluster_ok = false;
00142   for (size_t i = 0; i < cluster.points.size (); i++)
00143   {
00144     double ptp_dist = fabs (model[0] * cluster.points[i].x +
00145                             model[1] * cluster.points[i].y +
00146                             model[2] * cluster.points[i].z +
00147                             model[3]);
00148     bool in_poly = pcl::isPointIn2DPolygon<PointT> (cluster.points[i], poly);
00149     if (in_poly && ptp_dist < 0.02)
00150       return true;
00151   }
00152   return false;
00153 }
00154 
00155 bool
00156 comparePointToRegion (PointT& pt, pcl::ModelCoefficients& model, pcl::PointCloud<PointT>& poly)
00157 {
00158   bool dist_ok = false;
00159   bool inside = false;
00160   
00161   double ptp_dist = fabs (model.values[0] * pt.x +
00162                           model.values[1] * pt.y +
00163                           model.values[2] * pt.z +
00164                           model.values[3]);
00165   if (ptp_dist < 0.1)
00166   {
00167     dist_ok = true;
00168   }
00169   else
00170     return false;
00171 
00172   //project the point onto the plane
00173   Eigen::Vector3f mc (model.values[0], model.values[1], model.values[2]);
00174   Eigen::Vector3f pt_vec;
00175   pt_vec[0] = pt.x;
00176   pt_vec[1] = pt.y;
00177   pt_vec[2] = pt.z;
00178   Eigen::Vector3f projected (pt_vec - mc * ptp_dist);
00179   PointT projected_pt;
00180   projected_pt.x = projected[0];
00181   projected_pt.y = projected[1];
00182   projected_pt.z = projected[2];  
00183 
00184   PCL_INFO ("pt: %lf %lf %lf\n", projected_pt.x, projected_pt.y, projected_pt.z);
00185 
00186   if (pcl::isPointIn2DPolygon (projected_pt, poly))
00187   {
00188     PCL_INFO ("inside!\n");
00189     return true;
00190   }
00191   else
00192   {
00193     PCL_INFO ("not inside!\n");
00194     return false;
00195   }
00196   
00197 }
00198 
00200 OrganizedSegmentationDemo::OrganizedSegmentationDemo (pcl::Grabber& grabber) : grabber_ (grabber)
00201 {
00202   //Create a timer
00203   vis_timer_ = new QTimer (this);
00204   vis_timer_->start (5);//5ms
00205 
00206   connect (vis_timer_, SIGNAL (timeout ()), this, SLOT (timeoutSlot()));
00207 
00208   ui_ = new Ui::MainWindow;
00209   ui_->setupUi (this);
00210   
00211   this->setWindowTitle ("PCL Organized Connected Component Segmentation Demo");
00212   vis_.reset (new pcl::visualization::PCLVisualizer ("", false));
00213   ui_->qvtk_widget->SetRenderWindow (vis_->getRenderWindow ());
00214   vis_->setupInteractor (ui_->qvtk_widget->GetInteractor (), ui_->qvtk_widget->GetRenderWindow ());
00215   vis_->getInteractorStyle ()->setKeyboardModifier (pcl::visualization::INTERACTOR_KB_MOD_SHIFT);
00216   ui_->qvtk_widget->update ();
00217 
00218   boost::function<void (const CloudConstPtr&)> f = boost::bind (&OrganizedSegmentationDemo::cloud_cb, this, _1);
00219   boost::signals2::connection c = grabber_.registerCallback(f);
00220   
00221   connect (ui_->captureButton, SIGNAL(clicked()), this, SLOT(toggleCapturePressed()));
00222 
00223   connect (ui_->euclideanComparatorButton, SIGNAL (clicked ()), this, SLOT (useEuclideanComparatorPressed ()));
00224   connect (ui_->planeComparatorButton, SIGNAL (clicked ()), this, SLOT (usePlaneComparatorPressed ()));
00225   connect (ui_->rgbComparatorButton, SIGNAL (clicked ()), this, SLOT (useRGBComparatorPressed ()));
00226   connect (ui_->edgeAwareComparatorButton, SIGNAL (clicked ()), this, SLOT (useEdgeAwareComparatorPressed ()));
00227 
00228   connect (ui_->displayCurvatureButton, SIGNAL (clicked ()), this, SLOT (displayCurvaturePressed ()));
00229   connect (ui_->displayDistanceMapButton, SIGNAL (clicked ()), this, SLOT (displayDistanceMapPressed ()));
00230   connect (ui_->displayNormalsButton, SIGNAL (clicked ()), this, SLOT (displayNormalsPressed ()));
00231 
00232   connect (ui_->disableRefinementButton, SIGNAL (clicked ()), this, SLOT (disableRefinementPressed ()));
00233   connect (ui_->planarRefinementButton, SIGNAL (clicked ()), this, SLOT (usePlanarRefinementPressed ()));
00234 
00235   connect (ui_->disableClusteringButton, SIGNAL (clicked ()), this, SLOT (disableClusteringPressed ()));
00236   connect (ui_->euclideanClusteringButton, SIGNAL (clicked ()), this, SLOT (useEuclideanClusteringPressed ()));
00237 
00238   capture_ = false;
00239   previous_data_size_ = 0;
00240   previous_clusters_size_ = 0;
00241   data_modified_ = true;
00242 
00243   display_normals_ = false;
00244   display_curvature_ = false;
00245   display_distance_map_ = false;
00246 
00247   use_planar_refinement_ = true;
00248   use_clustering_ = false;
00249   
00250 
00251   // Set up Normal Estimation
00252   //ne.setNormalEstimationMethod (ne.SIMPLE_3D_GRADIENT);
00253   ne.setNormalEstimationMethod (ne.COVARIANCE_MATRIX);
00254   ne.setMaxDepthChangeFactor (0.02f);
00255   ne.setNormalSmoothingSize (20.0f);
00256 
00257   plane_comparator_.reset (new pcl::PlaneCoefficientComparator<PointT, pcl::Normal> ());
00258   euclidean_comparator_.reset (new pcl::EuclideanPlaneCoefficientComparator<PointT, pcl::Normal> ());
00259   rgb_comparator_.reset (new pcl::RGBPlaneCoefficientComparator<PointT, pcl::Normal> ());
00260   edge_aware_comparator_.reset (new pcl::EdgeAwarePlaneComparator<PointT, pcl::Normal> ());
00261   euclidean_cluster_comparator_ = pcl::EuclideanClusterComparator<PointT, pcl::Normal, pcl::Label>::Ptr (new pcl::EuclideanClusterComparator<PointT, pcl::Normal, pcl::Label> ());
00262 
00263   // Set up Organized Multi Plane Segmentation
00264   mps.setMinInliers (10000);
00265   mps.setAngularThreshold (pcl::deg2rad (3.0)); //3 degrees
00266   mps.setDistanceThreshold (0.02); //2cm
00267   
00268 
00269   PCL_INFO ("starting grabber\n");
00270   grabber_.start ();
00271 }
00272 
00273 void 
00274 OrganizedSegmentationDemo::cloud_cb (const CloudConstPtr& cloud)
00275 {  
00276   if (!capture_)
00277     return;
00278   QMutexLocker locker (&mtx_);
00279   FPS_CALC ("computation");
00280 
00281   // Estimate Normals
00282   pcl::PointCloud<pcl::Normal>::Ptr normal_cloud (new pcl::PointCloud<pcl::Normal>);
00283   ne.setInputCloud (cloud);
00284   ne.compute (*normal_cloud);
00285   float* distance_map = ne.getDistanceMap ();
00286   boost::shared_ptr<pcl::EdgeAwarePlaneComparator<PointT,pcl::Normal> > eapc = boost::dynamic_pointer_cast<pcl::EdgeAwarePlaneComparator<PointT,pcl::Normal> >(edge_aware_comparator_);
00287   eapc->setDistanceMap (distance_map);
00288   eapc->setDistanceThreshold (0.01f, false);
00289 
00290   // Segment Planes
00291   double mps_start = pcl::getTime ();
00292   std::vector<pcl::PlanarRegion<PointT>, Eigen::aligned_allocator<pcl::PlanarRegion<PointT> > > regions;
00293   std::vector<pcl::ModelCoefficients> model_coefficients;
00294   std::vector<pcl::PointIndices> inlier_indices;  
00295   pcl::PointCloud<pcl::Label>::Ptr labels (new pcl::PointCloud<pcl::Label>);
00296   std::vector<pcl::PointIndices> label_indices;
00297   std::vector<pcl::PointIndices> boundary_indices;
00298   mps.setInputNormals (normal_cloud);
00299   mps.setInputCloud (cloud);
00300   if (use_planar_refinement_)
00301   {
00302     mps.segmentAndRefine (regions, model_coefficients, inlier_indices, labels, label_indices, boundary_indices);
00303   }
00304   else
00305   {
00306     mps.segment (regions);//, model_coefficients, inlier_indices, labels, label_indices, boundary_indices);
00307   }
00308   double mps_end = pcl::getTime ();
00309   std::cout << "MPS+Refine took: " << double(mps_end - mps_start) << std::endl;
00310 
00311   //Segment Objects
00312   pcl::PointCloud<PointT>::CloudVectorType clusters;
00313 
00314   if (use_clustering_ && regions.size () > 0)
00315   {
00316     std::vector<bool> plane_labels;
00317     plane_labels.resize (label_indices.size (), false);
00318     for (size_t i = 0; i < label_indices.size (); i++)
00319     {
00320       if (label_indices[i].indices.size () > 10000)
00321       {
00322         plane_labels[i] = true;
00323       }
00324     }  
00325     
00326     euclidean_cluster_comparator_->setInputCloud (cloud);
00327     euclidean_cluster_comparator_->setLabels (labels);
00328     euclidean_cluster_comparator_->setExcludeLabels (plane_labels);
00329     euclidean_cluster_comparator_->setDistanceThreshold (0.01f, false);
00330 
00331     pcl::PointCloud<pcl::Label> euclidean_labels;
00332     std::vector<pcl::PointIndices> euclidean_label_indices;
00333     pcl::OrganizedConnectedComponentSegmentation<PointT,pcl::Label> euclidean_segmentation (euclidean_cluster_comparator_);
00334     euclidean_segmentation.setInputCloud (cloud);
00335     euclidean_segmentation.segment (euclidean_labels, euclidean_label_indices);
00336     
00337     for (size_t i = 0; i < euclidean_label_indices.size (); i++)
00338     {
00339       if (euclidean_label_indices[i].indices.size () > 1000)
00340       {
00341         pcl::PointCloud<PointT> cluster;
00342         pcl::copyPointCloud (*cloud,euclidean_label_indices[i].indices,cluster);
00343         clusters.push_back (cluster);
00344       }    
00345     }
00346     
00347     PCL_INFO ("Got %d euclidean clusters!\n", clusters.size ());
00348   }          
00349 
00350   {  
00351     QMutexLocker vis_locker (&vis_mtx_);
00352     prev_cloud_ = *cloud;
00353     prev_normals_ = *normal_cloud;
00354     prev_regions_ = regions;
00355     prev_distance_map_ = distance_map;
00356     prev_clusters_ = clusters;
00357     data_modified_ = true;
00358   }
00359 }
00360 
00361 void 
00362 OrganizedSegmentationDemo::timeoutSlot ()
00363 {
00364   {
00365     QMutexLocker vis_locker (&vis_mtx_);
00366     if (capture_ && data_modified_)
00367     {
00368       removePreviousDataFromScreen (previous_data_size_, previous_clusters_size_, vis_);
00369       if (!vis_->updatePointCloud (boost::make_shared<pcl::PointCloud<PointT> >(prev_cloud_), "cloud"))
00370       {
00371         vis_->addPointCloud (boost::make_shared<pcl::PointCloud<PointT> >(prev_cloud_), "cloud");
00372         vis_->resetCameraViewpoint ("cloud");
00373       }
00374 
00375       displayPlanarRegions (prev_regions_, vis_);
00376 
00377       if (display_curvature_)
00378         displayCurvature (prev_cloud_, prev_normals_, vis_);
00379       else
00380         vis_->removePointCloud ("curvature");
00381 
00382       if (display_distance_map_)
00383         displayDistanceMap (prev_cloud_, prev_distance_map_, vis_);
00384       else
00385         vis_->removePointCloud ("distance_map");
00386 
00387       if (display_normals_)
00388       {
00389         vis_->removePointCloud ("normals");
00390         vis_->addPointCloudNormals<PointT,pcl::Normal>(boost::make_shared<pcl::PointCloud<PointT> >(prev_cloud_), boost::make_shared<pcl::PointCloud<pcl::Normal> >(prev_normals_), 10, 0.05f, "normals");
00391         vis_->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, 0.5, "normals");
00392       }
00393       else
00394       {
00395         vis_->removePointCloud ("normals");
00396       }
00397       
00398       displayEuclideanClusters (prev_clusters_,vis_);
00399 
00400       previous_data_size_ = prev_regions_.size ();
00401       previous_clusters_size_ = prev_clusters_.size ();
00402       data_modified_ = false;
00403     }
00404   }
00405   
00406   ui_->qvtk_widget->update();
00407 }
00408 
00409 void
00410 OrganizedSegmentationDemo::useEuclideanComparatorPressed ()
00411 {
00412   QMutexLocker locker (&mtx_);
00413   PCL_INFO ("Setting Comparator to Euclidean\n");
00414   mps.setComparator (euclidean_comparator_);
00415 }
00416 
00417 void
00418 OrganizedSegmentationDemo::useRGBComparatorPressed ()
00419 {
00420   QMutexLocker locker (&mtx_);
00421   PCL_INFO ("Setting Comparator to RGB\n");
00422   mps.setComparator (rgb_comparator_);
00423 }
00424 
00425 void
00426 OrganizedSegmentationDemo::usePlaneComparatorPressed ()
00427 {
00428   QMutexLocker locker (&mtx_);
00429   PCL_INFO ("Setting Comparator to Plane\n");
00430   mps.setComparator (plane_comparator_);
00431 }
00432 
00433 void
00434 OrganizedSegmentationDemo::useEdgeAwareComparatorPressed ()
00435 {
00436   QMutexLocker locker (&mtx_);
00437   PCL_INFO ("Setting Comparator to edge aware\n");
00438   mps.setComparator (edge_aware_comparator_);
00439 }
00440 
00441 void
00442 OrganizedSegmentationDemo::displayCurvaturePressed ()
00443 {
00444   display_curvature_ = !display_curvature_;
00445 }
00446 
00447 void
00448 OrganizedSegmentationDemo::displayDistanceMapPressed ()
00449 {
00450   display_distance_map_ = !display_distance_map_;
00451 }
00452 
00453 void
00454 OrganizedSegmentationDemo::displayNormalsPressed ()
00455 {
00456   display_normals_ = !display_normals_;
00457 }
00458 
00459 int
00460 main (int argc, char ** argv)
00461 {
00462   QApplication app(argc, argv);
00463   
00464   //PCL_INFO ("Creating PCD Grabber\n");
00465   //std::vector<std::string> pcd_files;
00466   //boost::filesystem::directory_iterator end_itr;
00467   //for (boost::filesystem::directory_iterator itr("/u/atrevor/data/sushi_long_pcds_compressed"); itr != end_itr; ++itr)
00468   //{
00469   //  pcd_files.push_back (itr->path ().string ());
00470   //  std::cout << "added: " << itr->path ().string () << std::endl;
00471   //}
00472   //sort (pcd_files.begin (),pcd_files.end ());
00473 
00474   //pcl::PCDGrabber<pcl::PointXYZRGB> grabber(pcd_files,5.0,false);
00475   //PCL_INFO ("PCD Grabber created\n");
00476 
00477   pcl::OpenNIGrabber grabber ("#1");
00478   
00479   OrganizedSegmentationDemo seg_demo (grabber);
00480   seg_demo.show();
00481   return (app.exec ());
00482 }


pcl
Author(s): Open Perception
autogenerated on Mon Oct 6 2014 03:16:14