void
compute (ConstCloudPtr &input, Cloud &output, int max_window_size, float slope, float max_distance, float initial_distance, float cell_size, float base, bool exponential)
{
  // Estimate
  TicToc tt;
  tt.tic ();

  print_highlight (stderr, "Computing ");

  std::vector<int> ground;

  ProgressiveMorphologicalFilter<PointType> pmf;
  pmf.setInputCloud (input);
  pmf.setMaxWindowSize (max_window_size);
  pmf.setSlope (slope);
  pmf.setMaxDistance (max_distance);
  pmf.setInitialDistance (initial_distance);
  pmf.setCellSize (cell_size);
  pmf.setBase (base);
  pmf.setExponential (exponential);
  pmf.extract (ground);

  PointIndicesPtr idx (new PointIndices);
  idx->indices = ground;

  ExtractIndices<PointType> extract;
  extract.setInputCloud (input);
  extract.setIndices (idx);
  extract.setNegative (false);
  extract.filter (output);

  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%d", output.width * output.height); print_info (" points]\n");
}
Exemple #2
0
    // Subsample cloud for faster matching and processing, while filling in normals.
    void PointcloudProc::reduceCloud(const PointCloud<PointXYZRGB>& input, PointCloud<PointXYZRGBNormal>& output) const
    {
      PointCloud<PointXYZRGB> cloud_nan_filtered, cloud_box_filtered, cloud_voxel_reduced;
      PointCloud<Normal> normals;
      PointCloud<PointXYZRGBNormal> cloud_normals;
      
      std::vector<int> indices;
      
      // Filter out nans.
      removeNaNFromPointCloud(input, cloud_nan_filtered, indices);
      indices.clear();
      
      // Filter out everything outside a [200x200x200] box.
      Eigen::Vector4f min_pt(-100, -100, -100, -100);
      Eigen::Vector4f max_pt(100, 100, 100, 100);
      getPointsInBox(cloud_nan_filtered, min_pt, max_pt, indices);
      
      ExtractIndices<PointXYZRGB> boxfilter;
      boxfilter.setInputCloud(boost::make_shared<const PointCloud<PointXYZRGB> >(cloud_nan_filtered));
      boxfilter.setIndices (boost::make_shared<vector<int> > (indices));
      boxfilter.filter(cloud_box_filtered);
      
      // Reduce pointcloud
      VoxelGrid<PointXYZRGB> voxelfilter;
      voxelfilter.setInputCloud (boost::make_shared<const PointCloud<PointXYZRGB> > (cloud_box_filtered));
      voxelfilter.setLeafSize (0.05, 0.05, 0.05);
      //      voxelfilter.setLeafSize (0.1, 0.1, 0.1);
      voxelfilter.filter (cloud_voxel_reduced);
      
      // Compute normals
      NormalEstimation<PointXYZRGB, Normal> normalest;
      normalest.setViewPoint(0, 0, 0);
      normalest.setSearchMethod (boost::make_shared<search::KdTree<PointXYZRGB> > ());
      //normalest.setKSearch (10);
      normalest.setRadiusSearch (0.25);
      //      normalest.setRadiusSearch (0.4);
      normalest.setInputCloud(boost::make_shared<const PointCloud<PointXYZRGB> >(cloud_voxel_reduced));
      normalest.compute(normals);
      
      pcl::concatenateFields (cloud_voxel_reduced, normals, cloud_normals);

      // Filter based on curvature
      PassThrough<PointXYZRGBNormal> normalfilter;
      normalfilter.setFilterFieldName("curvature");
      //      normalfilter.setFilterLimits(0.0, 0.2);
      normalfilter.setFilterLimits(0.0, 0.2);
      normalfilter.setInputCloud(boost::make_shared<const PointCloud<PointXYZRGBNormal> >(cloud_normals));
      normalfilter.filter(output);
    }
