pcd_organized_multi_plane_segmentation.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2012, Willow Garage, Inc.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of Willow Garage, Inc. nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *
00034  */
00035 #include <pcl/io/io.h>
00036 #include <pcl/io/pcd_io.h>
00037 #include <pcl/visualization/pcl_visualizer.h>
00038 #include <boost/make_shared.hpp>
00039 #include <pcl/common/time.h>
00040 #include <pcl/features/integral_image_normal.h>
00041 #include <pcl/features/normal_3d.h>
00042 #include <pcl/ModelCoefficients.h>
00043 #include <pcl/segmentation/planar_region.h>
00044 #include <pcl/segmentation/organized_multi_plane_segmentation.h>
00045 #include <pcl/segmentation/organized_connected_component_segmentation.h>
00046 #include <pcl/filters/extract_indices.h>
00047 #include <pcl/console/parse.h>
00048 #include <pcl/geometry/polygon_operations.h>
00049 
00050 template<typename PointT>
00051 class PCDOrganizedMultiPlaneSegmentation
00052 {
00053   private:
00054     pcl::visualization::PCLVisualizer viewer;
00055     typename pcl::PointCloud<PointT>::ConstPtr cloud;
00056     bool refine_;
00057     float threshold_;
00058     bool depth_dependent_;
00059     bool polygon_refinement_;
00060   public:
00061     PCDOrganizedMultiPlaneSegmentation (typename pcl::PointCloud<PointT>::ConstPtr cloud_, bool refine)
00062     : viewer ("Viewer")
00063     , cloud (cloud_)
00064     , refine_ (refine)
00065     , threshold_ (0.02f)
00066     , depth_dependent_ (true)
00067     , polygon_refinement_ (false)
00068     {
00069       viewer.setBackgroundColor (0, 0, 0);
00070       //viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "cloud");
00071       //viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, 0.15, "cloud");
00072       viewer.addCoordinateSystem (1.0);
00073       viewer.initCameraParameters ();
00074       viewer.registerKeyboardCallback(&PCDOrganizedMultiPlaneSegmentation::keyboard_callback, *this, 0);
00075     }
00076 
00077     void keyboard_callback (const pcl::visualization::KeyboardEvent& event, void*)
00078     {
00079       // do stuff and visualize here
00080       if (event.keyUp ())
00081       {
00082         switch (event.getKeyCode ())
00083         {
00084           case 'b':
00085           case 'B':
00086             if (threshold_ < 0.1f)
00087               threshold_ += 0.001f;
00088             break;
00089           case 'v':
00090           case 'V':
00091             if (threshold_ > 0.001f)
00092               threshold_ -= 0.001f;
00093             break;
00094             
00095           case 'n':
00096           case 'N':
00097             depth_dependent_ = !depth_dependent_;
00098             break;
00099             
00100           case 'm':
00101           case 'M':
00102             polygon_refinement_ = !polygon_refinement_;
00103             break;
00104         }
00105         
00106         process ();
00107       }
00108     }
00109     
00110     void
00111     process ()
00112     {
00113       std::cout << "threshold: " << threshold_ << std::endl;
00114       std::cout << "depth dependent: " << (depth_dependent_ ? "true\n" : "false\n");
00115       unsigned char red [6] = {255,   0,   0, 255, 255,   0};
00116       unsigned char grn [6] = {  0, 255,   0, 255,   0, 255};
00117       unsigned char blu [6] = {  0,   0, 255,   0, 255, 255};
00118 
00119       pcl::IntegralImageNormalEstimation<PointT, pcl::Normal> ne;
00120       ne.setNormalEstimationMethod (ne.COVARIANCE_MATRIX);
00121       ne.setMaxDepthChangeFactor (0.02f);
00122       ne.setNormalSmoothingSize (20.0f);
00123       
00124       typename pcl::PlaneRefinementComparator<PointT, pcl::Normal, pcl::Label>::Ptr refinement_compare (new pcl::PlaneRefinementComparator<PointT, pcl::Normal, pcl::Label> ());
00125       refinement_compare->setDistanceThreshold (threshold_, depth_dependent_);
00126       
00127       pcl::OrganizedMultiPlaneSegmentation<PointT, pcl::Normal, pcl::Label> mps;
00128       mps.setMinInliers (5000);
00129       mps.setAngularThreshold (0.017453 * 3.0); //3 degrees
00130       mps.setDistanceThreshold (0.03); //2cm
00131       mps.setRefinementComparator (refinement_compare);
00132       
00133       std::vector<pcl::PlanarRegion<PointT>, Eigen::aligned_allocator<pcl::PlanarRegion<PointT> > > regions;
00134       typename pcl::PointCloud<PointT>::Ptr contour (new pcl::PointCloud<PointT>);
00135       typename pcl::PointCloud<PointT>::Ptr approx_contour (new pcl::PointCloud<PointT>);
00136       char name[1024];
00137 
00138       typename pcl::PointCloud<pcl::Normal>::Ptr normal_cloud (new pcl::PointCloud<pcl::Normal>);
00139       double normal_start = pcl::getTime ();
00140       ne.setInputCloud (cloud);
00141       ne.compute (*normal_cloud);
00142       double normal_end = pcl::getTime ();
00143       std::cout << "Normal Estimation took " << double (normal_end - normal_start) << std::endl;
00144 
00145       double plane_extract_start = pcl::getTime ();
00146       mps.setInputNormals (normal_cloud);
00147       mps.setInputCloud (cloud);
00148       if (refine_)
00149         mps.segmentAndRefine (regions);
00150       else
00151         mps.segment (regions);
00152       double plane_extract_end = pcl::getTime ();
00153       std::cout << "Plane extraction took " << double (plane_extract_end - plane_extract_start) << " with planar regions found: " << regions.size () << std::endl;
00154       std::cout << "Frame took " << double (plane_extract_end - normal_start) << std::endl;
00155 
00156       typename pcl::PointCloud<PointT>::Ptr cluster (new pcl::PointCloud<PointT>);
00157 
00158       viewer.removeAllPointClouds (0);
00159       viewer.removeAllShapes (0);
00160       pcl::visualization::PointCloudColorHandlerCustom<PointT> single_color (cloud, 0, 255, 0);
00161       viewer.addPointCloud<PointT> (cloud, single_color, "cloud");
00162       
00163       pcl::PlanarPolygon<PointT> approx_polygon;
00164       //Draw Visualization
00165       for (size_t i = 0; i < regions.size (); i++)
00166       {
00167         Eigen::Vector3f centroid = regions[i].getCentroid ();
00168         Eigen::Vector4f model = regions[i].getCoefficients ();
00169         pcl::PointXYZ pt1 = pcl::PointXYZ (centroid[0], centroid[1], centroid[2]);
00170         pcl::PointXYZ pt2 = pcl::PointXYZ (centroid[0] + (0.5f * model[0]),
00171                                            centroid[1] + (0.5f * model[1]),
00172                                            centroid[2] + (0.5f * model[2]));
00173         sprintf (name, "normal_%d", unsigned (i));
00174         viewer.addArrow (pt2, pt1, 1.0, 0, 0, name);
00175 
00176         contour->points = regions[i].getContour ();        
00177         sprintf (name, "plane_%02d", int (i));
00178         pcl::visualization::PointCloudColorHandlerCustom <PointT> color (contour, red[i], grn[i], blu[i]);
00179         viewer.addPointCloud (contour, color, name);
00180 
00181         pcl::approximatePolygon (regions[i], approx_polygon, threshold_, polygon_refinement_);
00182         approx_contour->points = approx_polygon.getContour ();
00183         std::cout << "polygon: " << contour->size () << " -> " << approx_contour->size () << std::endl;
00184         typename pcl::PointCloud<PointT>::ConstPtr approx_contour_const = approx_contour;
00185         
00186 //        sprintf (name, "approx_plane_%02d", int (i));
00187 //        viewer.addPolygon<PointT> (approx_contour_const, 0.5 * red[i], 0.5 * grn[i], 0.5 * blu[i], name);
00188         for (unsigned idx = 0; idx < approx_contour->points.size (); ++idx)
00189         {
00190           sprintf (name, "approx_plane_%02d_%03d", int (i), int(idx));
00191           viewer.addLine (approx_contour->points [idx], approx_contour->points [(idx+1)%approx_contour->points.size ()], 0.5 * red[i], 0.5 * grn[i], 0.5 * blu[i], name);
00192         }
00193       }
00194     }
00195     
00196     void
00197     run ()
00198     {
00199       // initial processing
00200       process ();
00201     
00202       while (!viewer.wasStopped ())
00203         viewer.spinOnce (100);
00204     }
00205 };
00206 
00207 int
00208 main (int argc, char** argv)
00209 {
00210   bool refine = pcl::console::find_switch (argc, argv, "-refine");
00211   
00212   pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_xyz (new pcl::PointCloud<pcl::PointXYZ>);
00213   pcl::io::loadPCDFile (argv[1], *cloud_xyz);
00214   PCDOrganizedMultiPlaneSegmentation<pcl::PointXYZ> multi_plane_app (cloud_xyz, refine);
00215   multi_plane_app.run ();
00216   return 0;
00217 }


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