00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #ifndef PCL_SEGMENTATION_IMPL_ORGANIZED_MULTI_PLANE_SEGMENTATION_H_
00041 #define PCL_SEGMENTATION_IMPL_ORGANIZED_MULTI_PLANE_SEGMENTATION_H_
00042
00043 #include <pcl/segmentation/organized_connected_component_segmentation.h>
00044 #include <pcl/segmentation/organized_multi_plane_segmentation.h>
00045 #include <pcl/common/centroid.h>
00046 #include <pcl/common/eigen.h>
00047 #include <boost/make_shared.hpp>
00048
00050 Eigen::Vector3f linePlaneIntersection (Eigen::Vector3f& p1, Eigen::Vector3f& p2, Eigen::Vector3f& norm, Eigen::Vector3f& p3)
00051 {
00052 float u = norm.dot ((p3 - p1)) / norm.dot ((p2 - p1));
00053 Eigen::Vector3f intersection (p1 + u * (p2 - p1));
00054 return (intersection);
00055 }
00056
00058 template <typename PointT> pcl::PointCloud<PointT>
00059 projectToPlaneFromViewpoint (pcl::PointCloud<PointT>& cloud, Eigen::Vector4f& normal, Eigen::Vector3f& centroid, Eigen::Vector3f& vp)
00060 {
00061 Eigen::Vector3f norm (normal[0], normal[1], normal[2]);
00062 pcl::PointCloud<PointT> projected_cloud;
00063 projected_cloud.resize (cloud.points.size ());
00064 for (size_t i = 0; i < cloud.points.size (); i++)
00065 {
00066 Eigen::Vector3f pt (cloud.points[i].x, cloud.points[i].y, cloud.points[i].z);
00067 Eigen::Vector3f intersection = linePlaneIntersection (vp, pt, norm, centroid);
00068 projected_cloud[i].x = intersection[0];
00069 projected_cloud[i].y = intersection[1];
00070 projected_cloud[i].z = intersection[2];
00071 }
00072
00073 return (projected_cloud);
00074 }
00075
00077 template<typename PointT, typename PointNT, typename PointLT> void
00078 pcl::OrganizedMultiPlaneSegmentation<PointT, PointNT, PointLT>::segment (std::vector<ModelCoefficients>& model_coefficients,
00079 std::vector<PointIndices>& inlier_indices)
00080 {
00081 pcl::PointCloud<pcl::Label> labels;
00082 std::vector<pcl::PointIndices> label_indices;
00083 std::vector<Eigen::Vector4f, Eigen::aligned_allocator<Eigen::Vector4f> > centroids;
00084 std::vector <Eigen::Matrix3f, Eigen::aligned_allocator<Eigen::Matrix3f> > covariances;
00085 segment (model_coefficients, inlier_indices, centroids, covariances, labels, label_indices);
00086 }
00087
00089 template<typename PointT, typename PointNT, typename PointLT> void
00090 pcl::OrganizedMultiPlaneSegmentation<PointT, PointNT, PointLT>::segment (std::vector<ModelCoefficients>& model_coefficients,
00091 std::vector<PointIndices>& inlier_indices,
00092 std::vector<Eigen::Vector4f, Eigen::aligned_allocator<Eigen::Vector4f> >& centroids,
00093 std::vector <Eigen::Matrix3f, Eigen::aligned_allocator<Eigen::Matrix3f> >& covariances,
00094 pcl::PointCloud<PointLT>& labels,
00095 std::vector<pcl::PointIndices>& label_indices)
00096 {
00097 if (!initCompute ())
00098 return;
00099
00100
00101 if (static_cast<int> (normals_->points.size ()) != static_cast<int> (input_->points.size ()))
00102 {
00103 PCL_ERROR ("[pcl::%s::segment] Number of points in input cloud (%zu) and normal cloud (%zu) do not match!\n",
00104 getClassName ().c_str (), input_->points.size (),
00105 normals_->points.size ());
00106 return;
00107 }
00108
00109
00110 if (!input_->isOrganized ())
00111 {
00112 PCL_ERROR ("[pcl::%s::segment] Organized point cloud is required for this plane extraction method!\n",
00113 getClassName ().c_str ());
00114 return;
00115 }
00116
00117
00118 std::vector<float> plane_d (input_->points.size ());
00119
00120 for (unsigned int i = 0; i < input_->size (); ++i)
00121 plane_d[i] = input_->points[i].getVector3fMap ().dot (normals_->points[i].getNormalVector3fMap ());
00122
00123
00124
00125 compare_->setPlaneCoeffD (plane_d);
00126 compare_->setInputCloud (input_);
00127 compare_->setInputNormals (normals_);
00128 compare_->setAngularThreshold (static_cast<float> (angular_threshold_));
00129 compare_->setDistanceThreshold (static_cast<float> (distance_threshold_), true);
00130
00131
00132 OrganizedConnectedComponentSegmentation<PointT,pcl::Label> connected_component (compare_);
00133 connected_component.setInputCloud (input_);
00134 connected_component.segment (labels, label_indices);
00135
00136 Eigen::Vector4f clust_centroid = Eigen::Vector4f::Zero ();
00137 Eigen::Vector4f vp = Eigen::Vector4f::Zero ();
00138 Eigen::Matrix3f clust_cov;
00139 pcl::ModelCoefficients model;
00140 model.values.resize (4);
00141
00142
00143 for (size_t i = 0; i < label_indices.size (); i++)
00144 {
00145 if (static_cast<unsigned> (label_indices[i].indices.size ()) > min_inliers_)
00146 {
00147 pcl::computeMeanAndCovarianceMatrix (*input_, label_indices[i].indices, clust_cov, clust_centroid);
00148 Eigen::Vector4f plane_params;
00149
00150 EIGEN_ALIGN16 Eigen::Vector3f::Scalar eigen_value;
00151 EIGEN_ALIGN16 Eigen::Vector3f eigen_vector;
00152 pcl::eigen33 (clust_cov, eigen_value, eigen_vector);
00153 plane_params[0] = eigen_vector[0];
00154 plane_params[1] = eigen_vector[1];
00155 plane_params[2] = eigen_vector[2];
00156 plane_params[3] = 0;
00157 plane_params[3] = -1 * plane_params.dot (clust_centroid);
00158
00159 vp -= clust_centroid;
00160 float cos_theta = vp.dot (plane_params);
00161 if (cos_theta < 0)
00162 {
00163 plane_params *= -1;
00164 plane_params[3] = 0;
00165 plane_params[3] = -1 * plane_params.dot (clust_centroid);
00166 }
00167
00168
00169 float curvature;
00170 float eig_sum = clust_cov.coeff (0) + clust_cov.coeff (4) + clust_cov.coeff (8);
00171 if (eig_sum != 0)
00172 curvature = fabsf (eigen_value / eig_sum);
00173 else
00174 curvature = 0;
00175
00176 if (curvature < maximum_curvature_)
00177 {
00178 model.values[0] = plane_params[0];
00179 model.values[1] = plane_params[1];
00180 model.values[2] = plane_params[2];
00181 model.values[3] = plane_params[3];
00182 model_coefficients.push_back (model);
00183 inlier_indices.push_back (label_indices[i]);
00184 centroids.push_back (clust_centroid);
00185 covariances.push_back (clust_cov);
00186 }
00187 }
00188 }
00189 deinitCompute ();
00190 }
00191
00193 template<typename PointT, typename PointNT, typename PointLT> void
00194 pcl::OrganizedMultiPlaneSegmentation<PointT, PointNT, PointLT>::segment (std::vector<PlanarRegion<PointT>, Eigen::aligned_allocator<PlanarRegion<PointT> > >& regions)
00195 {
00196 std::vector<ModelCoefficients> model_coefficients;
00197 std::vector<PointIndices> inlier_indices;
00198 PointCloudLPtr labels (new PointCloudL);
00199 std::vector<pcl::PointIndices> label_indices;
00200 std::vector<pcl::PointIndices> boundary_indices;
00201 pcl::PointCloud<PointT> boundary_cloud;
00202 std::vector<Eigen::Vector4f, Eigen::aligned_allocator<Eigen::Vector4f> > centroids;
00203 std::vector <Eigen::Matrix3f, Eigen::aligned_allocator<Eigen::Matrix3f> > covariances;
00204 segment (model_coefficients, inlier_indices, centroids, covariances, *labels, label_indices);
00205 regions.resize (model_coefficients.size ());
00206 boundary_indices.resize (model_coefficients.size ());
00207
00208 for (size_t i = 0; i < model_coefficients.size (); i++)
00209 {
00210 boundary_cloud.resize (0);
00211 pcl::OrganizedConnectedComponentSegmentation<PointT,PointLT>::findLabeledRegionBoundary (inlier_indices[i].indices[0], labels, boundary_indices[i]);
00212 boundary_cloud.points.resize (boundary_indices[i].indices.size ());
00213 for (unsigned j = 0; j < boundary_indices[i].indices.size (); j++)
00214 boundary_cloud.points[j] = input_->points[boundary_indices[i].indices[j]];
00215
00216 Eigen::Vector3f centroid = Eigen::Vector3f (centroids[i][0],centroids[i][1],centroids[i][2]);
00217 Eigen::Vector4f model = Eigen::Vector4f (model_coefficients[i].values[0],
00218 model_coefficients[i].values[1],
00219 model_coefficients[i].values[2],
00220 model_coefficients[i].values[3]);
00221 regions[i] = PlanarRegion<PointT> (centroid,
00222 covariances[i],
00223 static_cast<unsigned int> (inlier_indices[i].indices.size ()),
00224 boundary_cloud.points,
00225 model);
00226 }
00227 }
00228
00230 template<typename PointT, typename PointNT, typename PointLT> void
00231 pcl::OrganizedMultiPlaneSegmentation<PointT, PointNT, PointLT>::segmentAndRefine (std::vector<PlanarRegion<PointT>, Eigen::aligned_allocator<PlanarRegion<PointT> > >& regions)
00232 {
00233 std::vector<ModelCoefficients> model_coefficients;
00234 std::vector<PointIndices> inlier_indices;
00235 PointCloudLPtr labels (new PointCloudL);
00236 std::vector<pcl::PointIndices> label_indices;
00237 std::vector<pcl::PointIndices> boundary_indices;
00238 pcl::PointCloud<PointT> boundary_cloud;
00239 std::vector<Eigen::Vector4f, Eigen::aligned_allocator<Eigen::Vector4f> > centroids;
00240 std::vector <Eigen::Matrix3f, Eigen::aligned_allocator<Eigen::Matrix3f> > covariances;
00241 segment (model_coefficients, inlier_indices, centroids, covariances, *labels, label_indices);
00242 refine (model_coefficients, inlier_indices, centroids, covariances, labels, label_indices);
00243 regions.resize (model_coefficients.size ());
00244 boundary_indices.resize (model_coefficients.size ());
00245
00246 for (size_t i = 0; i < model_coefficients.size (); i++)
00247 {
00248 boundary_cloud.resize (0);
00249 int max_inlier_idx = static_cast<int> (inlier_indices[i].indices.size ()) - 1;
00250 pcl::OrganizedConnectedComponentSegmentation<PointT,PointLT>::findLabeledRegionBoundary (inlier_indices[i].indices[max_inlier_idx], labels, boundary_indices[i]);
00251 boundary_cloud.points.resize (boundary_indices[i].indices.size ());
00252 for (unsigned j = 0; j < boundary_indices[i].indices.size (); j++)
00253 boundary_cloud.points[j] = input_->points[boundary_indices[i].indices[j]];
00254
00255 Eigen::Vector3f centroid = Eigen::Vector3f (centroids[i][0],centroids[i][1],centroids[i][2]);
00256 Eigen::Vector4f model = Eigen::Vector4f (model_coefficients[i].values[0],
00257 model_coefficients[i].values[1],
00258 model_coefficients[i].values[2],
00259 model_coefficients[i].values[3]);
00260
00261 Eigen::Vector3f vp (0.0, 0.0, 0.0);
00262 if (project_points_)
00263 boundary_cloud = projectToPlaneFromViewpoint (boundary_cloud, model, centroid, vp);
00264
00265 regions[i] = PlanarRegion<PointT> (centroid,
00266 covariances[i],
00267 static_cast<unsigned int> (inlier_indices[i].indices.size ()),
00268 boundary_cloud.points,
00269 model);
00270 }
00271 }
00272
00274 template<typename PointT, typename PointNT, typename PointLT> void
00275 pcl::OrganizedMultiPlaneSegmentation<PointT, PointNT, PointLT>::segmentAndRefine (std::vector<PlanarRegion<PointT>, Eigen::aligned_allocator<PlanarRegion<PointT> > >& regions,
00276 std::vector<ModelCoefficients>& model_coefficients,
00277 std::vector<PointIndices>& inlier_indices,
00278 PointCloudLPtr& labels,
00279 std::vector<pcl::PointIndices>& label_indices,
00280 std::vector<pcl::PointIndices>& boundary_indices)
00281 {
00282 pcl::PointCloud<PointT> boundary_cloud;
00283 std::vector<Eigen::Vector4f, Eigen::aligned_allocator<Eigen::Vector4f> > centroids;
00284 std::vector <Eigen::Matrix3f, Eigen::aligned_allocator<Eigen::Matrix3f> > covariances;
00285 segment (model_coefficients, inlier_indices, centroids, covariances, *labels, label_indices);
00286 refine (model_coefficients, inlier_indices, centroids, covariances, labels, label_indices);
00287 regions.resize (model_coefficients.size ());
00288 boundary_indices.resize (model_coefficients.size ());
00289
00290 for (size_t i = 0; i < model_coefficients.size (); i++)
00291 {
00292 boundary_cloud.resize (0);
00293 int max_inlier_idx = static_cast<int> (inlier_indices[i].indices.size ()) - 1;
00294 pcl::OrganizedConnectedComponentSegmentation<PointT,PointLT>::findLabeledRegionBoundary (inlier_indices[i].indices[max_inlier_idx], labels, boundary_indices[i]);
00295 boundary_cloud.points.resize (boundary_indices[i].indices.size ());
00296 for (unsigned j = 0; j < boundary_indices[i].indices.size (); j++)
00297 boundary_cloud.points[j] = input_->points[boundary_indices[i].indices[j]];
00298
00299 Eigen::Vector3f centroid = Eigen::Vector3f (centroids[i][0],centroids[i][1],centroids[i][2]);
00300 Eigen::Vector4f model = Eigen::Vector4f (model_coefficients[i].values[0],
00301 model_coefficients[i].values[1],
00302 model_coefficients[i].values[2],
00303 model_coefficients[i].values[3]);
00304
00305 Eigen::Vector3f vp (0.0, 0.0, 0.0);
00306 if (project_points_ && boundary_cloud.points.size () > 0)
00307 boundary_cloud = projectToPlaneFromViewpoint (boundary_cloud, model, centroid, vp);
00308
00309 regions[i] = PlanarRegion<PointT> (centroid,
00310 covariances[i],
00311 static_cast<unsigned int> (inlier_indices[i].indices.size ()),
00312 boundary_cloud.points,
00313 model);
00314 }
00315 }
00316
00318 template<typename PointT, typename PointNT, typename PointLT> void
00319 pcl::OrganizedMultiPlaneSegmentation<PointT, PointNT, PointLT>::refine (std::vector<ModelCoefficients>& model_coefficients,
00320 std::vector<PointIndices>& inlier_indices,
00321 std::vector<Eigen::Vector4f, Eigen::aligned_allocator<Eigen::Vector4f> >&,
00322 std::vector <Eigen::Matrix3f, Eigen::aligned_allocator<Eigen::Matrix3f> >&,
00323 PointCloudLPtr& labels,
00324 std::vector<pcl::PointIndices>& label_indices)
00325 {
00326
00327 std::vector<bool> grow_labels;
00328 std::vector<int> label_to_model;
00329 grow_labels.resize (label_indices.size (), false);
00330 label_to_model.resize (label_indices.size (), 0);
00331
00332 for (size_t i = 0; i < model_coefficients.size (); i++)
00333 {
00334 int model_label = (*labels)[inlier_indices[i].indices[0]].label;
00335 label_to_model[model_label] = static_cast<int> (i);
00336 grow_labels[model_label] = true;
00337 }
00338
00339
00340 refinement_compare_->setInputCloud (input_);
00341 refinement_compare_->setLabels (labels);
00342 refinement_compare_->setModelCoefficients (model_coefficients);
00343 refinement_compare_->setRefineLabels (grow_labels);
00344 refinement_compare_->setLabelToModel (label_to_model);
00345
00346
00347 unsigned int current_row = 0;
00348 unsigned int next_row = labels->width;
00349 for (size_t rowIdx = 0; rowIdx < labels->height - 1; ++rowIdx, current_row = next_row, next_row += labels->width)
00350 {
00351
00352 for (unsigned colIdx = 0; colIdx < labels->width - 1; ++colIdx)
00353 {
00354 int current_label = (*labels)[current_row+colIdx].label;
00355 int right_label = (*labels)[current_row+colIdx+1].label;
00356 if (current_label < 0 || right_label < 0)
00357 continue;
00358
00359
00360
00361 if (refinement_compare_->compare (current_row+colIdx, current_row+colIdx+1))
00362 {
00363
00364 labels->points[current_row+colIdx+1].label = current_label;
00365 label_indices[label_to_model[current_label]].indices.push_back (current_row+colIdx+1);
00366 inlier_indices[label_to_model[current_label]].indices.push_back (current_row+colIdx+1);
00367 }
00368
00369 int lower_label = (*labels)[next_row+colIdx].label;
00370 if (lower_label < 0)
00371 continue;
00372
00373
00374 if (refinement_compare_->compare (current_row+colIdx, next_row+colIdx))
00375 {
00376 labels->points[next_row+colIdx].label = current_label;
00377 label_indices[label_to_model[current_label]].indices.push_back (next_row+colIdx);
00378 inlier_indices[label_to_model[current_label]].indices.push_back (next_row+colIdx);
00379 }
00380
00381 }
00382 }
00383
00384
00385 current_row = labels->width * (labels->height - 1);
00386 unsigned int prev_row = current_row - labels->width;
00387 for (size_t rowIdx = 0; rowIdx < labels->height - 1; ++rowIdx, current_row = prev_row, prev_row -= labels->width)
00388 {
00389 for (int colIdx = labels->width - 1; colIdx >= 0; --colIdx)
00390 {
00391 int current_label = (*labels)[current_row+colIdx].label;
00392 int left_label = (*labels)[current_row+colIdx-1].label;
00393 if (current_label < 0 || left_label < 0)
00394 continue;
00395
00396
00397 if (refinement_compare_->compare (current_row+colIdx, current_row+colIdx-1))
00398 {
00399 labels->points[current_row+colIdx-1].label = current_label;
00400 label_indices[label_to_model[current_label]].indices.push_back (current_row+colIdx-1);
00401 inlier_indices[label_to_model[current_label]].indices.push_back (current_row+colIdx-1);
00402 }
00403
00404 int upper_label = (*labels)[prev_row+colIdx].label;
00405 if (upper_label < 0)
00406 continue;
00407
00408 if (refinement_compare_->compare (current_row+colIdx, prev_row+colIdx))
00409 {
00410 labels->points[prev_row+colIdx].label = current_label;
00411 label_indices[label_to_model[current_label]].indices.push_back (prev_row+colIdx);
00412 inlier_indices[label_to_model[current_label]].indices.push_back (prev_row+colIdx);
00413 }
00414 }
00415 }
00416 }
00417
00418 #define PCL_INSTANTIATE_OrganizedMultiPlaneSegmentation(T,NT,LT) template class PCL_EXPORTS pcl::OrganizedMultiPlaneSegmentation<T,NT,LT>;
00419
00420 #endif // PCL_SEGMENTATION_IMPL_MULTI_PLANE_SEGMENTATION_H_