Exemple #3
0
void getCylClusters (boost::shared_ptr<PointCloud<T> > sceneCloud, vector<boost::shared_ptr<PointCloud<T> > > &outVector) {

  typedef typename pcl::search::KdTree<T>::Ptr my_KdTreePtr;
  typedef typename pcl::PointCloud<T>::Ptr my_PointCloudPtr;

  NormalEstimation<T, Normal> ne;
  SACSegmentationFromNormals<T, Normal> seg; 
  my_KdTreePtr tree (new pcl::search::KdTree<T> ());
  PointCloud<Normal>::Ptr cloud_normals (new PointCloud<pcl::Normal>);

  ModelCoefficients::Ptr coefficients_cylinder (new pcl::ModelCoefficients);
  PointIndices::Ptr  inliers_cylinder (new pcl::PointIndices);
  ExtractIndices<T> extract;

  // Estimate point normals
  ne.setSearchMethod (tree);
  ne.setInputCloud (sceneCloud);
  ne.setKSearch (50);
  ne.compute (*cloud_normals);

  seg.setOptimizeCoefficients (true);
  seg.setModelType (SACMODEL_CYLINDER);
  seg.setMethodType (SAC_RANSAC);
  seg.setNormalDistanceWeight (0.1);
  seg.setMaxIterations (10000);
  seg.setDistanceThreshold (0.05);
  seg.setRadiusLimits (0, 0.1);
  seg.setInputCloud (sceneCloud);
  seg.setInputNormals (cloud_normals);

  // Obtain the cylinder inliers and coefficients
  seg.segment (*inliers_cylinder, *coefficients_cylinder);
  cout << " Number of inliers vs total number of points " << inliers_cylinder->indices.size() << " vs " << sceneCloud->size() << endl; 
  // Write the cylinder inliers to disk
  extract.setInputCloud (sceneCloud);
  extract.setIndices (inliers_cylinder);
  extract.setNegative (false);
  my_PointCloudPtr cloud_cylinder (new PointCloud<T> ());
  extract.filter (*cloud_cylinder);
  
  outVector.push_back(cloud_cylinder);
}
/**
	Toma nube de puntos con gripper y objeto tomado, y los separa, entregando dos nubes diferentes.
	La forma de separarlos es considerando al gripper como un paralelepípedo y luego:
		- Obtener todos los puntos dentro del paralelepípedo
		- Acumular sus índices
		- Retornar puntos dentro y fuera.

	@param cloud_in: Nube con scaneo
	@param gripper_out: Referencia de nube donde retornar gripper aislado
	@param object_out: Referencia de nube donde retornar objeto aislado
	@return: Nada.
 */
