/** \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; } } }
/** \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[in] plane_boundary_indices a set of indices representing the boundary of the plane * \param[out] object the segmented resultant object */ void segmentObject (int picked_idx, const CloudConstPtr &cloud, const PointIndices::Ptr &plane_indices, const PointIndices::Ptr &plane_boundary_indices, Cloud &object) { CloudPtr plane_hull (new Cloud); // Compute the convex hull of the plane ConvexHull<PointT> chull; chull.setDimension (2); chull.setInputCloud (cloud); chull.setIndices (plane_boundary_indices); chull.reconstruct (*plane_hull); // Remove the plane indices from the data PointIndices::Ptr everything_but_the_plane (new PointIndices); if (indices_fullset_.size () != cloud->points.size ()) { indices_fullset_.resize (cloud->points.size ()); for (int p_it = 0; p_it < static_cast<int> (indices_fullset_.size ()); ++p_it) indices_fullset_[p_it] = p_it; } std::vector<int> indices_subset = plane_indices->indices; std::sort (indices_subset.begin (), indices_subset.end ()); set_difference (indices_fullset_.begin (), indices_fullset_.end (), indices_subset.begin (), indices_subset.end (), inserter (everything_but_the_plane->indices, everything_but_the_plane->indices.begin ())); // Extract all clusters above the hull PointIndices::Ptr points_above_plane (new PointIndices); ExtractPolygonalPrismData<PointT> exppd; exppd.setInputCloud (cloud); exppd.setInputPlanarHull (plane_hull); exppd.setIndices (everything_but_the_plane); exppd.setHeightLimits (0.0, 0.5); // up to half a meter exppd.segment (*points_above_plane); // Use an organized clustering segmentation to extract the individual clusters EuclideanClusterComparator<PointT, Normal, Label>::Ptr euclidean_cluster_comparator (new EuclideanClusterComparator<PointT, Normal, 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 (int i = 0; i < static_cast<int> (points_above_plane->indices.size ()); ++i) scene->points[points_above_plane->indices[i]].label = 1; euclidean_cluster_comparator->setLabels (scene); vector<bool> exclude_labels (2); exclude_labels[0] = true; exclude_labels[1] = false; euclidean_cluster_comparator->setExcludeLabels (exclude_labels); OrganizedConnectedComponentSegmentation<PointT, Label> euclidean_segmentation (euclidean_cluster_comparator); euclidean_segmentation.setInputCloud (cloud); PointCloud<Label> euclidean_labels; vector<PointIndices> euclidean_label_indices; euclidean_segmentation.segment (euclidean_labels, euclidean_label_indices); // For each cluster found bool cluster_found = false; for (size_t i = 0; i < euclidean_label_indices.size (); i++) { if (cluster_found) break; // Check if the point that we picked belongs to it for (size_t j = 0; j < euclidean_label_indices[i].indices.size (); ++j) { if (picked_idx != euclidean_label_indices[i].indices[j]) continue; //pcl::PointCloud<PointT> cluster; pcl::copyPointCloud (*cloud, euclidean_label_indices[i].indices, object); cluster_found = true; break; //object_indices = euclidean_label_indices[i].indices; //clusters.push_back (cluster); } } }