Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LCCP preparation for CPC #1287

Merged
merged 1 commit into from
Jul 29, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions examples/segmentation/example_lccp_segmentation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ LCCPSegmentation Parameters: \n\
-st <smoothness threshold> - Invalidate steps. Value from the interval [0,1], where 0 is the strictest and 1 equals 'no smoothness check' \n\
-ec - Use extended (less local) convexity check\n\
-sc - Use sanity criterion to invalidate singular connected patches\n\
-smooth <mininmal segment size> - Remove small segments which have fewer points than minimal segment size\n\
-smooth <mininmal segment size> - Merge small segments which have fewer points than minimal segment size\n\
\n",
argv[0]);
return (1);
Expand Down Expand Up @@ -391,14 +391,14 @@ LCCPSegmentation Parameters: \n\

/// Create a cloud of the voxelcenters and map: VertexID in adjacency graph -> Point index in cloud

vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New ();
vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New ();
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New ();
vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New ();
vtkSmartPointer<vtkUnsignedCharArray> colors = vtkSmartPointer<vtkUnsignedCharArray>::New ();
colors->SetNumberOfComponents (3);
colors->SetName ("Colors");

// Create a polydata to store everything in
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New ();
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New ();
for (VertexIterator itr = vertex_iterator_range.first; itr != vertex_iterator_range.second; ++itr)
{
const uint32_t sv_label = sv_adjacency_list[*itr];
Expand All @@ -417,7 +417,7 @@ LCCPSegmentation Parameters: \n\
colors->InsertNextTupleValue (color);

pcl::Supervoxel<PointT>::Ptr supervoxel = supervoxel_clusters.at (sv_label);
pcl::PointXYZRGBA vert_curr = supervoxel->centroid_;
pcl::PointXYZRGBA vert_curr = supervoxel->centroid_;


const uint32_t sv_neighbor_label = sv_adjacency_list[*itr_neighbor];
Expand All @@ -434,10 +434,10 @@ LCCPSegmentation Parameters: \n\
polyLine->GetPointIds ()->SetId (1, points->GetNumberOfPoints ()-1);
cells->InsertNextCell (polyLine);
}
}
}
polyData->SetPoints (points);
// Add the lines to the dataset
polyData->SetLines (cells);
polyData->SetLines (cells);

polyData->GetPointData ()->SetScalars (colors);

