00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
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
00071
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
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);
00130 mps.setDistanceThreshold (0.03);
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
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
00187
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
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 }