void isolateObject(PointCloud<PointXYZ>::Ptr cloud_in, PointCloud<PointXYZ>::Ptr &gripper_out, PointCloud<PointXYZ>::Ptr &object_out){
	// Capturar índices de puntos dentro de paralelepípedo
	PointIndices::Ptr inliers (new PointIndices());
	for (int i=0; i < cloud_in->points.size(); i++){
		for (int j=0; j < gripper_boxes.size(); j++){
			if (isPointInsideBox(cloud_in->points[i], gripper_boxes[j])){
				inliers->indices.push_back(i);
				break;
			}
		}
	}
	// Extraer índices de cada figura
	ExtractIndices<PointXYZ> extractor;
	extractor.setInputCloud(cloud_in);
	extractor.setIndices(inliers);
	extractor.setNegative(false);
	extractor.filter(*gripper_out);
	extractor.setNegative(true);
	extractor.filter(*object_out);
}
Exemple #5
0
	PointCloud<PointXYZ>::Ptr PCLTools::segmentPlanar(PointCloud<PointXYZ>::Ptr cloud, bool negative) {

		// Create the segmentation object for the planar model and set all the parameters
		PointCloud<PointXYZ>::Ptr cloud_f(new PointCloud<PointXYZ>);
		SACSegmentation<PointXYZ> seg;
		PointIndices::Ptr inliers(new PointIndices);
		ModelCoefficients::Ptr coefficients(new ModelCoefficients);
		PointCloud<PointXYZ>::Ptr cloud_plane(new PointCloud<PointXYZ> ());

		seg.setOptimizeCoefficients(true);
		seg.setModelType(pcl::SACMODEL_PLANE);
		seg.setMethodType(pcl::SAC_RANSAC);
		seg.setMaxIterations(100);
		seg.setDistanceThreshold(0.02);

		// Segment the largest planar component from the remaining cloud
		seg.setInputCloud(cloud);
		seg.segment(*inliers, *coefficients);
		if (inliers->indices.size () == 0) {
			cerr << "Could not estimate a planar model for the given dataset." << endl;
			return cloud_f;
		}

		// Extract the planar inliers from the input cloud
		ExtractIndices<PointXYZ> extract;
		extract.setInputCloud(cloud);
		extract.setIndices(inliers);
		extract.setNegative(false);

		// Get the points associated with the planar surface
		extract.filter(*cloud_plane);

		// Remove the planar inliers, extract the rest
		extract.setNegative(negative);
		extract.filter(*cloud_f);

		return cloud_f;

	}
    void
    segment (const PointT &picked_point, 
             int picked_idx,
             PlanarRegion<PointT> &region,
             typename PointCloud<PointT>::Ptr &object)
    {
      object.reset ();

      // Segment out all planes
      vector<ModelCoefficients> model_coefficients;
      vector<PointIndices> inlier_indices, boundary_indices;
      vector<PlanarRegion<PointT>, Eigen::aligned_allocator<PlanarRegion<PointT> > > regions;

      // Prefer a faster method if the cloud is organized, over RANSAC
      if (cloud_->isOrganized ())
      {
        print_highlight (stderr, "Estimating normals ");
        TicToc tt; tt.tic ();
        // Estimate normals
        PointCloud<Normal>::Ptr normal_cloud (new PointCloud<Normal>);
        estimateNormals (cloud_, *normal_cloud);
        print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%lu", normal_cloud->size ()); print_info (" points]\n");

        OrganizedMultiPlaneSegmentation<PointT, Normal, Label> mps;
        mps.setMinInliers (1000);
        mps.setAngularThreshold (deg2rad (3.0)); // 3 degrees
        mps.setDistanceThreshold (0.03); // 2 cm
        mps.setMaximumCurvature (0.001); // a small curvature
        mps.setProjectPoints (true);
        mps.setComparator (plane_comparator_);
        mps.setInputNormals (normal_cloud);
        mps.setInputCloud (cloud_);

        // Use one of the overloaded segmentAndRefine calls to get all the information that we want out
        PointCloud<Label>::Ptr labels (new PointCloud<Label>);
        vector<PointIndices> label_indices;
        mps.segmentAndRefine (regions, model_coefficients, inlier_indices, labels, label_indices, boundary_indices);
      }
      else
      {
        SACSegmentation<PointT> seg;
        seg.setOptimizeCoefficients (true);
        seg.setModelType (SACMODEL_PLANE);
        seg.setMethodType (SAC_RANSAC);
        seg.setMaxIterations (10000);
        seg.setDistanceThreshold (0.005);

        // Copy XYZ and Normals to a new cloud
        typename PointCloud<PointT>::Ptr cloud_segmented (new PointCloud<PointT> (*cloud_));
        typename PointCloud<PointT>::Ptr cloud_remaining (new PointCloud<PointT>);

        ModelCoefficients coefficients;
        ExtractIndices<PointT> extract;
        PointIndices::Ptr inliers (new PointIndices ());

        // Up until 30% of the original cloud is left
        int i = 1;
        while (double (cloud_segmented->size ()) > 0.3 * double (cloud_->size ()))
        {
          seg.setInputCloud (cloud_segmented);

          print_highlight (stderr, "Searching for the largest plane (%2.0d) ", i++);
          TicToc tt; tt.tic ();
          seg.segment (*inliers, coefficients);
          print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%lu", inliers->indices.size ()); print_info (" points]\n");
 
          // No datasets could be found anymore
          if (inliers->indices.empty ())
            break;

          // Save this plane
          PlanarRegion<PointT> region;
          region.setCoefficients (coefficients);
          regions.push_back (region);

          inlier_indices.push_back (*inliers);
          model_coefficients.push_back (coefficients);

          // Extract the outliers
          extract.setInputCloud (cloud_segmented);
          extract.setIndices (inliers);
          extract.setNegative (true);
          extract.filter (*cloud_remaining);
          cloud_segmented.swap (cloud_remaining);
        }
      }
      print_highlight ("Number of planar regions detected: %lu for a cloud of %lu points\n", regions.size (), cloud_->size ());

      double max_dist = numeric_limits<double>::max ();
      // Compute the distances from all the planar regions to the picked point, and select the closest region
      int idx = -1;
      for (size_t i = 0; i < regions.size (); ++i)
      {
        double dist = pointToPlaneDistance (picked_point, regions[i].getCoefficients ()); 
        if (dist < max_dist)
        {
          max_dist = dist;
          idx = static_cast<int> (i);
        }
      }

      // Get the plane that holds the object of interest
      if (idx != -1)
      {
        plane_indices_.reset (new PointIndices (inlier_indices[idx]));

        if (cloud_->isOrganized ())
        {
          approximatePolygon (regions[idx], region, 0.01f, false, true);
          print_highlight ("Planar region: %lu points initial, %lu points after refinement.\n", regions[idx].getContour ().size (), region.getContour ().size ());
        }
        else
        {
          // Save the current region
          region = regions[idx]; 

          print_highlight (stderr, "Obtaining the boundary points for the region ");
          TicToc tt; tt.tic ();
          // Project the inliers to obtain a better hull
          typename PointCloud<PointT>::Ptr cloud_projected (new PointCloud<PointT>);
          ModelCoefficients::Ptr coefficients (new ModelCoefficients (model_coefficients[idx]));
          ProjectInliers<PointT> proj;
          proj.setModelType (SACMODEL_PLANE);
          proj.setInputCloud (cloud_);
          proj.setIndices (plane_indices_);
          proj.setModelCoefficients (coefficients);
          proj.filter (*cloud_projected);

          // Compute the boundary points as a ConvexHull
          ConvexHull<PointT> chull;
          chull.setDimension (2);
          chull.setInputCloud (cloud_projected);
          PointCloud<PointT> plane_hull;
          chull.reconstruct (plane_hull);
          region.setContour (plane_hull);
          print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%lu", plane_hull.size ()); print_info (" points]\n");
        }

      }

      // Segment the object of interest
      if (plane_indices_ && !plane_indices_->indices.empty ())
      {
        plane_.reset (new PointCloud<PointT>);
        copyPointCloud (*cloud_, plane_indices_->indices, *plane_);
        object.reset (new PointCloud<PointT>);
        segmentObject (picked_idx, cloud_, plane_indices_, *object);
      }
    }
    /** \brief Given a plane, and the set of inlier indices representing it,
      * segment out the object of intererest supported by it. 
      *
      * \param[in] picked_idx the index of a point on the object
      * \param[in] cloud the full point cloud dataset
      * \param[in] plane_indices a set of indices representing the plane supporting the object of interest
      * \param[out] object the segmented resultant object 
      */
    void
    segmentObject (int picked_idx, 
                   const typename PointCloud<PointT>::ConstPtr &cloud, 
                   const PointIndices::Ptr &plane_indices, 
                   PointCloud<PointT> &object)
    {
      typename PointCloud<PointT>::Ptr plane_hull (new PointCloud<PointT>);

      // Compute the convex hull of the plane
      ConvexHull<PointT> chull;
      chull.setDimension (2);
      chull.setInputCloud (cloud);
      chull.setIndices (plane_indices);
      chull.reconstruct (*plane_hull);

      // Remove the plane indices from the data
      typename PointCloud<PointT>::Ptr plane (new PointCloud<PointT>);
      ExtractIndices<PointT> extract (true);
      extract.setInputCloud (cloud);
      extract.setIndices (plane_indices);
      extract.setNegative (false);
      extract.filter (*plane);
      PointIndices::Ptr indices_but_the_plane (new PointIndices);
      extract.getRemovedIndices (*indices_but_the_plane);

      // Extract all clusters above the hull
      PointIndices::Ptr points_above_plane (new PointIndices);
      ExtractPolygonalPrismData<PointT> exppd;
      exppd.setInputCloud (cloud);
      exppd.setIndices (indices_but_the_plane);
      exppd.setInputPlanarHull (plane_hull);
      exppd.setViewPoint (cloud->points[picked_idx].x, cloud->points[picked_idx].y, cloud->points[picked_idx].z);
      exppd.setHeightLimits (0.001, 0.5);           // up to half a meter
      exppd.segment (*points_above_plane);

      vector<PointIndices> euclidean_label_indices;
      // Prefer a faster method if the cloud is organized, over EuclidanClusterExtraction
      if (cloud_->isOrganized ())
      {
        // Use an organized clustering segmentation to extract the individual clusters
        typename EuclideanClusterComparator<PointT, Label>::Ptr euclidean_cluster_comparator (new EuclideanClusterComparator<PointT, Label>);
        euclidean_cluster_comparator->setInputCloud (cloud);
        euclidean_cluster_comparator->setDistanceThreshold (0.03f, false);
        // Set the entire scene to false, and the inliers of the objects located on top of the plane to true
        Label l; l.label = 0;
        PointCloud<Label>::Ptr scene (new PointCloud<Label> (cloud->width, cloud->height, l));
        // Mask the objects that we want to split into clusters
        for (const int &index : points_above_plane->indices)
          scene->points[index].label = 1;
        euclidean_cluster_comparator->setLabels (scene);

        boost::shared_ptr<std::set<uint32_t> > exclude_labels = boost::make_shared<std::set<uint32_t> > ();
        exclude_labels->insert (0);
        euclidean_cluster_comparator->setExcludeLabels (exclude_labels);

        OrganizedConnectedComponentSegmentation<PointT, Label> euclidean_segmentation (euclidean_cluster_comparator);
        euclidean_segmentation.setInputCloud (cloud);

        PointCloud<Label> euclidean_labels;
        euclidean_segmentation.segment (euclidean_labels, euclidean_label_indices);
      }
      else
      {
        print_highlight (stderr, "Extracting individual clusters from the points above the reference plane ");
        TicToc tt; tt.tic ();

        EuclideanClusterExtraction<PointT> ec;
        ec.setClusterTolerance (0.02); // 2cm
        ec.setMinClusterSize (100);
        ec.setSearchMethod (search_);
        ec.setInputCloud (cloud);
        ec.setIndices (points_above_plane);
        ec.extract (euclidean_label_indices);
        
        print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%lu", euclidean_label_indices.size ()); print_info (" clusters]\n");
      }

      // For each cluster found
      bool cluster_found = false;
      for (const auto &euclidean_label_index : euclidean_label_indices)
      {
        if (cluster_found)
          break;
        // Check if the point that we picked belongs to it
        for (size_t j = 0; j < euclidean_label_index.indices.size (); ++j)
        {
          if (picked_idx != euclidean_label_index.indices[j])
            continue;
          copyPointCloud (*cloud, euclidean_label_index.indices, object);
          cluster_found = true;
          break;
        }
      }
    }
