40#ifndef PCL_SEGMENTATION_IMPL_ORGANIZED_MULTI_PLANE_SEGMENTATION_H_
41#define PCL_SEGMENTATION_IMPL_ORGANIZED_MULTI_PLANE_SEGMENTATION_H_
43#include <pcl/segmentation/organized_connected_component_segmentation.h>
44#include <pcl/segmentation/organized_multi_plane_segmentation.h>
46#include <pcl/common/eigen.h>
50projectToPlaneFromViewpoint (
pcl::PointCloud<PointT>& cloud, Eigen::Vector4f& normal, Eigen::Vector3f& centroid, Eigen::Vector3f& vp)
52 Eigen::Vector3f
norm (normal[0], normal[1], normal[2]);
55 for (std::size_t i = 0; i < cloud.
size (); i++)
57 Eigen::Vector3f pt (cloud[i].x, cloud[i].y, cloud[i].z);
59 float u =
norm.dot ((centroid - vp)) /
norm.dot ((pt - vp));
60 Eigen::Vector3f intersection (vp + u * (pt - vp));
61 projected_cloud[i].x = intersection[0];
62 projected_cloud[i].y = intersection[1];
63 projected_cloud[i].z = intersection[2];
66 return (projected_cloud);
70template<
typename Po
intT,
typename Po
intNT,
typename Po
intLT>
void
72 std::vector<PointIndices>& inlier_indices)
75 std::vector<pcl::PointIndices> label_indices;
76 std::vector<Eigen::Vector4f, Eigen::aligned_allocator<Eigen::Vector4f> > centroids;
77 std::vector <Eigen::Matrix3f, Eigen::aligned_allocator<Eigen::Matrix3f> > covariances;
78 segment (model_coefficients, inlier_indices, centroids, covariances, labels, label_indices);
82template<
typename Po
intT,
typename Po
intNT,
typename Po
intLT>
void
84 std::vector<PointIndices>& inlier_indices,
85 std::vector<Eigen::Vector4f, Eigen::aligned_allocator<Eigen::Vector4f> >& centroids,
86 std::vector <Eigen::Matrix3f, Eigen::aligned_allocator<Eigen::Matrix3f> >& covariances,
88 std::vector<pcl::PointIndices>& label_indices)
96 PCL_ERROR(
"[pcl::%s::segment] Must specify normals.\n",
getClassName().c_str());
103 PCL_ERROR(
"[pcl::%s::segment] Number of points in input cloud (%zu) and normal "
104 "cloud (%zu) do not match!\n",
106 static_cast<std::size_t
>(
input_->size()),
107 static_cast<std::size_t
>(
normals_->size()));
112 if (!
input_->isOrganized ())
114 PCL_ERROR (
"[pcl::%s::segment] Organized point cloud is required for this plane extraction method!\n",
120 std::vector<float> plane_d (
input_->size ());
122 for (std::size_t i = 0; i <
input_->size (); ++i)
123 plane_d[i] = (*
input_)[i].getVector3fMap ().dot ((*
normals_)[i].getNormalVector3fMap ());
136 connected_component.
segment (labels, label_indices);
138 Eigen::Vector4f clust_centroid = Eigen::Vector4f::Zero ();
139 Eigen::Vector4f vp = Eigen::Vector4f::Zero ();
140 Eigen::Matrix3f clust_cov;
145 for (
const auto &label_index : label_indices)
147 if (
static_cast<unsigned> (label_index.indices.size ()) >
min_inliers_)
150 Eigen::Vector4f plane_params;
152 EIGEN_ALIGN16 Eigen::Vector3f::Scalar eigen_value;
153 EIGEN_ALIGN16 Eigen::Vector3f eigen_vector;
155 plane_params[0] = eigen_vector[0];
156 plane_params[1] = eigen_vector[1];
157 plane_params[2] = eigen_vector[2];
159 plane_params[3] = -1 * plane_params.dot (clust_centroid);
161 vp -= clust_centroid;
162 float cos_theta = vp.dot (plane_params);
167 plane_params[3] = -1 * plane_params.dot (clust_centroid);
172 float eig_sum = clust_cov.coeff (0) + clust_cov.coeff (4) + clust_cov.coeff (8);
174 curvature = std::abs (eigen_value / eig_sum);
180 model.
values[0] = plane_params[0];
181 model.
values[1] = plane_params[1];
182 model.
values[2] = plane_params[2];
183 model.
values[3] = plane_params[3];
184 model_coefficients.push_back (model);
185 inlier_indices.push_back (label_index);
186 centroids.push_back (clust_centroid);
187 covariances.push_back (clust_cov);
195template<
typename Po
intT,
typename Po
intNT,
typename Po
intLT>
void
198 std::vector<ModelCoefficients> model_coefficients;
199 std::vector<PointIndices> inlier_indices;
201 std::vector<pcl::PointIndices> label_indices;
202 std::vector<pcl::PointIndices> boundary_indices;
204 std::vector<Eigen::Vector4f, Eigen::aligned_allocator<Eigen::Vector4f> > centroids;
205 std::vector <Eigen::Matrix3f, Eigen::aligned_allocator<Eigen::Matrix3f> > covariances;
206 segment (model_coefficients, inlier_indices, centroids, covariances, *labels, label_indices);
207 regions.resize (model_coefficients.size ());
208 boundary_indices.resize (model_coefficients.size ());
210 for (std::size_t i = 0; i < model_coefficients.size (); i++)
212 boundary_cloud.
resize (0);
214 boundary_cloud.
resize (boundary_indices[i].indices.size ());
215 for (std::size_t j = 0; j < boundary_indices[i].indices.size (); j++)
216 boundary_cloud[j] = (*
input_)[boundary_indices[i].indices[j]];
218 Eigen::Vector3f centroid = Eigen::Vector3f (centroids[i][0],centroids[i][1],centroids[i][2]);
219 Eigen::Vector4f model = Eigen::Vector4f (model_coefficients[i].values[0],
220 model_coefficients[i].values[1],
221 model_coefficients[i].values[2],
222 model_coefficients[i].values[3]);
225 static_cast<unsigned int> (inlier_indices[i].indices.size ()),
232template<
typename Po
intT,
typename Po
intNT,
typename Po
intLT>
void
235 std::vector<ModelCoefficients> model_coefficients;
236 std::vector<PointIndices> inlier_indices;
238 std::vector<pcl::PointIndices> label_indices;
239 std::vector<pcl::PointIndices> boundary_indices;
241 std::vector<Eigen::Vector4f, Eigen::aligned_allocator<Eigen::Vector4f> > centroids;
242 std::vector <Eigen::Matrix3f, Eigen::aligned_allocator<Eigen::Matrix3f> > covariances;
243 segment (model_coefficients, inlier_indices, centroids, covariances, *labels, label_indices);
244 refine (model_coefficients, inlier_indices, labels, label_indices);
245 regions.resize (model_coefficients.size ());
246 boundary_indices.resize (model_coefficients.size ());
248 for (std::size_t i = 0; i < model_coefficients.size (); i++)
250 boundary_cloud.
resize (0);
251 int max_inlier_idx =
static_cast<int> (inlier_indices[i].indices.size ()) - 1;
253 boundary_cloud.
resize (boundary_indices[i].indices.size ());
254 for (std::size_t j = 0; j < boundary_indices[i].indices.size (); j++)
255 boundary_cloud[j] = (*
input_)[boundary_indices[i].indices[j]];
257 Eigen::Vector3f centroid = Eigen::Vector3f (centroids[i][0],centroids[i][1],centroids[i][2]);
258 Eigen::Vector4f model = Eigen::Vector4f (model_coefficients[i].values[0],
259 model_coefficients[i].values[1],
260 model_coefficients[i].values[2],
261 model_coefficients[i].values[3]);
263 Eigen::Vector3f vp (0.0, 0.0, 0.0);
265 boundary_cloud = projectToPlaneFromViewpoint (boundary_cloud, model, centroid, vp);
269 static_cast<unsigned int> (inlier_indices[i].indices.size ()),
276template<
typename Po
intT,
typename Po
intNT,
typename Po
intLT>
void
278 std::vector<ModelCoefficients>& model_coefficients,
279 std::vector<PointIndices>& inlier_indices,
281 std::vector<pcl::PointIndices>& label_indices,
282 std::vector<pcl::PointIndices>& boundary_indices)
285 std::vector<Eigen::Vector4f, Eigen::aligned_allocator<Eigen::Vector4f> > centroids;
286 std::vector <Eigen::Matrix3f, Eigen::aligned_allocator<Eigen::Matrix3f> > covariances;
287 segment (model_coefficients, inlier_indices, centroids, covariances, *labels, label_indices);
288 refine (model_coefficients, inlier_indices, labels, label_indices);
289 regions.resize (model_coefficients.size ());
290 boundary_indices.resize (model_coefficients.size ());
292 for (std::size_t i = 0; i < model_coefficients.size (); i++)
294 boundary_cloud.
resize (0);
295 int max_inlier_idx =
static_cast<int> (inlier_indices[i].indices.size ()) - 1;
297 boundary_cloud.
resize (boundary_indices[i].indices.size ());
298 for (std::size_t j = 0; j < boundary_indices[i].indices.size (); j++)
299 boundary_cloud[j] = (*
input_)[boundary_indices[i].indices[j]];
301 Eigen::Vector3f centroid = Eigen::Vector3f (centroids[i][0],centroids[i][1],centroids[i][2]);
302 Eigen::Vector4f model = Eigen::Vector4f (model_coefficients[i].values[0],
303 model_coefficients[i].values[1],
304 model_coefficients[i].values[2],
305 model_coefficients[i].values[3]);
307 Eigen::Vector3f vp (0.0, 0.0, 0.0);
309 boundary_cloud = projectToPlaneFromViewpoint (boundary_cloud, model, centroid, vp);
313 static_cast<unsigned int> (inlier_indices[i].indices.size ()),
320template<
typename Po
intT,
typename Po
intNT,
typename Po
intLT>
void
322 std::vector<PointIndices>& inlier_indices,
324 std::vector<pcl::PointIndices>& label_indices)
327 std::vector<bool> grow_labels;
328 std::vector<int> label_to_model;
329 grow_labels.resize (label_indices.size (),
false);
330 label_to_model.resize (label_indices.size (), 0);
332 for (std::size_t i = 0; i < model_coefficients.size (); i++)
334 int model_label = (*labels)[inlier_indices[i].indices[0]].label;
335 label_to_model[model_label] =
static_cast<int> (i);
336 grow_labels[model_label] =
true;
347 unsigned int current_row = 0;
348 unsigned int next_row = labels->width;
349 for (std::size_t rowIdx = 0; rowIdx < labels->height - 1; ++rowIdx, current_row = next_row, next_row += labels->width)
352 for (
unsigned colIdx = 0; colIdx < labels->width - 1; ++colIdx)
354 int current_label = (*labels)[current_row+colIdx].label;
355 int right_label = (*labels)[current_row+colIdx+1].label;
356 if (current_label < 0 || right_label < 0)
364 (*labels)[current_row+colIdx+1].label = current_label;
365 label_indices[current_label].indices.push_back (current_row+colIdx+1);
366 inlier_indices[label_to_model[current_label]].indices.push_back (current_row+colIdx+1);
369 int lower_label = (*labels)[next_row+colIdx].label;
376 (*labels)[next_row+colIdx].label = current_label;
377 label_indices[current_label].indices.push_back (next_row+colIdx);
378 inlier_indices[label_to_model[current_label]].indices.push_back (next_row+colIdx);
385 current_row = labels->width * (labels->height - 1);
386 unsigned int prev_row = current_row - labels->width;
387 for (std::size_t rowIdx = 0; rowIdx < labels->height - 1; ++rowIdx, current_row = prev_row, prev_row -= labels->width)
389 for (
int colIdx = labels->width - 1; colIdx >= 0; --colIdx)
391 int current_label = (*labels)[current_row+colIdx].label;
392 int left_label = (*labels)[current_row+colIdx-1].label;
393 if (current_label < 0 || left_label < 0)
399 (*labels)[current_row+colIdx-1].label = current_label;
400 label_indices[current_label].indices.push_back (current_row+colIdx-1);
401 inlier_indices[label_to_model[current_label]].indices.push_back (current_row+colIdx-1);
404 int upper_label = (*labels)[prev_row+colIdx].label;
410 (*labels)[prev_row+colIdx].label = current_label;
411 label_indices[current_label].indices.push_back (prev_row+colIdx);
412 inlier_indices[label_to_model[current_label]].indices.push_back (prev_row+colIdx);
418#define PCL_INSTANTIATE_OrganizedMultiPlaneSegmentation(T,NT,LT) template class PCL_EXPORTS pcl::OrganizedMultiPlaneSegmentation<T,NT,LT>;
Define methods for centroid estimation and covariance matrix calculus.
OrganizedConnectedComponentSegmentation allows connected components to be found within organized poin...
static void findLabeledRegionBoundary(int start_idx, PointCloudLPtr labels, pcl::PointIndices &boundary_indices)
Find the boundary points / contour of a connected component.
void segment(pcl::PointCloud< PointLT > &labels, std::vector< pcl::PointIndices > &label_indices) const
Perform the connected component segmentation.
void segment(std::vector< ModelCoefficients > &model_coefficients, std::vector< PointIndices > &inlier_indices, std::vector< Eigen::Vector4f, Eigen::aligned_allocator< Eigen::Vector4f > > ¢roids, std::vector< Eigen::Matrix3f, Eigen::aligned_allocator< Eigen::Matrix3f > > &covariances, pcl::PointCloud< PointLT > &labels, std::vector< pcl::PointIndices > &label_indices)
Segmentation of all planes in a point cloud given by setInputCloud(), setIndices().
PlaneComparatorPtr compare_
A comparator for comparing neighboring pixels' plane equations.
typename PointCloudL::Ptr PointCloudLPtr
double distance_threshold_
The tolerance in meters for difference in perpendicular distance (d component of plane equation) to t...
unsigned min_inliers_
The minimum number of inliers required for each plane.
void segmentAndRefine(std::vector< PlanarRegion< PointT >, Eigen::aligned_allocator< PlanarRegion< PointT > > > ®ions)
Perform a segmentation, as well as an additional refinement step.
pcl::PointCloud< PointLT > PointCloudL
double maximum_curvature_
The tolerance for maximum curvature after fitting a plane.
virtual std::string getClassName() const
Class getName method.
double angular_threshold_
The tolerance in radians for difference in normal direction between neighboring points,...
PointCloudNConstPtr normals_
A pointer to the input normals.
PlaneRefinementComparatorPtr refinement_compare_
A comparator for use on the refinement step.
void refine(std::vector< ModelCoefficients > &model_coefficients, std::vector< PointIndices > &inlier_indices, PointCloudLPtr &labels, std::vector< pcl::PointIndices > &label_indices)
PointCloudConstPtr input_
The input point cloud dataset.
virtual void setInputCloud(const PointCloudConstPtr &cloud)
Provide a pointer to the input dataset.
bool initCompute()
This method should get called before starting the actual computation.
bool deinitCompute()
This method should get called after finishing the actual computation.
PlanarRegion represents a set of points that lie in a plane.
PointCloud represents the base class in PCL for storing collections of 3D points.
void resize(std::size_t count)
Resizes the container to contain count elements.
std::vector< PointT, Eigen::aligned_allocator< PointT > > points
The point data.
unsigned int computeMeanAndCovarianceMatrix(const pcl::PointCloud< PointT > &cloud, Eigen::Matrix< Scalar, 3, 3 > &covariance_matrix, Eigen::Matrix< Scalar, 4, 1 > ¢roid)
Compute the normalized 3x3 covariance matrix and the centroid of a given set of points in a single lo...
void eigen33(const Matrix &mat, typename Matrix::Scalar &eigenvalue, Vector &eigenvector)
determines the eigenvector and eigenvalue of the smallest eigenvalue of the symmetric positive semi d...
__device__ __host__ __forceinline__ float norm(const float3 &v1, const float3 &v2)
std::vector< float > values