Point Cloud Library (PCL)  1.7.0
conditional_euclidean_clustering.h
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2010-2011, Willow Garage, Inc.
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of the copyright holder(s) nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  */
37 
38 #ifndef PCL_SEGMENTATION_CONDITIONAL_EUCLIDEAN_CLUSTERING_H_
39 #define PCL_SEGMENTATION_CONDITIONAL_EUCLIDEAN_CLUSTERING_H_
40 
41 #include <pcl/pcl_base.h>
42 #include <pcl/search/pcl_search.h>
43 
44 namespace pcl
45 {
46  typedef std::vector<pcl::PointIndices> IndicesClusters;
47  typedef boost::shared_ptr<std::vector<pcl::PointIndices> > IndicesClustersPtr;
48 
49  /** \brief @b ConditionalEuclideanClustering performs segmentation based on Euclidean distance and a user-defined clustering condition.
50  * \details The condition that need to hold is currently passed using a function pointer.
51  * For more information check the documentation of setConditionFunction() or the usage example below:
52  * \code
53  * bool
54  * enforceIntensitySimilarity (const pcl::PointXYZI& point_a, const pcl::PointXYZI& point_b, float squared_distance)
55  * {
56  * if (fabs (point_a.intensity - point_b.intensity) < 0.1f)
57  * return (true);
58  * else
59  * return (false);
60  * }
61  * // ...
62  * // Somewhere down to the main code
63  * // ...
64  * pcl::ConditionalEuclideanClustering<pcl::PointXYZI> cec (true);
65  * cec.setInputCloud (cloud_in);
66  * cec.setConditionFunction (&enforceIntensitySimilarity);
67  * // Points within this distance from one another are going to need to validate the enforceIntensitySimilarity function to be part of the same cluster:
68  * cec.setClusterTolerance (0.09f);
69  * // Size constraints for the clusters:
70  * cec.setMinClusterSize (5);
71  * cec.setMaxClusterSize (30);
72  * // The resulting clusters (an array of pointindices):
73  * cec.segment (*clusters);
74  * // The clusters that are too small or too large in size can also be extracted separately:
75  * cec.getRemovedClusters (small_clusters, large_clusters);
76  * \endcode
77  * \author Frits Florentinus
78  * \ingroup segmentation
79  */
80  template<typename PointT>
81  class ConditionalEuclideanClustering : public PCLBase<PointT>
82  {
83  protected:
85 
90 
91  public:
92  /** \brief Constructor.
93  * \param[in] extract_removed_clusters Set to true if you want to be able to extract the clusters that are too large or too small (default = false)
94  */
95  ConditionalEuclideanClustering (bool extract_removed_clusters = false) :
96  searcher_ (),
97  condition_function_ (),
98  cluster_tolerance_ (0.0f),
99  min_cluster_size_ (1),
100  max_cluster_size_ (std::numeric_limits<int>::max ()),
101  extract_removed_clusters_ (extract_removed_clusters),
102  small_clusters_ (new pcl::IndicesClusters),
103  large_clusters_ (new pcl::IndicesClusters)
104  {
105  }
106 
107  /** \brief Set the condition that needs to hold for neighboring points to be considered part of the same cluster.
108  * \details Any two points within a certain distance from one another will need to evaluate this condition in order to be made part of the same cluster.
109  * The distance can be set using setClusterTolerance().
110  * <br>
111  * Note that for a point to be part of a cluster, the condition only needs to hold for at least 1 point pair.
112  * To clarify, the following statement is false:
113  * Any two points within a cluster always evaluate this condition function to true.
114  * <br><br>
115  * The input arguments of the condition function are:
116  * <ul>
117  * <li>PointT The first point of the point pair</li>
118  * <li>PointT The second point of the point pair</li>
119  * <li>float The squared distance between the points</li>
120  * </ul>
121  * The output argument is a boolean, returning true will merge the second point into the cluster of the first point.
122  * \param[in] condition_function The condition function that needs to hold for clustering
123  */
124  inline void
125  setConditionFunction (bool (*condition_function) (const PointT&, const PointT&, float))
126  {
127  condition_function_ = condition_function;
128  }
129 
130  /** \brief Set the spatial tolerance for new cluster candidates.
131  * \details Any two points within this distance from one another will need to evaluate a certain condition in order to be made part of the same cluster.
132  * The condition can be set using setConditionFunction().
133  * \param[in] cluster_tolerance The distance to scan for cluster candidates (default = 0.0)
134  */
135  inline void
136  setClusterTolerance (float cluster_tolerance)
137  {
138  cluster_tolerance_ = cluster_tolerance;
139  }
140 
141  /** \brief Get the spatial tolerance for new cluster candidates.*/
142  inline float
144  {
145  return (cluster_tolerance_);
146  }
147 
148  /** \brief Set the minimum number of points that a cluster needs to contain in order to be considered valid.
149  * \param[in] min_cluster_size The minimum cluster size (default = 1)
150  */
151  inline void
152  setMinClusterSize (int min_cluster_size)
153  {
154  min_cluster_size_ = min_cluster_size;
155  }
156 
157  /** \brief Get the minimum number of points that a cluster needs to contain in order to be considered valid.*/
158  inline int
160  {
161  return (min_cluster_size_);
162  }
163 
164  /** \brief Set the maximum number of points that a cluster needs to contain in order to be considered valid.
165  * \param[in] max_cluster_size The maximum cluster size (default = unlimited)
166  */
167  inline void
168  setMaxClusterSize (int max_cluster_size)
169  {
170  max_cluster_size_ = max_cluster_size;
171  }
172 
173  /** \brief Get the maximum number of points that a cluster needs to contain in order to be considered valid.*/
174  inline int
176  {
177  return (max_cluster_size_);
178  }
179 
180  /** \brief Segment the input into separate clusters.
181  * \details The input can be set using setInputCloud() and setIndices().
182  * <br>
183  * The size constraints for the resulting clusters can be set using setMinClusterSize() and setMaxClusterSize().
184  * <br>
185  * The region growing parameters can be set using setConditionFunction() and setClusterTolerance().
186  * <br>
187  * \param[out] clusters The resultant set of indices, indexing the points of the input cloud that correspond to the clusters
188  */
189  void
190  segment (IndicesClusters &clusters);
191 
192  /** \brief Get the clusters that are invalidated due to size constraints.
193  * \note The constructor of this class needs to be initialized with true, and the segment method needs to have been called prior to using this method.
194  * \param[out] small_clusters The resultant clusters that contain less than min_cluster_size points
195  * \param[out] large_clusters The resultant clusters that contain more than max_cluster_size points
196  */
197  inline void
198  getRemovedClusters (IndicesClustersPtr &small_clusters, IndicesClustersPtr &large_clusters)
199  {
200  if (!extract_removed_clusters_)
201  {
202  PCL_WARN("[pcl::ConditionalEuclideanClustering::getRemovedClusters] You need to set extract_removed_clusters to true (in this class' constructor) if you want to use this functionality.\n");
203  return;
204  }
205  small_clusters = small_clusters_;
206  large_clusters = large_clusters_;
207  }
208 
209  private:
210  /** \brief A pointer to the spatial search object */
211  SearcherPtr searcher_;
212 
213  /** \brief The condition function that needs to hold for clustering */
214  bool (*condition_function_) (const PointT&, const PointT&, float);
215 
216  /** \brief The distance to scan for cluster candidates (default = 0.0) */
217  float cluster_tolerance_;
218 
219  /** \brief The minimum cluster size (default = 1) */
220  int min_cluster_size_;
221 
222  /** \brief The maximum cluster size (default = unlimited) */
223  int max_cluster_size_;
224 
225  /** \brief Set to true if you want to be able to extract the clusters that are too large or too small (default = false) */
226  bool extract_removed_clusters_;
227 
228  /** \brief The resultant clusters that contain less than min_cluster_size points */
229  pcl::IndicesClustersPtr small_clusters_;
230 
231  /** \brief The resultant clusters that contain more than max_cluster_size points */
232  pcl::IndicesClustersPtr large_clusters_;
233 
234  public:
235  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
236  };
237 }
238 
239 #ifdef PCL_NO_PRECOMPILE
240 #include <pcl/segmentation/impl/conditional_euclidean_clustering.hpp>
241 #endif
242 
243 #endif // PCL_SEGMENTATION_CONDITIONAL_EUCLIDEAN_CLUSTERING_H_
244