int main(int argc, char** argv) {

    sensor_msgs::PointCloud2 cloud_blob, cloud_tmp;
    sensor_msgs::PointCloud cloud_blob2;
    pcl::PointCloud<PointT> cloud;
    ofstream labelfile, featfile;
    labelfile.open ("labels.txt");
    featfile.open ("feats.txt");

    // read the pcd file

    if (pcl::io::loadPCDFile(argv[1], cloud_blob) == -1) {
        ROS_ERROR("Couldn't read file test_pcd.pcd");
        return (-1);
    }
    ROS_INFO("Loaded %d data points from test_pcd.pcd with the following fields: %s", (int) (cloud_blob.width * cloud_blob.height), pcl::getFieldsList(cloud_blob).c_str());

    // convert to templated message type

    pcl::fromROSMsg(cloud_blob, cloud);

    pcl::PointCloud<PointT>::Ptr cloud_ptr(new pcl::PointCloud<PointT > (cloud));

    pcl::PointCloud<PointT>::Ptr cloud_filtered(new pcl::PointCloud<PointT > ());
    pcl::PointCloud<PointT>::Ptr cloud_seg(new pcl::PointCloud<PointT > ());
    //pcl::PointCloud<PointXYZI>::Ptr cloud_seg (new pcl::PointCloud<PointXYZI> ());


    pcl::PointIndices::Ptr segment_indices(new pcl::PointIndices());

    // get segments

    // find the max segment number
    int max_segment_num = 0;
    for (size_t i = 0; i < cloud.points.size(); ++i) {
        if (max_segment_num < cloud.points[i].segment) {
            max_segment_num = (int) cloud.points[i].segment;
        }
    }


    ExtractIndices<PointT> extract;


    Eigen::Vector4f min_p;
    Eigen::Vector4f max_p;
    for (int seg = 1; seg <= max_segment_num; seg++) {
        vector<float> features;
        int label;
        segment_indices->indices.clear();
        for (size_t i = 0; i < cloud.points.size(); ++i) {
            if (cloud.points[i].segment == seg) {
                segment_indices->indices.push_back(i);
                label = cloud.points[i].label;
            }
        }
        extract.setInputCloud(cloud_ptr);
        extract.setIndices(segment_indices);
        extract.setNegative(false);
        extract.filter(*cloud_seg);
       // std::cerr << seg << ". Cloud size after extracting : " << cloud_seg->points.size() << std::endl;
        if (cloud_seg->points[0].label != 0) {

            SpectralAnalysis sa(0.05);
            SpinImageNormal spin_image(0.025, 0.025, 5, 4, false, sa);
            ShapeSpectral shape_spectral(sa);
            OrientationNormal o_normal(0, 0, 1, sa);
            OrientationTangent o_tangent(0, 0, 1, sa);
            Position position;
            BoundingBoxSpectral bbox_spectral(1.0, sa);

            // histogram feats
            vector<Descriptor3D*> descriptors_3d;
            descriptors_3d.push_back(&shape_spectral);
            descriptors_3d.push_back(&o_normal);
            //descriptors_3d.push_back(&o_tangent);
            //descriptors_3d.push_back(&position);
            //descriptors_3d.push_back(&bbox_spectral);

            pcl::toROSMsg(*cloud_seg, cloud_tmp);
            sensor_msgs::convertPointCloud2ToPointCloud(cloud_tmp, cloud_blob2);
            cloud_kdtree::KdTreeANN pt_cloud_kdtree(cloud_blob2);
            vector<const geometry_msgs::Point32*> interest_pts;
            if (cloud_seg->points.size() < 200) {
                interest_pts.resize(cloud_blob2.points.size());
                for (size_t i = 0; i < cloud_blob2.points.size(); i++) {
                    interest_pts[i] = &(cloud_blob2.points[i]);
                }
            } else {
                interest_pts.resize(100);
                map<int, int> in;
                int count = 0;
                while (count < 100) {
                    int a = rand() % cloud_blob2.points.size();
                    if (in.find(a) == in.end()) {
                        in[a] = 1;
                        interest_pts[count] = &(cloud_blob2.points[a]);
                    }
                    count++;
                }

            }


            //     vector<vector<float> >  descriptor_results;
            //     spin_image.compute(cloud_blob2, pt_cloud_kdtree, interest_pts, descriptor_results);
            unsigned int nbr_descriptors = descriptors_3d.size();
            vector<vector<vector<float> > > all_descriptor_results(nbr_descriptors);
           
            vector<vector<vector<float> > > hist_feats(nbr_descriptors);
            for (unsigned int i = 0; i < nbr_descriptors; i++) {
                std::cerr << "hist featnum: " << i << "\n"  ;
                descriptors_3d[i]->compute(cloud_blob2, pt_cloud_kdtree, interest_pts, all_descriptor_results[i]);
                std::cerr << "feature computed" << "\n"  ;
                get_feat_histogram(all_descriptor_results[i], hist_feats[i]);
                concat_feats(features,hist_feats[i]);
            }


            // average feats
            vector<Descriptor3D*> descriptors_3d_avg;
            descriptors_3d_avg.push_back(&spin_image);

            unsigned int nbr_descriptors_avg = descriptors_3d_avg.size();
            vector<vector<vector<float> > > all_avg_descriptor_results(nbr_descriptors);
            vector<vector<float> > avg_feats(nbr_descriptors_avg);
            for (unsigned int i = 0; i < nbr_descriptors_avg; i++) {
                std::cerr << "avg featnum: " << i << "\n"  ;
                descriptors_3d_avg[i]->compute(cloud_blob2, pt_cloud_kdtree, interest_pts, all_avg_descriptor_results[i]);
                get_avg_feats(all_avg_descriptor_results[i], avg_feats[i]);
                concat_feats(features,avg_feats[i]);
            }
           

            getMinMax(*cloud_ptr, *segment_indices, min_p, max_p);
          //  ROS_INFO("minp : %f,%f,%f\t maxp : %f,%f,%f", min_p[0], min_p[1], min_p[2], max_p[0], max_p[1], max_p[2]);
          //  ROS_INFO("size of all_descriptor_results : %d", all_descriptor_results[1].size());
            // add bounding box features
            features.push_back(max_p[0]-  min_p[0]);
            features.push_back(max_p[1]-  min_p[1]);
            features.push_back(max_p[2]-  min_p[2]);


            // write label to  file
             labelfile << cloud_seg->points[0].label <<"\n";

            // write features to file
             for (vector<float>::iterator it = features.begin(); it < features.end(); it++) {
                 featfile << *it <<"\t";
             }
             featfile <<"\n";
        }
    }


    // print out the features to a file
    
    labelfile.close();
    featfile.close();


}
Exemple #9
0
// Returns the points that are above the floor, but not the floor itself
CloudT get_object_points(CloudT cloud)
{
  // PHASE 1: DATA CLEANUP
  ////////////////////////////////////////////////////////

  // Filter out NaNs from data (this is necessary now) ...
  PassThrough<PointXYZRGB> nan_remover;
  nan_remover.setInputCloud(boost::make_shared<PointCloud<PointXYZRGB> >(cloud));
  nan_remover.setFilterFieldName("z");
  nan_remover.setFilterLimits(0.0, 10.0);
  nan_remover.filter(cloud);

  // Filter out statistical outliers
  StatisticalOutlierRemoval<PointXYZRGB> statistical_filter;
  statistical_filter.setInputCloud(boost::make_shared<PointCloud<PointXYZRGB> >(cloud));
  statistical_filter.setMeanK(50);
  statistical_filter.setStddevMulThresh(1.0);
  statistical_filter.filter(cloud);

  // Downsample to 1cm Voxel Grid
  pcl::VoxelGrid<PointT> downsampler;
  downsampler.setInputCloud(boost::make_shared<CloudT>(cloud));
  downsampler.setLeafSize(0.005, 0.005, 0.005);
  downsampler.filter(cloud);
  ROS_INFO("PointCloud after filtering: %d data points.", cloud.width * cloud.height);

  // PHASE 2: FIND THE GROUND PLANE
  /////////////////////////////////////////////////////////

  // Step 3: Find the ground plane using RANSAC
  ModelCoefficients ground_coefficients;
  PointIndices ground_indices;
  SACSegmentation<PointXYZRGB> ground_finder;
  ground_finder.setOptimizeCoefficients(true);
  ground_finder.setModelType(SACMODEL_PLANE);
  ground_finder.setMethodType(SAC_RANSAC);
  ground_finder.setDistanceThreshold(0.015);
  ground_finder.setInputCloud(boost::make_shared<PointCloud<PointXYZRGB> >(cloud));
  ground_finder.segment(ground_indices, ground_coefficients);

  // PHASE 3: EXTRACT ONLY POINTS ABOVE THE GROUND PLANE
  /////////////////////////////////////////////////////////

  // Step 3a. Extract the ground plane inliers
  CloudT ground_points;
  ExtractIndices<PointXYZRGB> extractor;
  extractor.setInputCloud(boost::make_shared<PointCloud<PointXYZRGB> >(cloud));
  extractor.setIndices(boost::make_shared<PointIndices>(ground_indices));
  extractor.filter(ground_points);

  // Step 3b. Extract the ground plane outliers
  CloudT object_points;
  ExtractIndices<PointXYZRGB> outlier_extractor;
  outlier_extractor.setInputCloud(boost::make_shared<PointCloud<PointXYZRGB> >(cloud));
  outlier_extractor.setIndices(boost::make_shared<PointIndices>(ground_indices));
  outlier_extractor.setNegative(true);
  outlier_extractor.filter(object_points);

  // Step 3c. Project the ground inliers
  PointCloud<PointXYZRGB> cloud_projected;
  ProjectInliers<PointXYZRGB> proj;
  proj.setModelType(SACMODEL_PLANE);
  proj.setInputCloud(boost::make_shared<PointCloud<PointXYZRGB> >(ground_points));
  proj.setModelCoefficients(boost::make_shared<ModelCoefficients>(ground_coefficients));
  proj.filter(cloud_projected);

  // Step 3d. Create a Convex Hull representation of the projected inliers
  PointCloud<PointXYZRGB> ground_hull;
  ConvexHull2D<PointXYZRGB, PointXYZRGB> chull;
  chull.setInputCloud(boost::make_shared<PointCloud<PointXYZRGB> >(cloud_projected));
  chull.reconstruct(ground_hull);

  ROS_INFO ("Convex hull has: %d data points.", (int) ground_hull.points.size ());

  hull_pub.publish(ground_hull);

  // Step 3e. Extract only those outliers that lie above the ground plane's convex hull
  PointIndices object_indices;
  ExtractPolygonalPrismData<PointT> hull_limiter;
  hull_limiter.setInputCloud(boost::make_shared<CloudT>(object_points));
  hull_limiter.setInputPlanarHull(boost::make_shared<CloudT>(ground_hull));
  hull_limiter.setHeightLimits(0, 0.3);
  hull_limiter.segment(object_indices);

  ExtractIndices<PointT> object_extractor;
  object_extractor.setInputCloud(boost::make_shared<CloudT>(object_points));
  object_extractor.setIndices(boost::make_shared<PointIndices>(object_indices));
  object_extractor.filter(object_points);

  return object_points;
}
Exemple #10
0
/**
* This function tries to find all planes in a point cloud by applying
* a model-based RANSAC algorithm.
*
* Heavily inspired by
* http://www.pointclouds.org/documentation/tutorials/extract_indices.php
*/
void filterPlanes(
	TheiaCloudPtr inCloud,
	TheiaCloudPtr outPlanes,
	TheiaCloudPtr outObjects
){
	TheiaCloudPtr workingCloudPtr(new TheiaCloud(*inCloud));
	size_t origCloudSize = workingCloudPtr->points.size();
	size_t minPlanePoints = config.minPercentage * origCloudSize;

	if(origCloudSize < 3){
		ROS_INFO("Input cloud for findPlanes is too small");
		ROS_INFO("Check cropping and rescaling parameters");
		return;
	}


	TheiaCloudPtr allPlanesCloudPtr(new TheiaCloud());
	PointIndices::Ptr inliers(new PointIndices());
	ModelCoefficients::Ptr coefficients(new ModelCoefficients());

	// prepare plane segmentation
	SACSegmentation<TheiaPoint> seg;
	seg.setModelType(SACMODEL_PLANE);
	seg.setMethodType(SAC_RANSAC);
	seg.setMaxIterations(config.numbIterations);
	seg.setDistanceThreshold(config.planeDistThresh);
	seg.setOptimizeCoefficients(config.planeOptimize);

	// prepare extractor
	ExtractIndices<TheiaPoint> extract;

	while(workingCloudPtr->points.size() >= 4){
		seg.setInputCloud(workingCloudPtr);
		seg.segment(*inliers, *coefficients);

		/**
		* Stop the search for planes when the found plane
		* is too small (in terms of points).
		*/
		size_t numbInliers = inliers->indices.size();
		if(!numbInliers) break;
		if(numbInliers < minPlanePoints) break;
		
		// extract plane points
		TheiaCloudPtr planeCloudPtr(new TheiaCloud());
		extract.setInputCloud(workingCloudPtr);
		extract.setIndices(inliers);
		extract.setNegative(false);
		extract.filter(*planeCloudPtr);

		*allPlanesCloudPtr += *planeCloudPtr;

		/**
		* Remove plane from input cloud
		*/
		TheiaCloudPtr remainingCloudPtr(new TheiaCloud());
		extract.setNegative(true);
		extract.filter(*remainingCloudPtr);

		/**
		* Continue search 
		* But only use remaining point cloud
		*/
		workingCloudPtr->swap(*remainingCloudPtr);
	}

	*outPlanes = TheiaCloud(*allPlanesCloudPtr);
	*outObjects = TheiaCloud(*workingCloudPtr);
}
int main(int argc, char** argv)
{
	if (argc < 2)
	{
		cout << "Input a PCD file name...\n";
		return 0;
	}

	PointCloud<PointXYZ>::Ptr cloud(new PointCloud<PointXYZ>), cloud_f(new PointCloud<PointXYZ>);
	PCDReader reader;
	reader.read(argv[1], *cloud);
	cout << "PointCloud before filtering has: " << cloud->points.size() << " data points.\n";

	PointCloud<PointXYZ>::Ptr cloud_filtered(new PointCloud<PointXYZ>);
	VoxelGrid<PointXYZ> vg;
	vg.setInputCloud(cloud);
	vg.setLeafSize(0.01f, 0.01f, 0.01f);
	vg.filter(*cloud_filtered);
	cout << "PointCloud after filtering has: " << cloud_filtered->points.size() << " data points.\n";

	SACSegmentation<PointXYZ> seg;
	PointIndices::Ptr inliers(new PointIndices);
	PointCloud<PointXYZ>::Ptr cloud_plane(new PointCloud<PointXYZ>);

	ModelCoefficients::Ptr coefficients(new ModelCoefficients);
	seg.setOptimizeCoefficients(true);
	seg.setModelType(SACMODEL_PLANE);
	seg.setMethodType(SAC_RANSAC);
	seg.setMaxIterations(100);
	seg.setDistanceThreshold(0.02);

	int i=0, nr_points = (int)cloud_filtered->points.size();
	while (cloud_filtered->points.size() > 0.3 * nr_points)
	{
		seg.setInputCloud(cloud_filtered);
		seg.segment(*inliers, *coefficients);
		if (inliers->indices.size() == 0)
		{
			cout << "Coud not estimate a planar model for the given dataset.\n";
			break;
		}

		ExtractIndices<PointXYZ> extract;
		extract.setInputCloud(cloud_filtered);
		extract.setIndices(inliers);
		extract.setNegative(false);
		extract.filter(*cloud_plane);
		cout << "PointCloud representing the planar component has: " << cloud_filtered->points.size() << " data points.\n";

		extract.setNegative(true);
		extract.filter(*cloud_f);
		cloud_filtered->swap(*cloud_f);
	}

	search::KdTree<PointXYZ>::Ptr kdtree(new search::KdTree<PointXYZ>);
	kdtree->setInputCloud(cloud_filtered);

	vector<PointIndices> cluster_indices;
	EuclideanClusterExtraction<PointXYZ> ece;
	ece.setClusterTolerance(0.02);
	ece.setMinClusterSize(100);
	ece.setMaxClusterSize(25000);
	ece.setSearchMethod(kdtree);
	ece.setInputCloud(cloud_filtered);
	ece.extract(cluster_indices);

	PCDWriter writer;
	int j = 0;
	for (vector<PointIndices>::const_iterator it=cluster_indices.begin(); it != cluster_indices.end(); ++it)
	{
		PointCloud<PointXYZ>::Ptr cluster_cloud(new PointCloud<PointXYZ>);
		for (vector<int>::const_iterator pit=it->indices.begin(); pit != it->indices.end(); ++pit)
			cluster_cloud->points.push_back(cloud_filtered->points[*pit]);
		cluster_cloud->width = cluster_cloud->points.size();
		cluster_cloud->height = 1;
		cluster_cloud->is_dense = true;

		cout << "PointCloud representing a cluster has: " << cluster_cloud->points.size() << " data points.\n";

		stringstream ss;
		ss << "cloud_cluster_" << j << ".pcd";
		writer.write<PointXYZ>(ss.str(), *cluster_cloud, false);
		j++;
	}

	return 0;
}