pcl_utils
pcl_utils.h
Go to the documentation of this file.
1 
6 #ifndef UTILS_PCL_UTILS_H_
7 #define UTILS_PCL_UTILS_H_
8 
9 #include <string>
10 #include <vector>
11 #include <map>
12 #include <math.h>
13 #include <algorithm>
14 #include <stdlib.h>
15 
16 #include <Eigen/Core>
17 
18 #include <pcl/point_cloud.h>
19 #include <pcl/point_types.h>
20 #include <pcl/PointIndices.h>
21 #include <pcl/visualization/pcl_visualizer.h>
22 #include <pcl/kdtree/kdtree.h>
23 #include <pcl/filters/passthrough.h>
24 #include <pcl/filters/extract_indices.h>
25 #include <pcl/filters/voxel_grid.h>
26 #include <pcl/segmentation/extract_clusters.h>
27 #include <pcl/segmentation/sac_segmentation.h>
28 #include <pcl/ModelCoefficients.h>
29 #include <pcl/features/feature.h>
30 #include <pcl/features/normal_3d_omp.h>
31 #include <pcl/common/common.h>
32 #include <pcl/common/pca.h>
33 
34 // MACRO utilities
35 #define SSTR(x) static_cast<std::ostringstream&>((std::ostringstream() << std::dec << x )).str()
36 
37 
38 namespace utils {
39 
46 template <typename T>
47 class PclUtils
48 {
49  private:
50  typedef pcl::PointCloud<T> PclCloud;
51 
52  public:
59  static pcl::visualization::PCLVisualizer::Ptr pclViewer() {
60  pcl::visualization::PCLVisualizer::Ptr viewer (new pcl::visualization::PCLVisualizer);
61  viewer->setBackgroundColor(0,0,0);
62  viewer->addCoordinateSystem(1.0);
63  viewer->initCameraParameters();
64  return viewer;
65  }
66 
70  static pcl::visualization::PCLVisualizer::Ptr pclViewer(typename PclCloud::Ptr& cloud) {
71  pcl::visualization::PCLVisualizer::Ptr viewer = pclViewer();
72  viewer->addPointCloud<T>(cloud);
73  return viewer;
74  }
75 
81  static void showCloud(typename PclCloud::Ptr& cloud) {
82  pcl::visualization::PCLVisualizer::Ptr viewer = PclUtils::pclViewer(cloud);
83  viewer->spin();
84  }
85 
96  static void addColoredCloud(pcl::visualization::PCLVisualizer::Ptr& viewer,
97  typename PclCloud::Ptr& cloud,
98  float r = 255.0f, float g = 0.0f, float b = 0.0f) {
99  // random
100  if (r < 0) {
101  r = rand() % 255;
102  g = rand() % 255;
103  b = rand() % 255;
104  }
105  std::string id = SSTR(rand());
106 
107  viewer->addPointCloud<T>(cloud,
108  pcl::visualization::PointCloudColorHandlerCustom<T>(cloud, r, g, b), id);
109  }
110 
111 
121  static void downsample(typename PclCloud::Ptr& cloud, typename PclCloud::Ptr& outcloud,
122  const float leaf = 0.005f) {
123  pcl::VoxelGrid<T> grid;
124  grid.setLeafSize(leaf, leaf, leaf);
125  grid.setInputCloud(cloud);
126  grid.filter(*outcloud);
127  }
128 
138  template <typename PointNT>
139  static void estimateNormal(typename pcl::PointCloud<PointNT>::Ptr& cloud,
140  typename pcl::PointCloud<PointNT>::Ptr& outcloud,
141  const float radius = 0.01) {
142  /*
143  * NormalEstimation does not work from PointXYZRGB -> PointNormal. Hence the
144  * method accepts only PointNormal
145  */
146  pcl::NormalEstimationOMP<PointNT, PointNT> ne;
147  ne.setRadiusSearch(radius);
148  ne.setInputCloud(cloud);
149  ne.compute(*outcloud);
150  }
151 
161  static typename PclCloud::Ptr cropPointCloud(typename PclCloud::Ptr& cloud,
162  Eigen::Vector2i& topleft, Eigen::Vector2i& bottomright)
163  {
164  int width = bottomright[0] - topleft[0];
165  int height = bottomright[1] - topleft[1];
166 
167  typename PclCloud::Ptr out_cloud (new PclCloud);
168  out_cloud->resize(width * height);
169  out_cloud->width = width;
170  out_cloud->height = height;
171  out_cloud->is_dense = cloud->is_dense;
172  out_cloud->header = cloud->header;
173  out_cloud->sensor_orientation_ = cloud->sensor_orientation_;
174  out_cloud->sensor_origin_ = cloud->sensor_origin_;
175 
176  for (int i=topleft[0], c = 0; i < bottomright[0]; i++, c++)
177  {
178  for (int j = topleft[1], r = 0; j < bottomright[1]; j++, r++)
179  {
180  (*out_cloud)(c, r) = (*cloud)(i, j);
181  }
182  }
183  return out_cloud;
184  }
185 
193  static typename PclCloud::Ptr cropPointCloud(typename PclCloud::Ptr& cloud,
194  const Eigen::Vector4i& box) {
195  Eigen::Vector2i topleft(box[0], box[1]);
196  Eigen::Vector2i bottomright(box[2], box[3]);
197  return cropPointCloud(cloud, topleft, bottomright);
198  }
199 
209  static void filterOutliers(typename PclCloud::Ptr& cloud, std::string axis, float min, float max) {
210  pcl::PassThrough<T> pass;
211  pass.setInputCloud(cloud);
212  pass.setFilterFieldName(axis);
213  pass.setFilterLimits(min, max);
214  pass.setKeepOrganized(true);
215  pass.filter(*cloud);
216  }
217 
218 
230  static typename PclCloud::Ptr extractIndices(typename PclCloud::Ptr& cloud,
231  std::vector<int>& indices,
232  bool negative = false,
233  bool keep_organized = false) {
234  pcl::PointIndices::Ptr pcl_indices (new pcl::PointIndices);
235  pcl_indices->indices = indices;
236  return extractIndices(cloud, pcl_indices, negative, keep_organized);
237  }
238 
250  static typename PclCloud::Ptr extractIndices(typename PclCloud::Ptr& cloud,
251  pcl::PointIndices::Ptr& indices,
252  bool negative = false,
253  bool keep_organized = false) {
254  typename PclCloud::Ptr out_cloud (new PclCloud);
255  extractIndices(cloud, indices, out_cloud, negative, keep_organized);
256  return out_cloud;
257  }
258 
270  static void extractIndices(typename PclCloud::Ptr& cloud,
271  pcl::PointIndices::Ptr& indices,
272  typename PclCloud::Ptr& out_cloud,
273  bool negative = false,
274  bool keep_organized = false) {
275  pcl::ExtractIndices<T> filter;
276  filter.setInputCloud(cloud);
277  filter.setIndices(indices);
278  filter.setNegative(negative);
279  filter.setKeepOrganized(keep_organized);
280  filter.filter(*out_cloud);
281  }
282 
290  static void segmentPlane(typename PclCloud::Ptr& cloud,
291  pcl::ModelCoefficients::Ptr& coeff,
292  pcl::PointIndices::Ptr& inliers)
293  {
294  pcl::SACSegmentation<T> seg;
295  seg.setOptimizeCoefficients(true);
296  seg.setModelType(pcl::SACMODEL_PLANE);
297  seg.setMethodType(pcl::SAC_RANSAC);
298  seg.setDistanceThreshold(0.01);
299  seg.setInputCloud(cloud);
300  seg.segment(*inliers, *coeff);
301 
302  if (inliers->indices.size() == 0)
303  {
304  PCL_ERROR("Could not estimate a planar model for the given point cloud");
305  return;
306  }
307  }
308 
319  static void filterTableTop(typename PclCloud::Ptr& cloud, float min_table_z, float min_table_x) {
320  // Remove outliers (keep inliers)
321  // Table is retained to fit a plane in next step (hence min_table_z - 0.1)
322  filterOutliers(cloud, "z", min_table_z - 0.1, min_table_z + 1);
323  filterOutliers(cloud, "x", min_table_x, min_table_x + 1);
324 
325  // Fit a plane for table
326  pcl::ModelCoefficients::Ptr coeff (new pcl::ModelCoefficients);
327  pcl::PointIndices::Ptr inliers (new pcl::PointIndices);
328  segmentPlane(cloud, coeff, inliers);
329 
330  bool negative = true, keep_organized = true;
331  extractIndices(cloud, inliers, cloud, negative, keep_organized);
332  }
333 
337  static void convertToXYZRGB(typename pcl::PointCloud<T>& cloud, Eigen::Vector3i& color,
338  pcl::PointCloud<pcl::PointXYZRGB>& out_cloud)
339  {
340  pcl::copyPointCloud(cloud, out_cloud);
341 
342  for (size_t i = 0; i < out_cloud.size(); i++) {
343  pcl::PointXYZRGB &p = out_cloud.points[i];
344  if (!isnan(p.x)) {
345  p.r = color[0];
346  p.g = color[1];
347  p.b = color[2];
348  }
349  }
350  }
351 
362  static void cluster(typename PclCloud::Ptr& cloud, std::vector<pcl::PointIndices>& cluster_indices) {
363  using std::vector;
364 
365  pcl::IndicesPtr indices (new vector<int>);
366  pcl::removeNaNFromPointCloud(*cloud, *indices);
367 
368  typename pcl::search::KdTree<T>::Ptr tree (new pcl::search::KdTree<T>);
369  tree->setInputCloud(cloud, indices);
370 
371  pcl::EuclideanClusterExtraction<T> ec;
372  ec.setClusterTolerance (0.02); // 2cm
373  ec.setMinClusterSize (600);
374  ec.setMaxClusterSize (50000);
375  ec.setSearchMethod (tree);
376  ec.setIndices(indices);
377  ec.setInputCloud (cloud);
378  ec.extract (cluster_indices);
379  }
380 
388  static Eigen::Vector4i findBox(const pcl::PointIndices& indices, typename PclCloud::Ptr& cloud)
389  {
390  int minxi = cloud->width, maxxi = 0, minyi = cloud->height, maxyi = 0;
391  for (std::vector<int>::const_iterator it = indices.indices.begin();
392  it != indices.indices.end(); ++it)
393  {
394  int xi = *it % cloud->width;
395  int yi = (int) (*it / cloud->width);
396 
397  minxi = std::min(minxi, xi);
398  maxxi = std::max(maxxi, xi);
399  minyi = std::min(minyi, yi);
400  maxyi = std::max(maxyi, yi);
401  }
402  Eigen::Vector4i range (minxi, minyi, maxxi, maxyi);
403  return range;
404  }
405 
415  static T findNearestNonNan(typename PclCloud::Ptr& cloud, int cx, int cy) {
416  T pointCenter = (*cloud)(cx, cy);
417  // search for non-nan point in a circular with increasing radius
418  int r = 1;
419  while (isnan(pointCenter.x))
420  {
421  pointCenter = (*cloud)(cx + r, cy);
422  if (!isnan(pointCenter.x)) {
423  break;
424  }
425 
426  pointCenter = (*cloud)(cx - r, cy);
427  if (!isnan(pointCenter.x)) {
428  break;
429  }
430  pointCenter = (*cloud)(cx, cy + r);
431  if (!isnan(pointCenter.x)) {
432  break;
433  }
434  pointCenter = (*cloud)(cx, cy - r);
435  r++;
436  }
437  return pointCenter;
438  }
439 
445  static T createPoint(float x, float y, float z) {
446  T point;
447  point.x = x;
448  point.y = y;
449  point.z = z;
450  return point;
451  }
452 
459  static typename PclCloud::Ptr createCloud(const Eigen::Ref<const Eigen::MatrixXf>& mat) {
460  typename PclCloud::Ptr cloud (new PclCloud);
461 
462  for (int col=0; col < mat.cols(); ++col) {
463  float x = mat(0, col);
464  float y = mat(1, col);
465  float z = mat(2, col);
466  T point = createPoint(x, y, z);
467  cloud->push_back(point);
468  }
469  return cloud;
470  }
471 
478  static Eigen::Matrix<float, 3, 8> createOrientedBox(typename PclCloud::Ptr& cloud) {
479  pcl::PCA<T> pca;
480  pca.setInputCloud(cloud);
481  typename PclCloud::Ptr proj_c (new PclCloud);
482 
483  pca.project(*cloud, *proj_c);
484 
485  T proj_min, proj_max, min, max;
486  pcl::getMinMax3D(*proj_c, proj_min, proj_max);
487 
488  Eigen::Matrix<float, 3, 8> mat, res;
489  mat.col(0) << proj_min.x, proj_min.y, proj_min.z,
490  mat.col(1) << proj_max.x, proj_min.y, proj_min.z,
491  mat.col(2) << proj_max.x, proj_max.y, proj_min.z,
492  mat.col(3) << proj_min.x, proj_max.y, proj_min.z,
493  mat.col(4) << proj_min.x, proj_max.y, proj_max.z,
494  mat.col(5) << proj_min.x, proj_min.y, proj_max.z,
495  mat.col(6) << proj_max.x, proj_min.y, proj_max.z,
496  mat.col(7) << proj_max.x, proj_max.y, proj_max.z;
497 
498  for (int i=0; i < 8; ++i) {
499  T proj_point = createPoint(mat(0, i), mat(1, i), mat(2, i));
500  T point;
501  pca.reconstruct(proj_point, point);
502  res(0, i) = point.x;
503  res(1, i) = point.y;
504  res(2, i) = point.z;
505  }
506 
507  return res;
508  }
509 
510 }; // class PclUtils
511 
512 } // namespace utils
513 
514 #endif // UTILS_PCL_UTILS_H_
static void estimateNormal(typename pcl::PointCloud< PointNT >::Ptr &cloud, typename pcl::PointCloud< PointNT >::Ptr &outcloud, const float radius=0.01)
Definition: pcl_utils.h:139
static pcl::visualization::PCLVisualizer::Ptr pclViewer(typename PclCloud::Ptr &cloud)
Definition: pcl_utils.h:70
static PclCloud::Ptr createCloud(const Eigen::Ref< const Eigen::MatrixXf > &mat)
Definition: pcl_utils.h:459
static PclCloud::Ptr extractIndices(typename PclCloud::Ptr &cloud, pcl::PointIndices::Ptr &indices, bool negative=false, bool keep_organized=false)
Definition: pcl_utils.h:250
function p(by, bw, bv)
Definition: jquery.js:23
static Eigen::Vector4i findBox(const pcl::PointIndices &indices, typename PclCloud::Ptr &cloud)
Definition: pcl_utils.h:388
static void extractIndices(typename PclCloud::Ptr &cloud, pcl::PointIndices::Ptr &indices, typename PclCloud::Ptr &out_cloud, bool negative=false, bool keep_organized=false)
Definition: pcl_utils.h:270
var c
Definition: jquery.js:23
Definition: pcl_utils.h:47
static PclCloud::Ptr cropPointCloud(typename PclCloud::Ptr &cloud, const Eigen::Vector4i &box)
Definition: pcl_utils.h:193
static void segmentPlane(typename PclCloud::Ptr &cloud, pcl::ModelCoefficients::Ptr &coeff, pcl::PointIndices::Ptr &inliers)
Definition: pcl_utils.h:290
#define SSTR(x)
Definition: pcl_utils.h:35
static void showCloud(typename PclCloud::Ptr &cloud)
Definition: pcl_utils.h:81
static void convertToXYZRGB(typename pcl::PointCloud< T > &cloud, Eigen::Vector3i &color, pcl::PointCloud< pcl::PointXYZRGB > &out_cloud)
Definition: pcl_utils.h:337
static T createPoint(float x, float y, float z)
Definition: pcl_utils.h:445
static void cluster(typename PclCloud::Ptr &cloud, std::vector< pcl::PointIndices > &cluster_indices)
Definition: pcl_utils.h:362
static Eigen::Matrix< float, 3, 8 > createOrientedBox(typename PclCloud::Ptr &cloud)
Definition: pcl_utils.h:478
static void filterOutliers(typename PclCloud::Ptr &cloud, std::string axis, float min, float max)
Definition: pcl_utils.h:209
static PclCloud::Ptr cropPointCloud(typename PclCloud::Ptr &cloud, Eigen::Vector2i &topleft, Eigen::Vector2i &bottomright)
Definition: pcl_utils.h:161
Definition: pcl_utils.cpp:6
static void addColoredCloud(pcl::visualization::PCLVisualizer::Ptr &viewer, typename PclCloud::Ptr &cloud, float r=255.0f, float g=0.0f, float b=0.0f)
Definition: pcl_utils.h:96
static void filterTableTop(typename PclCloud::Ptr &cloud, float min_table_z, float min_table_x)
Definition: pcl_utils.h:319
var b
Definition: jquery.js:16
static void downsample(typename PclCloud::Ptr &cloud, typename PclCloud::Ptr &outcloud, const float leaf=0.005f)
Definition: pcl_utils.h:121
static T findNearestNonNan(typename PclCloud::Ptr &cloud, int cx, int cy)
Definition: pcl_utils.h:415
static PclCloud::Ptr extractIndices(typename PclCloud::Ptr &cloud, std::vector< int > &indices, bool negative=false, bool keep_organized=false)
Definition: pcl_utils.h:230
static pcl::visualization::PCLVisualizer::Ptr pclViewer()
Definition: pcl_utils.h:59