Expand Down
63 changes: 42 additions & 21 deletions segmentation/include/pcl/segmentation/impl/lccp_segmentation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,14 @@ pcl::LCCPSegmentation<PointT>::computeSegmentAdjacency ()
// For every Supervoxel..
for (VertexIterator sv_itr = vertex_iterator_range.first; sv_itr != vertex_iterator_range.second; ++sv_itr) // For all SuperVoxels
{
const uint32_t sv_label = sv_adjacency_list_[*sv_itr];
const uint32_t& sv_label = sv_adjacency_list_[*sv_itr];
current_segLabel = sv_label_to_seg_label_map_[sv_label];

// ..look at all neighbors and insert their labels into the neighbor set
std::pair<AdjacencyIterator, AdjacencyIterator> neighbors = boost::adjacent_vertices (*sv_itr, sv_adjacency_list_);
for (AdjacencyIterator itr_neighbor = neighbors.first; itr_neighbor != neighbors.second; ++itr_neighbor)
{
const uint32_t neigh_label = sv_adjacency_list_[*itr_neighbor];
const uint32_t& neigh_label = sv_adjacency_list_[*itr_neighbor];
neigh_segLabel = sv_label_to_seg_label_map_[neigh_label];

if (current_segLabel != neigh_segLabel)
Expand Down Expand Up @@ -159,12 +159,12 @@ pcl::LCCPSegmentation<PointT>::mergeSmallSegments (uint32_t min_segment_size_arg
// Iterate through all supervoxels, check if they are in a "small" segment -> change label to largest neighborID
for (VertexIterator sv_itr = vertex_iterator_range.first; sv_itr != vertex_iterator_range.second; ++sv_itr) // For all SuperVoxels
{
const uint32_t sv_label = sv_adjacency_list_[*sv_itr];
const uint32_t& sv_label = sv_adjacency_list_[*sv_itr];
current_seg_label = sv_label_to_seg_label_map_[sv_label];
largest_neigh_seg_label = current_seg_label;
largest_neigh_size = seg_label_to_sv_list_map_[current_seg_label].size ();

const uint32_t nr_neighbors = seg_label_to_neighbor_set_map_[current_seg_label].size ();
const uint32_t& nr_neighbors = seg_label_to_neighbor_set_map_[current_seg_label].size ();
if (nr_neighbors == 0)
continue;

Expand Down Expand Up @@ -240,7 +240,7 @@ pcl::LCCPSegmentation<PointT>::prepareSegmentation (const std::map<uint32_t, typ
for (typename std::map<uint32_t, typename pcl::Supervoxel<PointT>::Ptr>::iterator svlabel_itr = sv_label_to_supervoxel_map_.begin ();
svlabel_itr != sv_label_to_supervoxel_map_.end (); ++svlabel_itr)
{
const uint32_t sv_label = svlabel_itr->first;
const uint32_t& sv_label = svlabel_itr->first;
VertexID node_id = boost::add_vertex (sv_adjacency_list_);
sv_adjacency_list_[node_id] = sv_label;
label_ID_map[sv_label] = node_id;
Expand All @@ -250,8 +250,8 @@ pcl::LCCPSegmentation<PointT>::prepareSegmentation (const std::map<uint32_t, typ
for (std::multimap<uint32_t, uint32_t>::const_iterator sv_neighbors_itr = label_adjaceny_arg.begin (); sv_neighbors_itr != label_adjaceny_arg.end ();
++sv_neighbors_itr)
{
const uint32_t sv_label = sv_neighbors_itr->first;
const uint32_t neighbor_label = sv_neighbors_itr->second;
const uint32_t& sv_label = sv_neighbors_itr->first;
const uint32_t& neighbor_label = sv_neighbors_itr->second;

VertexID u = label_ID_map[sv_label];
VertexID v = label_ID_map[neighbor_label];
Expand All @@ -265,7 +265,7 @@ pcl::LCCPSegmentation<PointT>::prepareSegmentation (const std::map<uint32_t, typ
for (typename std::map<uint32_t, typename pcl::Supervoxel<PointT>::Ptr>::iterator svlabel_itr = sv_label_to_supervoxel_map_.begin ();
svlabel_itr != sv_label_to_supervoxel_map_.end (); ++svlabel_itr)
{
const uint32_t sv_label = svlabel_itr->first;
const uint32_t& sv_label = svlabel_itr->first;
processed_[sv_label] = false;
sv_label_to_seg_label_map_[sv_label] = 0;
}
Expand All @@ -285,6 +285,24 @@ pcl::LCCPSegmentation<PointT>::segment (std::map<uint32_t, typename pcl::Supervo
// Correct edge relations using extended convexity definition if k>0
applyKconvexity (k_factor_);

// Determine wether to use cutting planes
doGrouping ();
grouping_data_valid_ = true;
}

template <typename PointT> void
pcl::LCCPSegmentation<PointT>::doGrouping ()
{
// clear the processed_ map
seg_label_to_sv_list_map_.clear ();
for (typename std::map<uint32_t, typename pcl::Supervoxel<PointT>::Ptr>::iterator svlabel_itr = sv_label_to_supervoxel_map_.begin ();
svlabel_itr != sv_label_to_supervoxel_map_.end (); ++svlabel_itr)
{
const uint32_t& sv_label = svlabel_itr->first;
processed_[sv_label] = false;
sv_label_to_seg_label_map_[sv_label] = 0;
}

// Perform depth search on the graph and recursively group all supervoxels with convex connections
//The vertices in the supervoxel adjacency list are the supervoxel centroids
std::pair< VertexIterator, VertexIterator> vertex_iterator_range;
Expand All @@ -295,22 +313,21 @@ pcl::LCCPSegmentation<PointT>::segment (std::map<uint32_t, typename pcl::Supervo
for (VertexIterator sv_itr = vertex_iterator_range.first; sv_itr != vertex_iterator_range.second; ++sv_itr) // For all SuperVoxels
{
const VertexID sv_vertex_id = *sv_itr;
const uint32_t sv_label = sv_adjacency_list_[sv_vertex_id];
const uint32_t& sv_label = sv_adjacency_list_[sv_vertex_id];
if (!processed_[sv_label])
{
// Add neighbors (and their neighbors etc.) to group if similarity constraint is met
recursiveGrouping (sv_vertex_id, segment_label);
recursiveSegmentGrowing (sv_vertex_id, segment_label);
++segment_label; // After recursive grouping ended (no more neighbors to consider) -> go to next group
}
}
grouping_data_valid_ = true;
}

template <typename PointT> void
pcl::LCCPSegmentation<PointT>::recursiveGrouping (VertexID const &query_point_id,
unsigned int const segment_label)
pcl::LCCPSegmentation<PointT>::recursiveSegmentGrowing (VertexID const &query_point_id,
unsigned int const segment_label)
{
const uint32_t sv_label = sv_adjacency_list_[query_point_id];
const uint32_t& sv_label = sv_adjacency_list_[query_point_id];

processed_[sv_label] = true;

Expand All @@ -324,13 +341,13 @@ pcl::LCCPSegmentation<PointT>::recursiveGrouping (VertexID const &query_point_id
for (OutEdgeIterator out_Edge_itr = out_edge_iterator_range.first; out_Edge_itr != out_edge_iterator_range.second; ++out_Edge_itr)
{
const VertexID neighbor_ID = boost::target (*out_Edge_itr, sv_adjacency_list_);
const uint32_t neighbor_label = sv_adjacency_list_[neighbor_ID];
const uint32_t& neighbor_label = sv_adjacency_list_[neighbor_ID];

if (!processed_[neighbor_label]) // If neighbor was not already processed
{
if (sv_adjacency_list_[*out_Edge_itr].is_convex)
if (sv_adjacency_list_[*out_Edge_itr].is_valid)
{
recursiveGrouping (neighbor_ID, segment_label);
recursiveSegmentGrowing (neighbor_ID, segment_label);
}
}
} // End neighbor loop
Expand Down Expand Up @@ -397,7 +414,7 @@ pcl::LCCPSegmentation<PointT>::applyKconvexity (unsigned int k_arg)

// Check k convexity
if (kcount < k_arg)
(sv_adjacency_list_)[*edge_itr].is_convex = false;
(sv_adjacency_list_)[*edge_itr].is_valid = false;
}
}
}
Expand All @@ -417,14 +434,18 @@ pcl::LCCPSegmentation<PointT>::calculateConvexConnections (SupervoxelAdjacencyLi
uint32_t source_sv_label = adjacency_list_arg[boost::source (*edge_itr, adjacency_list_arg)];
uint32_t target_sv_label = adjacency_list_arg[boost::target (*edge_itr, adjacency_list_arg)];

is_convex = connIsConvex (source_sv_label, target_sv_label);
float normal_difference;
is_convex = connIsConvex (source_sv_label, target_sv_label, normal_difference);
adjacency_list_arg[*edge_itr].is_convex = is_convex;
adjacency_list_arg[*edge_itr].is_valid = is_convex;
adjacency_list_arg[*edge_itr].normal_difference = normal_difference;
}
}

template <typename PointT> bool
pcl::LCCPSegmentation<PointT>::connIsConvex (uint32_t source_label_arg,
uint32_t target_label_arg)
uint32_t target_label_arg,
float &normal_angle)
{
typename pcl::Supervoxel<PointT>::Ptr& sv_source = sv_label_to_supervoxel_map_[source_label_arg];
typename pcl::Supervoxel<PointT>::Ptr& sv_target = sv_label_to_supervoxel_map_[target_label_arg];
Expand All @@ -444,7 +465,7 @@ pcl::LCCPSegmentation<PointT>::connIsConvex (uint32_t source_label_arg,
bool is_convex = true;
bool is_smooth = true;

float normal_angle = getAngle3D (source_normal, target_normal, true);
normal_angle = getAngle3D (source_normal, target_normal, true);
// Geometric comparisons
Eigen::Vector3f vec_t_to_s, vec_s_to_t;

Expand Down
33 changes: 26 additions & 7 deletions segmentation/include/pcl/segmentation/lccp_segmentation.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,20 @@ namespace pcl
/** \brief Edge Properties stored in the adjacency graph.*/
struct EdgeProperties
{
/** \brief Desribes the difference of normals of the two supervoxels being connected*/
float normal_difference;

/** \brief Desribes if a connection is convex or concave*/
bool is_convex;

/** \brief Describes if a connection is valid for the segment growing. Usually convex connections are and concave connection are not. Due to k-concavity a convex connection can be invalidated*/
bool is_valid;

/** \brief Additional member used for the CPC algorithm. If edge has already induced a cut, it should be ignored for further cutting.*/
bool used_for_cutting;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing description here. Also missing c in "Desribes" above.


EdgeProperties () :
is_convex (false)
normal_difference (0), is_convex (false), is_valid (false), used_for_cutting (false)
{
}
};
Expand Down Expand Up @@ -204,7 +215,7 @@ namespace pcl
k_factor_ = k;
}

private:
protected:

/** \brief Compute the adjacency of the segments */
void
Expand All @@ -217,12 +228,18 @@ namespace pcl
prepareSegmentation (const std::map<uint32_t, typename pcl::Supervoxel<PointT>::Ptr> &supervoxel_clusters_arg,
const std::multimap<uint32_t, uint32_t> &label_adjacency_arg);


/** Perform depth search on the graph and recursively group all supervoxels with convex connections
* \note The vertices in the supervoxel adjacency list are the supervoxel centroids */
void
doGrouping ();

/** \brief Assigns neighbors of the query point to the same group as the query point. Recursive part of groupSupervoxels (..). Grouping is done by a depth-search of nodes in the adjacency-graph.
* \param[in] queryPointID ID of point whose neighbors will be considered for grouping
* \param[in] group_label ID of the group/segment the queried point belongs to */
void
recursiveGrouping (VertexID const &queryPointID,
unsigned int const group_label);
recursiveSegmentGrowing (VertexID const &queryPointID,
unsigned int const group_label);

/** \brief Calculates convexity of edges and saves this to the adjacency graph.
* \param[in] adjacency_list_arg The supervoxel adjacency list*/
Expand All @@ -237,10 +254,12 @@ namespace pcl
/** \brief Returns true if the connection between source and target is convex.
* \param[in] source_label_arg Label of one Supervoxel connected to the edge that should be checked
* \param[in] target_label_arg Label of the other Supervoxel connected to the edge that should be checked
* \param[out] normal_angle The angle between source and target
* \return True if connection is convex */
bool
connIsConvex (uint32_t source_label_arg,
uint32_t target_label_arg);
uint32_t target_label_arg,
float &normal_angle);

/// *** Parameters *** ///

Expand All @@ -266,7 +285,7 @@ namespace pcl
float voxel_resolution_;

/** \brief Factor used for k-convexity */
unsigned int k_factor_;
uint32_t k_factor_;

/** \brief Stores which SuperVoxel labels were already visited during recursive grouping. processed_[sv_Label] = false (default)/true (already processed) */
std::map<uint32_t, bool> processed_;
Expand All @@ -283,7 +302,7 @@ namespace pcl
/** \brief map <Segment Label, std::set <SuperVoxel Labels> > */
std::map<uint32_t, std::set<uint32_t> > seg_label_to_sv_list_map_;

/** \brief map <SegmentID, std::vector <Neighboring segment labels> > */
/** \brief map < SegmentID, std::set< Neighboring segment labels> > */
std::map<uint32_t, std::set<uint32_t> > seg_label_to_neighbor_set_map_;

};
Expand Down