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 
00009 #include <pcl/segmentation/extract_polygonal_prism_data.h>
00010 #include <pcl/surface/convex_hull.h>
00011 
00012 #include <vtkRenderWindow.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" , int (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   for (size_t i = 0; i < cluster.points.size (); i++)
00142   {
00143     double ptp_dist = fabs (model[0] * cluster.points[i].x +
00144                             model[1] * cluster.points[i].y +
00145                             model[2] * cluster.points[i].z +
00146                             model[3]);
00147     bool in_poly = pcl::isPointIn2DPolygon<PointT> (cluster.points[i], poly);
00148     if (in_poly && ptp_dist < 0.02)
00149       return true;
00150   }
00151   return false;
00152 }
00153 
00154 bool
00155 comparePointToRegion (PointT& pt, pcl::ModelCoefficients& model, pcl::PointCloud<PointT>& poly)
00156 {
00157   //bool dist_ok;
00158   
00159   double ptp_dist = fabs (model.values[0] * pt.x +
00160                           model.values[1] * pt.y +
00161                           model.values[2] * pt.z +
00162                           model.values[3]);
00163   if (ptp_dist >= 0.1)
00164     return (false);
00165 //  else
00166 //    dist_ok = true;
00167 
00168   //project the point onto the plane
00169   Eigen::Vector3f mc (model.values[0], model.values[1], model.values[2]);
00170   Eigen::Vector3f pt_vec;
00171   pt_vec[0] = pt.x;
00172   pt_vec[1] = pt.y;
00173   pt_vec[2] = pt.z;
00174   Eigen::Vector3f projected (pt_vec - mc * float (ptp_dist));
00175   PointT projected_pt;
00176   projected_pt.x = projected[0];
00177   projected_pt.y = projected[1];
00178   projected_pt.z = projected[2];  
00179 
00180   PCL_INFO ("pt: %lf %lf %lf\n", projected_pt.x, projected_pt.y, projected_pt.z);
00181 
00182   if (pcl::isPointIn2DPolygon (projected_pt, poly))
00183   {
00184     PCL_INFO ("inside!\n");
00185     return true;
00186   }
00187   else
00188   {
00189     PCL_INFO ("not inside!\n");
00190     return false;
00191   }
00192   
00193 }
00194 
00196 OrganizedSegmentationDemo::OrganizedSegmentationDemo (pcl::Grabber& grabber) : grabber_ (grabber)
00197 {
00198   //Create a timer
00199   vis_timer_ = new QTimer (this);
00200   vis_timer_->start (5);//5ms
00201 
00202   connect (vis_timer_, SIGNAL (timeout ()), this, SLOT (timeoutSlot()));
00203 
00204   ui_ = new Ui::MainWindow;
00205   ui_->setupUi (this);
00206   
00207   this->setWindowTitle ("PCL Organized Connected Component Segmentation Demo");
00208   vis_.reset (new pcl::visualization::PCLVisualizer ("", false));
00209   ui_->qvtk_widget->SetRenderWindow (vis_->getRenderWindow ());
00210   vis_->setupInteractor (ui_->qvtk_widget->GetInteractor (), ui_->qvtk_widget->GetRenderWindow ());
00211   vis_->getInteractorStyle ()->setKeyboardModifier (pcl::visualization::INTERACTOR_KB_MOD_SHIFT);
00212   ui_->qvtk_widget->update ();
00213 
00214   boost::function<void (const CloudConstPtr&)> f = boost::bind (&OrganizedSegmentationDemo::cloud_cb, this, _1);
00215   boost::signals2::connection c = grabber_.registerCallback(f);
00216   
00217   connect (ui_->captureButton, SIGNAL(clicked()), this, SLOT(toggleCapturePressed()));
00218 
00219   connect (ui_->euclideanComparatorButton, SIGNAL (clicked ()), this, SLOT (useEuclideanComparatorPressed ()));
00220   connect (ui_->planeComparatorButton, SIGNAL (clicked ()), this, SLOT (usePlaneComparatorPressed ()));
00221   connect (ui_->rgbComparatorButton, SIGNAL (clicked ()), this, SLOT (useRGBComparatorPressed ()));
00222   connect (ui_->edgeAwareComparatorButton, SIGNAL (clicked ()), this, SLOT (useEdgeAwareComparatorPressed ()));
00223 
00224   connect (ui_->displayCurvatureButton, SIGNAL (clicked ()), this, SLOT (displayCurvaturePressed ()));
00225   connect (ui_->displayDistanceMapButton, SIGNAL (clicked ()), this, SLOT (displayDistanceMapPressed ()));
00226   connect (ui_->displayNormalsButton, SIGNAL (clicked ()), this, SLOT (displayNormalsPressed ()));
00227 
00228   connect (ui_->disableRefinementButton, SIGNAL (clicked ()), this, SLOT (disableRefinementPressed ()));
00229   connect (ui_->planarRefinementButton, SIGNAL (clicked ()), this, SLOT (usePlanarRefinementPressed ()));
00230 
00231   connect (ui_->disableClusteringButton, SIGNAL (clicked ()), this, SLOT (disableClusteringPressed ()));
00232   connect (ui_->euclideanClusteringButton, SIGNAL (clicked ()), this, SLOT (useEuclideanClusteringPressed ()));
00233 
00234   capture_ = false;
00235   previous_data_size_ = 0;
00236   previous_clusters_size_ = 0;
00237   data_modified_ = true;
00238 
00239   display_normals_ = false;
00240   display_curvature_ = false;
00241   display_distance_map_ = false;
00242 
00243   use_planar_refinement_ = true;
00244   use_clustering_ = false;
00245   
00246 
00247   // Set up Normal Estimation
00248   //ne.setNormalEstimationMethod (ne.SIMPLE_3D_GRADIENT);
00249   ne.setNormalEstimationMethod (ne.COVARIANCE_MATRIX);
00250   ne.setMaxDepthChangeFactor (0.02f);
00251   ne.setNormalSmoothingSize (20.0f);
00252 
00253   plane_comparator_.reset (new pcl::PlaneCoefficientComparator<PointT, pcl::Normal> ());
00254   euclidean_comparator_.reset (new pcl::EuclideanPlaneCoefficientComparator<PointT, pcl::Normal> ());
00255   rgb_comparator_.reset (new pcl::RGBPlaneCoefficientComparator<PointT, pcl::Normal> ());
00256   edge_aware_comparator_.reset (new pcl::EdgeAwarePlaneComparator<PointT, pcl::Normal> ());
00257   euclidean_cluster_comparator_ = pcl::EuclideanClusterComparator<PointT, pcl::Normal, pcl::Label>::Ptr (new pcl::EuclideanClusterComparator<PointT, pcl::Normal, pcl::Label> ());
00258 
00259   // Set up Organized Multi Plane Segmentation
00260   mps.setMinInliers (10000);
00261   mps.setAngularThreshold (pcl::deg2rad (3.0)); //3 degrees
00262   mps.setDistanceThreshold (0.02); //2cm
00263   
00264 
00265   PCL_INFO ("starting grabber\n");
00266   grabber_.start ();
00267 }
00268 
00269 void 
00270 OrganizedSegmentationDemo::cloud_cb (const CloudConstPtr& cloud)
00271 {  
00272   if (!capture_)
00273     return;
00274   QMutexLocker locker (&mtx_);
00275   FPS_CALC ("computation");
00276 
00277   // Estimate Normals
00278   pcl::PointCloud<pcl::Normal>::Ptr normal_cloud (new pcl::PointCloud<pcl::Normal>);
00279   ne.setInputCloud (cloud);
00280   ne.compute (*normal_cloud);
00281   float* distance_map = ne.getDistanceMap ();
00282   boost::shared_ptr<pcl::EdgeAwarePlaneComparator<PointT,pcl::Normal> > eapc = boost::dynamic_pointer_cast<pcl::EdgeAwarePlaneComparator<PointT,pcl::Normal> >(edge_aware_comparator_);
00283   eapc->setDistanceMap (distance_map);
00284   eapc->setDistanceThreshold (0.01f, false);
00285 
00286   // Segment Planes
00287   double mps_start = pcl::getTime ();
00288   std::vector<pcl::PlanarRegion<PointT>, Eigen::aligned_allocator<pcl::PlanarRegion<PointT> > > regions;
00289   std::vector<pcl::ModelCoefficients> model_coefficients;
00290   std::vector<pcl::PointIndices> inlier_indices;  
00291   pcl::PointCloud<pcl::Label>::Ptr labels (new pcl::PointCloud<pcl::Label>);
00292   std::vector<pcl::PointIndices> label_indices;
00293   std::vector<pcl::PointIndices> boundary_indices;
00294   mps.setInputNormals (normal_cloud);
00295   mps.setInputCloud (cloud);
00296   if (use_planar_refinement_)
00297   {
00298     mps.segmentAndRefine (regions, model_coefficients, inlier_indices, labels, label_indices, boundary_indices);
00299   }
00300   else
00301   {
00302     mps.segment (regions);//, model_coefficients, inlier_indices, labels, label_indices, boundary_indices);
00303   }
00304   double mps_end = pcl::getTime ();
00305   std::cout << "MPS+Refine took: " << double(mps_end - mps_start) << std::endl;
00306 
00307   //Segment Objects
00308   pcl::PointCloud<PointT>::CloudVectorType clusters;
00309 
00310   if (use_clustering_ && regions.size () > 0)
00311   {
00312     std::vector<bool> plane_labels;
00313     plane_labels.resize (label_indices.size (), false);
00314     for (size_t i = 0; i < label_indices.size (); i++)
00315     {
00316       if (label_indices[i].indices.size () > 10000)
00317       {
00318         plane_labels[i] = true;
00319       }
00320     }  
00321     
00322     euclidean_cluster_comparator_->setInputCloud (cloud);
00323     euclidean_cluster_comparator_->setLabels (labels);
00324     euclidean_cluster_comparator_->setExcludeLabels (plane_labels);
00325     euclidean_cluster_comparator_->setDistanceThreshold (0.01f, false);
00326 
00327     pcl::PointCloud<pcl::Label> euclidean_labels;
00328     std::vector<pcl::PointIndices> euclidean_label_indices;
00329     pcl::OrganizedConnectedComponentSegmentation<PointT,pcl::Label> euclidean_segmentation (euclidean_cluster_comparator_);
00330     euclidean_segmentation.setInputCloud (cloud);
00331     euclidean_segmentation.segment (euclidean_labels, euclidean_label_indices);
00332     
00333     for (size_t i = 0; i < euclidean_label_indices.size (); i++)
00334     {
00335       if (euclidean_label_indices[i].indices.size () > 1000)
00336       {
00337         pcl::PointCloud<PointT> cluster;
00338         pcl::copyPointCloud (*cloud,euclidean_label_indices[i].indices,cluster);
00339         clusters.push_back (cluster);
00340       }    
00341     }
00342     
00343     PCL_INFO ("Got %d euclidean clusters!\n", clusters.size ());
00344   }          
00345 
00346   {  
00347     QMutexLocker vis_locker (&vis_mtx_);
00348     prev_cloud_ = *cloud;
00349     prev_normals_ = *normal_cloud;
00350     prev_regions_ = regions;
00351     prev_distance_map_ = distance_map;
00352     prev_clusters_ = clusters;
00353     data_modified_ = true;
00354   }
00355 }
00356 
00357 void 
00358 OrganizedSegmentationDemo::timeoutSlot ()
00359 {
00360   {
00361     QMutexLocker vis_locker (&vis_mtx_);
00362     if (capture_ && data_modified_)
00363     {
00364       removePreviousDataFromScreen (previous_data_size_, previous_clusters_size_, vis_);
00365       if (!vis_->updatePointCloud (boost::make_shared<pcl::PointCloud<PointT> >(prev_cloud_), "cloud"))
00366       {
00367         vis_->addPointCloud (boost::make_shared<pcl::PointCloud<PointT> >(prev_cloud_), "cloud");
00368         vis_->resetCameraViewpoint ("cloud");
00369       }
00370 
00371       displayPlanarRegions (prev_regions_, vis_);
00372 
00373       if (display_curvature_)
00374         displayCurvature (prev_cloud_, prev_normals_, vis_);
00375       else
00376         vis_->removePointCloud ("curvature");
00377 
00378       if (display_distance_map_)
00379         displayDistanceMap (prev_cloud_, prev_distance_map_, vis_);
00380       else
00381         vis_->removePointCloud ("distance_map");
00382 
00383       if (display_normals_)
00384       {
00385         vis_->removePointCloud ("normals");
00386         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");
00387         vis_->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, 0.5, "normals");
00388       }
00389       else
00390       {
00391         vis_->removePointCloud ("normals");
00392       }
00393       
00394       displayEuclideanClusters (prev_clusters_,vis_);
00395 
00396       previous_data_size_ = prev_regions_.size ();
00397       previous_clusters_size_ = prev_clusters_.size ();
00398       data_modified_ = false;
00399     }
00400   }
00401   
00402   ui_->qvtk_widget->update();
00403 }
00404 
00405 void
00406 OrganizedSegmentationDemo::useEuclideanComparatorPressed ()
00407 {
00408   QMutexLocker locker (&mtx_);
00409   PCL_INFO ("Setting Comparator to Euclidean\n");
00410   mps.setComparator (euclidean_comparator_);
00411 }
00412 
00413 void
00414 OrganizedSegmentationDemo::useRGBComparatorPressed ()
00415 {
00416   QMutexLocker locker (&mtx_);
00417   PCL_INFO ("Setting Comparator to RGB\n");
00418   mps.setComparator (rgb_comparator_);
00419 }
00420 
00421 void
00422 OrganizedSegmentationDemo::usePlaneComparatorPressed ()
00423 {
00424   QMutexLocker locker (&mtx_);
00425   PCL_INFO ("Setting Comparator to Plane\n");
00426   mps.setComparator (plane_comparator_);
00427 }
00428 
00429 void
00430 OrganizedSegmentationDemo::useEdgeAwareComparatorPressed ()
00431 {
00432   QMutexLocker locker (&mtx_);
00433   PCL_INFO ("Setting Comparator to edge aware\n");
00434   mps.setComparator (edge_aware_comparator_);
00435 }
00436 
00437 void
00438 OrganizedSegmentationDemo::displayCurvaturePressed ()
00439 {
00440   display_curvature_ = !display_curvature_;
00441 }
00442 
00443 void
00444 OrganizedSegmentationDemo::displayDistanceMapPressed ()
00445 {
00446   display_distance_map_ = !display_distance_map_;
00447 }
00448 
00449 void
00450 OrganizedSegmentationDemo::displayNormalsPressed ()
00451 {
00452   display_normals_ = !display_normals_;
00453 }
00454 
00455 int
00456 main (int argc, char ** argv)
00457 {
00458   QApplication app(argc, argv);
00459   
00460   //PCL_INFO ("Creating PCD Grabber\n");
00461   //std::vector<std::string> pcd_files;
00462   //boost::filesystem::directory_iterator end_itr;
00463   //for (boost::filesystem::directory_iterator itr("/u/atrevor/data/sushi_long_pcds_compressed"); itr != end_itr; ++itr)
00464   //{
00465   //  pcd_files.push_back (itr->path ().string ());
00466   //  std::cout << "added: " << itr->path ().string () << std::endl;
00467   //}
00468   //sort (pcd_files.begin (),pcd_files.end ());
00469 
00470   //pcl::PCDGrabber<pcl::PointXYZRGB> grabber(pcd_files,5.0,false);
00471   //PCL_INFO ("PCD Grabber created\n");
00472 
00473   pcl::OpenNIGrabber grabber ("#1");
00474   
00475   OrganizedSegmentationDemo seg_demo (grabber);
00476   seg_demo.show();
00477   return (app.exec ());
00478 }


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:27:29