Loading...
Searching...
No Matches
cpc_segmentation.h
/*
* Software License Agreement (BSD License)
*
* Point Cloud Library (PCL) - www.pointclouds.org
* Copyright (c) 2014-, Open Perception, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of the copyright holder(s) nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#pragma once
// common includes
#include <pcl/pcl_base.h>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
// segmentation and sample consensus includes
#include <pcl/segmentation/supervoxel_clustering.h>
#include <pcl/segmentation/lccp_segmentation.h>
#include <pcl/sample_consensus/sac.h>
#include <pcl/segmentation/extract_clusters.h>
#define PCL_INSTANTIATE_CPCSegmentation(T) template class PCL_EXPORTS pcl::CPCSegmentation<T>;
namespace pcl
{
/** \brief A segmentation algorithm partitioning a supervoxel graph. It uses planar cuts induced by local concavities for the recursive segmentation. Cuts are estimated using locally constrained directed RANSAC.
* \note If you use this in a scientific work please cite the following paper:
* M. Schoeler, J. Papon, F. Woergoetter
* Constrained Planar Cuts - Object Partitioning for Point Clouds
* In Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition (CVPR) 2015
* Inherits most of its functionality from \ref LCCPSegmentation
* \author Markus Schoeler (mschoeler@web.de)
* \ingroup segmentation
*/
template <typename PointT>
class CPCSegmentation : public LCCPSegmentation<PointT>
{
using WeightSACPointType = PointXYZINormal;
using LCCP = LCCPSegmentation<PointT>;
// LCCP typedefs
using EdgeID = typename LCCP::EdgeID;
using EdgeIterator = typename LCCP::EdgeIterator;
// LCCP methods
using LCCP::calculateConvexConnections;
using LCCP::applyKconvexity;
using LCCP::doGrouping;
using LCCP::mergeSmallSegments;
// LCCP variables
using LCCP::sv_adjacency_list_;
using LCCP::k_factor_;
using LCCP::grouping_data_valid_;
using LCCP::sv_label_to_seg_label_map_;
using LCCP::sv_label_to_supervoxel_map_;
using LCCP::concavity_tolerance_threshold_;
using LCCP::seed_resolution_;
using LCCP::supervoxels_set_;
public:
CPCSegmentation ();
~CPCSegmentation () override;
/** \brief Merge supervoxels using cuts through local convexities. The input parameters are generated by using the \ref SupervoxelClustering class. To retrieve the output use the \ref relabelCloud method.
* \note There are three ways to retrieve the segmentation afterwards (inherited from \ref LCCPSegmentation): \ref relabelCloud, \ref getSupervoxelToSegmentMap and \ref getSupervoxelToSegmentMap */
void
segment ();
/** \brief Determines if we want to use cutting planes
* \param[in] max_cuts Maximum number of cuts
* \param[in] cutting_min_segments Minimum segment size for cutting
* \param[in] cutting_min_score Minimum score a proposed cut has to achieve for being performed
* \param[in] locally_constrained Decide if we constrain our cuts locally
* \param[in] directed_cutting Decide if we prefer cuts perpendicular to the edge-direction
* \param[in] clean_cutting Decide if we cut only edges with supervoxels on opposite sides of the plane (clean) or all edges within the seed_resolution_ distance to the plane (not clean). The later was used in the paper.
*/
inline void
setCutting (const std::uint32_t max_cuts = 20,
const std::uint32_t cutting_min_segments = 0,
const float cutting_min_score = 0.16,
const bool locally_constrained = true,
const bool directed_cutting = true,
const bool clean_cutting = false)
{
max_cuts_ = max_cuts;
min_segment_size_for_cutting_ = cutting_min_segments;
min_cut_score_ = cutting_min_score;
use_local_constrains_ = locally_constrained;
use_directed_weights_ = directed_cutting;
use_clean_cutting_ = clean_cutting;
}
/** \brief Set the number of iterations for the weighted RANSAC step (best cut estimations)
* \param[in] ransac_iterations The number of iterations */
inline void
setRANSACIterations (const std::uint32_t ransac_iterations)
{
ransac_itrs_ = ransac_iterations;
}
private:
/** \brief Used in for CPC to find and fit cutting planes to the pointcloud.
* \note Is used recursively
* \param[in] depth_levels_left When first calling the function set this parameter to the maximum levels you want to cut down */
void
applyCuttingPlane (std::uint32_t depth_levels_left);
/// *** Parameters *** ///
/** \brief Maximum number of cuts */
std::uint32_t max_cuts_{20};
/** \brief Minimum segment size for cutting */
std::uint32_t min_segment_size_for_cutting_{400};
/** \brief Cut_score threshold */
float min_cut_score_{0.16};
/** \brief Use local constrains for cutting */
bool use_local_constrains_{true};
/** \brief Use directed weights for the cutting */
bool use_directed_weights_{true};
/** \brief Use clean cutting */
bool use_clean_cutting_{false};
/** \brief Iterations for RANSAC */
std::uint32_t ransac_itrs_{10000};
/******************************************* Directional weighted RANSAC declarations ******************************************************************/
/** \brief @b WeightedRandomSampleConsensus represents an implementation of the Directionally Weighted RANSAC algorithm, as described in: "Constrained Planar Cuts - Part Segmentation for Point Clouds", CVPR 2015, M. Schoeler, J. Papon, F. Wörgötter.
* \note It only uses points with a weight > 0 for the model calculation, but uses all points for the evaluation (scoring of the model)
* Only use in conjunction with sac_model_plane
* If you use this in a scientific work please cite the following paper:
* M. Schoeler, J. Papon, F. Woergoetter
* Constrained Planar Cuts - Object Partitioning for Point Clouds
* In Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition (CVPR) 2015
* \author Markus Schoeler (mschoeler@web.de)
* \ingroup segmentation
*/
class WeightedRandomSampleConsensus : public SampleConsensus<WeightSACPointType>
{
using SampleConsensusModelPtr = SampleConsensusModel<WeightSACPointType>::Ptr;
public:
using Ptr = shared_ptr<WeightedRandomSampleConsensus>;
using ConstPtr = shared_ptr<const WeightedRandomSampleConsensus>;
/** \brief WeightedRandomSampleConsensus (Weighted RAndom SAmple Consensus) main constructor
* \param[in] model a Sample Consensus model
* \param[in] random if true set the random seed to the current time, else set to 12345 (default: false)
*/
WeightedRandomSampleConsensus (const SampleConsensusModelPtr &model,
bool random = false)
: SampleConsensus<WeightSACPointType> (model, random)
{
initialize ();
}
/** \brief WeightedRandomSampleConsensus (Weighted RAndom SAmple Consensus) main constructor
* \param[in] model a Sample Consensus model
* \param[in] threshold distance to model threshold
* \param[in] random if true set the random seed to the current time, else set to 12345 (default: false)
*/
WeightedRandomSampleConsensus (const SampleConsensusModelPtr &model,
double threshold,
bool random = false)
: SampleConsensus<WeightSACPointType> (model, threshold, random)
{
initialize ();
}
/** \brief Compute the actual model and find the inliers
* \param[in] debug_verbosity_level enable/disable on-screen debug information and set the verbosity level
*/
bool
computeModel (int debug_verbosity_level = 0) override;
/** \brief Set the weights for the input points
* \param[in] weights Weights for input samples. Negative weights are counted as penalty.
*/
void
setWeights (const std::vector<double> &weights,
const bool directed_weights = false)
{
if (weights.size () != full_cloud_pt_indices_->size ())
{
PCL_ERROR ("[pcl::WeightedRandomSampleConsensus::setWeights] Cannot assign weights. Weight vector needs to have the same length as the input pointcloud\n");
return;
}
weights_ = weights;
model_pt_indices_->clear ();
for (std::size_t i = 0; i < weights.size (); ++i)
{
if (weights[i] > std::numeric_limits<double>::epsilon ())
model_pt_indices_->push_back (i);
}
use_directed_weights_ = directed_weights;
}
/** \brief Get the best score
* \returns The best score found.
*/
double
getBestScore () const
{
return (best_score_);
}
protected:
/** \brief Initialize the model parameters. Called by the constructors. */
void
initialize ()
{
// Maximum number of trials before we give up.
max_iterations_ = 10000;
use_directed_weights_ = false;
model_pt_indices_.reset (new Indices);
full_cloud_pt_indices_.reset (new Indices (* (sac_model_->getIndices ())));
point_cloud_ptr_ = sac_model_->getInputCloud ();
}
/** \brief weight each positive weight point by the inner product between the normal and the plane normal */
bool use_directed_weights_;
/** \brief vector of weights assigned to points. Set by the setWeights-method */
std::vector<double> weights_;
/** \brief The indices used for estimating the RANSAC model. Only those whose weight is > 0 */
pcl::IndicesPtr model_pt_indices_;
/** \brief The complete list of indices used for the model evaluation */
pcl::IndicesPtr full_cloud_pt_indices_;
/** \brief Pointer to the input PointCloud */
pcl::PointCloud<WeightSACPointType>::ConstPtr point_cloud_ptr_;
/** \brief Highest score found so far */
double best_score_;
};
};
}
#ifdef PCL_NO_PRECOMPILE
#include <pcl/segmentation/impl/cpc_segmentation.hpp>
#elif defined(PCL_ONLY_CORE_POINT_TYPES)
//pcl::PointXYZINormal is not a core point type (so we cannot use the precompiled classes here)
#include <pcl/sample_consensus/impl/sac_model_plane.hpp>
#include <pcl/segmentation/impl/extract_clusters.hpp>
#endif // PCL_NO_PRECOMPILE / PCL_ONLY_CORE_POINT_TYPES
pcl::CPCSegmentation
A segmentation algorithm partitioning a supervoxel graph.
Definition cpc_segmentation.h:67
pcl::CPCSegmentation::segment
void segment()
Merge supervoxels using cuts through local convexities.
Definition cpc_segmentation.hpp:51
pcl::CPCSegmentation::CPCSegmentation
CPCSegmentation()
pcl::CPCSegmentation::~CPCSegmentation
~CPCSegmentation() override
pcl::CPCSegmentation::setCutting
void setCutting(const std::uint32_t max_cuts=20, const std::uint32_t cutting_min_segments=0, const float cutting_min_score=0.16, const bool locally_constrained=true, const bool directed_cutting=true, const bool clean_cutting=false)
Determines if we want to use cutting planes.
Definition cpc_segmentation.h:107
pcl::CPCSegmentation::setRANSACIterations
void setRANSACIterations(const std::uint32_t ransac_iterations)
Set the number of iterations for the weighted RANSAC step (best cut estimations)
Definition cpc_segmentation.h:125
pcl::LCCPSegmentation
A simple segmentation algorithm partitioning a supervoxel graph into groups of locally convex connect...
Definition lccp_segmentation.h:58
pcl::LCCPSegmentation::supervoxels_set_
bool supervoxels_set_
Marks if supervoxels have been set by calling setInputSupervoxels.
Definition lccp_segmentation.h:303
pcl::LCCPSegmentation::sv_label_to_seg_label_map_
std::map< std::uint32_t, std::uint32_t > sv_label_to_seg_label_map_
Storing relation between original SuperVoxel Labels and new segmantion labels.
Definition lccp_segmentation.h:338
pcl::LCCPSegmentation::EdgeIterator
typename boost::graph_traits< SupervoxelAdjacencyList >::edge_iterator EdgeIterator
Definition lccp_segmentation.h:85
pcl::LCCPSegmentation::grouping_data_valid_
bool grouping_data_valid_
Marks if valid grouping data (sv_adjacency_list_, sv_label_to_seg_label_map_, processed_) is availabl...
Definition lccp_segmentation.h:300
pcl::LCCPSegmentation::k_factor_
std::uint32_t k_factor_
Factor used for k-convexity.
Definition lccp_segmentation.h:321
pcl::LCCPSegmentation::calculateConvexConnections
void calculateConvexConnections(SupervoxelAdjacencyList &adjacency_list_arg)
Calculates convexity of edges and saves this to the adjacency graph.
Definition lccp_segmentation.hpp:396
pcl::LCCPSegmentation::mergeSmallSegments
void mergeSmallSegments()
Segments smaller than min_segment_size_ are merged to the label of largest neighbor.
Definition lccp_segmentation.hpp:154
pcl::LCCPSegmentation::concavity_tolerance_threshold_
float concavity_tolerance_threshold_
*** Parameters *** ///
Definition lccp_segmentation.h:297
pcl::LCCPSegmentation::seed_resolution_
float seed_resolution_
Seed resolution of the supervoxels (used only for smoothness check)
Definition lccp_segmentation.h:315
pcl::LCCPSegmentation::doGrouping
void doGrouping()
Perform depth search on the graph and recursively group all supervoxels with convex connections.
Definition lccp_segmentation.hpp:278
pcl::LCCPSegmentation::applyKconvexity
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.
Definition lccp_segmentation.hpp:339
pcl::LCCPSegmentation::sv_adjacency_list_
SupervoxelAdjacencyList sv_adjacency_list_
Adjacency graph with the supervoxel labels as nodes and edges between adjacent supervoxels.
Definition lccp_segmentation.h:331
pcl::LCCPSegmentation::EdgeID
typename boost::graph_traits< SupervoxelAdjacencyList >::edge_descriptor EdgeID
Definition lccp_segmentation.h:87
pcl::LCCPSegmentation::sv_label_to_supervoxel_map_
std::map< std::uint32_t, typename pcl::Supervoxel< PointT >::Ptr > sv_label_to_supervoxel_map_
map from the supervoxel labels to the supervoxel objects
Definition lccp_segmentation.h:334
pcl::PointCloud::ConstPtr
shared_ptr< const PointCloud< PointT > > ConstPtr
Definition point_cloud.h:414
pcl::SampleConsensus< WeightSACPointType >::sac_model_
SampleConsensusModelPtr sac_model_
The underlying data model used (i.e.
Definition sac.h:320
pcl::SampleConsensus< WeightSACPointType >::max_iterations_
int max_iterations_
Maximum number of iterations before giving up.
Definition sac.h:341
pcl::SampleConsensus< WeightSACPointType >::SampleConsensus
SampleConsensus(const SampleConsensusModelPtr &model, bool random=false)
Constructor for base SAC.
Definition sac.h:77
point_types.h
Defines all the PCL implemented PointT point type structures.
pcl
Definition convolution.h:46
pcl::Indices
IndicesAllocator<> Indices
Type used for indices in PCL.
Definition types.h:133
pcl::IndicesPtr
shared_ptr< Indices > IndicesPtr
Definition pcl_base.h:58
pcl::PointXYZINormal
A point structure representing Euclidean xyz coordinates, intensity, together with normal coordinates...
Definition point_types.hpp:972