38#ifndef PCL_SEGMENTATION_IMPL_LCCP_SEGMENTATION_HPP_
39#define PCL_SEGMENTATION_IMPL_LCCP_SEGMENTATION_HPP_
41#include <pcl/segmentation/lccp_segmentation.h>
53template <
typename Po
intT>
68template <
typename Po
intT>
73template <
typename Po
intT>
void
86template <
typename Po
intT>
void
107 PCL_WARN (
"[pcl::LCCPSegmentation::segment] WARNING: Call function setInputSupervoxels first. Nothing has been done. \n");
111template <
typename Po
intT>
void
117 for (
auto &voxel : labeled_cloud_arg)
124 PCL_WARN (
"[pcl::LCCPSegmentation::relabelCloud] WARNING: Call function segment first. Nothing has been done. \n");
136template <
typename Po
intT>
void
141 std::uint32_t current_segLabel;
142 std::uint32_t neigh_segLabel;
147 for(std::tie(sv_itr, sv_itr_end) = boost::vertices(
sv_adjacency_list_); sv_itr != sv_itr_end; ++sv_itr)
154 for (std::tie(itr_neighbor, itr_neighbor_end) = boost::adjacent_vertices (*sv_itr,
sv_adjacency_list_); itr_neighbor != itr_neighbor_end; ++itr_neighbor)
159 if (current_segLabel != neigh_segLabel)
167template <
typename Po
intT>
void
175 std::set<std::uint32_t> filteredSegLabels;
177 bool continue_filtering =
true;
179 while (continue_filtering)
181 continue_filtering =
false;
182 unsigned int nr_filtered = 0;
186 for (std::tie(sv_itr, sv_itr_end) = boost::vertices (
sv_adjacency_list_); sv_itr != sv_itr_end; ++sv_itr)
190 std::uint32_t largest_neigh_seg_label = current_seg_label;
194 if (nr_neighbors == 0)
199 continue_filtering =
true;
207 largest_neigh_seg_label = *neighbors_itr;
213 if (largest_neigh_seg_label != current_seg_label)
215 if (filteredSegLabels.count (largest_neigh_seg_label) > 0)
219 filteredSegLabels.insert (current_seg_label);
231 for (
const unsigned int &filteredSegLabel : filteredSegLabels)
243template <
typename Po
intT>
void
245 const std::multimap<std::uint32_t, std::uint32_t>& label_adjaceny_arg)
254 std::map<std::uint32_t, VertexID> label_ID_map;
260 const std::uint32_t& sv_label = svlabel_itr->first;
263 label_ID_map[sv_label] = node_id;
267 for (
const auto &sv_neighbors_itr : label_adjaceny_arg)
269 const std::uint32_t& sv_label = sv_neighbors_itr.first;
270 const std::uint32_t& neighbor_label = sv_neighbors_itr.second;
272 VertexID u = label_ID_map[sv_label];
273 VertexID v = label_ID_map[neighbor_label];
284 const std::uint32_t& sv_label = svlabel_itr->first;
293template <
typename Po
intT>
void
301 const std::uint32_t& sv_label = svlabel_itr->first;
310 unsigned int segment_label = 1;
311 for (std::tie(sv_itr, sv_itr_end) = boost::vertices (
sv_adjacency_list_); sv_itr != sv_itr_end; ++sv_itr)
313 const VertexID sv_vertex_id = *sv_itr;
324template <
typename Po
intT>
void
326 const unsigned int segment_label)
339 for (std::tie(out_Edge_itr, out_Edge_itr_end) = boost::out_edges (query_point_id,
sv_adjacency_list_); out_Edge_itr != out_Edge_itr_end; ++out_Edge_itr)
354template <
typename Po
intT>
void
362 for (std::tie (edge_itr, edge_itr_end) = boost::edges (
sv_adjacency_list_), next_edge = edge_itr; edge_itr != edge_itr_end; edge_itr = next_edge)
370 unsigned int kcount = 0;
377 for (std::tie(source_neighbors_itr, source_neighbors_itr_end) = boost::out_edges (source,
sv_adjacency_list_); source_neighbors_itr != source_neighbors_itr_end; ++source_neighbors_itr)
382 for (std::tie(target_neighbors_itr, target_neighbors_itr_end) = boost::out_edges (target,
sv_adjacency_list_); target_neighbors_itr != target_neighbors_itr_end; ++target_neighbors_itr)
385 if (source_neighbor_ID == target_neighbor_ID)
393 if (src_is_convex && tar_is_convex)
411template <
typename Po
intT>
void
416 for (std::tie(edge_itr, edge_itr_end) = boost::edges (adjacency_list_arg), next_edge = edge_itr; edge_itr != edge_itr_end; edge_itr = next_edge)
420 std::uint32_t source_sv_label = adjacency_list_arg[boost::source (*edge_itr, adjacency_list_arg)];
421 std::uint32_t target_sv_label = adjacency_list_arg[boost::target (*edge_itr, adjacency_list_arg)];
423 float normal_difference;
424 bool is_convex =
connIsConvex (source_sv_label, target_sv_label, normal_difference);
425 adjacency_list_arg[*edge_itr].is_convex = is_convex;
426 adjacency_list_arg[*edge_itr].is_valid = is_convex;
427 adjacency_list_arg[*edge_itr].normal_difference = normal_difference;
431template <
typename Po
intT>
bool
433 const std::uint32_t target_label_arg,
439 const Eigen::Vector3f& source_centroid = sv_source->
centroid_.getVector3fMap ();
440 const Eigen::Vector3f& target_centroid = sv_target->
centroid_.getVector3fMap ();
442 const Eigen::Vector3f& source_normal = sv_source->
normal_.getNormalVector3fMap (). normalized ();
443 const Eigen::Vector3f& target_normal = sv_target->
normal_.getNormalVector3fMap (). normalized ();
451 bool is_convex =
true;
452 bool is_smooth =
true;
454 normal_angle =
getAngle3D (source_normal, target_normal,
true);
456 Eigen::Vector3f vec_t_to_s, vec_s_to_t;
458 vec_t_to_s = source_centroid - target_centroid;
459 vec_s_to_t = -vec_t_to_s;
461 Eigen::Vector3f ncross;
462 ncross = source_normal.cross (target_normal);
468 float dot_p_1 = vec_t_to_s.dot (source_normal);
469 float dot_p_2 = vec_s_to_t.dot (target_normal);
470 float point_dist = (std::fabs (dot_p_1) < std::fabs (dot_p_2)) ? std::fabs (dot_p_1) : std::fabs (dot_p_2);
473 if (point_dist > (expected_distance + dist_smoothing))
481 float intersection_angle =
getAngle3D (ncross, vec_t_to_s,
true);
482 float min_intersect_angle = (intersection_angle < 90.) ? intersection_angle : 180. - intersection_angle;
484 float intersect_thresh = 60. * 1. / (1. + std::exp (-0.25 * (normal_angle - 25.)));
502 return (is_convex && is_smooth);
virtual ~LCCPSegmentation()
float voxel_resolution_
Voxel resolution used to build the supervoxels (used only for smoothness check).
std::map< std::uint32_t, std::set< std::uint32_t > > seg_label_to_sv_list_map_
map Segment Label to a set of Supervoxel Labels
bool supervoxels_set_
Marks if supervoxels have been set by calling setInputSupervoxels.
std::map< std::uint32_t, std::uint32_t > sv_label_to_seg_label_map_
Storing relation between original SuperVoxel Labels and new segmantion labels.
typename boost::graph_traits< SupervoxelAdjacencyList >::vertex_iterator VertexIterator
typename boost::graph_traits< SupervoxelAdjacencyList >::edge_iterator EdgeIterator
boost::adjacency_list< boost::setS, boost::setS, boost::undirectedS, std::uint32_t, EdgeProperties > SupervoxelAdjacencyList
bool grouping_data_valid_
Marks if valid grouping data (sv_adjacency_list_, sv_label_to_seg_label_map_, processed_) is availabl...
void recursiveSegmentGrowing(const VertexID &queryPointID, const unsigned int group_label)
Assigns neighbors of the query point to the same group as the query point.
std::uint32_t k_factor_
Factor used for k-convexity.
void calculateConvexConnections(SupervoxelAdjacencyList &adjacency_list_arg)
Calculates convexity of edges and saves this to the adjacency graph.
void computeSegmentAdjacency()
Compute the adjacency of the segments.
bool use_smoothness_check_
Determines if the smoothness check is used during segmentation.
bool use_sanity_check_
Determines if we use the sanity check which tries to find and invalidate singular connected patches.
void relabelCloud(pcl::PointCloud< pcl::PointXYZL > &labeled_cloud_arg)
Relabels cloud with supervoxel labels with the computed segment labels.
void mergeSmallSegments()
Segments smaller than min_segment_size_ are merged to the label of largest neighbor.
void prepareSegmentation(const std::map< std::uint32_t, typename pcl::Supervoxel< PointT >::Ptr > &supervoxel_clusters_arg, const std::multimap< std::uint32_t, std::uint32_t > &label_adjacency_arg)
Is called within setInputSupervoxels mainly to reserve required memory.
void segment()
Merge supervoxels using local convexity.
float concavity_tolerance_threshold_
*** Parameters *** ///
float smoothness_threshold_
Two supervoxels are unsmooth if their plane-to-plane distance DIST > (expected_distance + smoothness_...
typename boost::graph_traits< SupervoxelAdjacencyList >::out_edge_iterator OutEdgeIterator
float seed_resolution_
Seed resolution of the supervoxels (used only for smoothness check).
std::uint32_t min_segment_size_
Minimum segment size.
std::map< std::uint32_t, bool > processed_
Stores which supervoxel labels were already visited during recursive grouping.
typename boost::graph_traits< SupervoxelAdjacencyList >::adjacency_iterator AdjacencyIterator
bool connIsConvex(const std::uint32_t source_label_arg, const std::uint32_t target_label_arg, float &normal_angle)
Returns true if the connection between source and target is convex.
void doGrouping()
Perform depth search on the graph and recursively group all supervoxels with convex connections.
void applyKconvexity(const unsigned int k_arg)
Connections are only convex if this is true for at least k_arg common neighbors of the two patches.
SupervoxelAdjacencyList sv_adjacency_list_
Adjacency graph with the supervoxel labels as nodes and edges between adjacent supervoxels.
typename boost::graph_traits< SupervoxelAdjacencyList >::edge_descriptor EdgeID
typename boost::graph_traits< SupervoxelAdjacencyList >::vertex_descriptor VertexID
void reset()
Reset internal memory.
std::map< std::uint32_t, typename pcl::Supervoxel< PointT >::Ptr > sv_label_to_supervoxel_map_
map from the supervoxel labels to the supervoxel objects
std::map< std::uint32_t, std::set< std::uint32_t > > seg_label_to_neighbor_set_map_
map < SegmentID, std::set< Neighboring segment labels> >
PointCloud represents the base class in PCL for storing collections of 3D points.
pcl::PointXYZRGBA centroid_
The centroid of the supervoxel - average voxel.
shared_ptr< Supervoxel< PointT > > Ptr
pcl::Normal normal_
The normal calculated for the voxels contained in the supervoxel.
Define standard C methods and C++ classes that are common to all methods.
double getAngle3D(const Eigen::Vector4f &v1, const Eigen::Vector4f &v2, const bool in_degree=false)
Compute the smallest angle between two 3D vectors in radians (default) or degree.