ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
PCLModules.h
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #pragma once
9 
10 #ifdef _MSC_VER
11 #pragma warning(disable : 4996)
12 #pragma warning(disable : 4290)
13 #pragma warning(disable : 4819)
14 #endif
15 
16 // LOCAL
17 #include <Utils/PCLCloud.h>
18 #include <Utils/PCLConv.h>
19 
20 #include "qPCL.h"
21 
22 // CV_CORE_LIB
23 #include <CVLog.h>
24 #include <CVMath.h>
25 #include <Eigen.h>
26 #include <Parallel.h>
27 
28 // PCL COMMON
29 #include <pcl/ModelCoefficients.h>
30 #include <pcl/Vertices.h>
31 #include <pcl/common/common.h>
32 #include <pcl/common/io.h> // for getFieldIndex
33 #include <pcl/common/transforms.h>
34 #include <pcl/correspondence.h>
35 #include <pcl/point_types.h>
36 
37 // PCL KEYPOINTS
38 #include <pcl/keypoints/harris_3d.h>
39 #include <pcl/keypoints/sift_keypoint.h>
40 // #include <pcl/keypoints/uniform_sampling.h>
41 
42 // PCL FILTERS
43 #include <pcl/filters/conditional_removal.h>
44 #include <pcl/filters/crop_hull.h>
45 #include <pcl/filters/extract_indices.h>
46 #include <pcl/filters/passthrough.h>
47 #include <pcl/filters/project_inliers.h>
48 #include <pcl/filters/statistical_outlier_removal.h>
49 #include <pcl/filters/uniform_sampling.h>
50 #include <pcl/filters/voxel_grid.h>
51 
52 // PCL RECOGNITION
53 #include <pcl/recognition/cg/geometric_consistency.h>
54 #include <pcl/recognition/cg/hough_3d.h>
55 
56 // PCL REGISTRATION
57 #include <pcl/registration/ia_ransac.h>
58 #include <pcl/registration/icp.h>
59 
60 // PCL SEARCH
61 #include <pcl/kdtree/kdtree_flann.h>
62 #include <pcl/search/kdtree.h> // for KdTree
63 
64 // PCL SURFACE
65 #include <pcl/surface/concave_hull.h>
66 #include <pcl/surface/convex_hull.h>
67 #include <pcl/surface/marching_cubes.h>
68 #include <pcl/surface/marching_cubes_hoppe.h>
69 #include <pcl/surface/marching_cubes_rbf.h>
70 #include <pcl/surface/mls.h>
71 #if defined(WITH_PCL_NURBS)
72 #include <pcl/surface/on_nurbs/fitting_curve_2d.h>
73 #include <pcl/surface/on_nurbs/fitting_curve_2d_apdm.h>
74 #include <pcl/surface/on_nurbs/fitting_curve_2d_asdm.h>
75 #include <pcl/surface/on_nurbs/fitting_curve_2d_atdm.h>
76 #include <pcl/surface/on_nurbs/fitting_curve_2d_pdm.h>
77 #include <pcl/surface/on_nurbs/fitting_curve_2d_sdm.h>
78 #include <pcl/surface/on_nurbs/fitting_curve_2d_tdm.h>
79 #include <pcl/surface/on_nurbs/fitting_curve_pdm.h>
80 #include <pcl/surface/on_nurbs/fitting_surface_tdm.h>
81 #include <pcl/surface/on_nurbs/triangulation.h>
82 #endif
83 
84 // PCL FEATURES
85 #include <pcl/features/board.h>
86 #include <pcl/features/boundary.h>
87 #include <pcl/features/don.h>
88 #include <pcl/features/normal_3d_omp.h>
89 #include <pcl/features/shot_omp.h>
90 
91 // PCL SEGMENTATION
92 #include <pcl/segmentation/extract_clusters.h>
93 #include <pcl/segmentation/min_cut_segmentation.h>
94 #include <pcl/segmentation/progressive_morphological_filter.h>
95 
96 #include <pcl/segmentation/impl/extract_clusters.hpp>
97 
98 // QT
99 #include <QThread>
100 
101 // SYSTEM
102 #include <Eigen/Core>
103 #include <limits>
104 #include <vector>
105 
106 // normal function
107 namespace PCLModules {
108 // for grid projection
110 GridProjection(const PointCloudNormal::ConstPtr &cloudWithNormals,
111  PCLMesh &outMesh,
112  float resolution = 0.2f,
113  int paddingSize = 2,
114  int maxSearchLevel = 8);
115 
116 // for poisson reconstruction
118 GetPoissonReconstruction(const PointCloudNormal::ConstPtr &cloudWithNormals,
119  PCLMesh &outMesh,
120  int degree = 2,
121  int treeDepth = 8,
122  int isoDivideDepth = 8,
123  int solverDivideDepth = 8,
124  float scale = 1.25f,
125  float samplesPerNode = 3.0f,
126  bool useConfidence = true,
127  bool useManifold = true,
128  bool outputPolygons = false);
129 
130 // for greedy projection triangulation
132 GetGreedyTriangulation(const PointCloudNormal::ConstPtr &cloudWithNormals,
133  PCLMesh &outMesh,
134  int trigulationSearchRadius = 25,
135  float weightingFactor = 2.5f,
136  int maxNearestNeighbors = 100,
137  int maxSurfaceAngle = 45,
138  int minAngle = 10,
139  int maxAngle = 120,
140  bool normalConsistency = false);
141 
143  const PointCloudT::ConstPtr &originCloud,
144  PointCloudT::Ptr &projectedCloud,
145  const pcl::ModelCoefficients::ConstPtr coefficients,
146  const int &modelType = 0 /*pcl::SACMODEL_PLANE*/
147 );
148 
149 // for pcl projection filter
151  const PointCloudT::ConstPtr &originCloud,
152  PointCloudT::Ptr &projectedCloud,
153  float coefficientA = 0.0f,
154  float coefficientB = 0.0f,
155  float coefficientC = 1.0f,
156  float coefficientD = 0.0f,
157  const int &modelType = 0 /*pcl::SACMODEL_PLANE*/
158 );
159 
172 GetRegionGrowing(const PointCloudT::ConstPtr cloud,
173  std::vector<pcl::PointIndices> &clusters,
174  PointCloudRGB::Ptr cloud_segmented,
175  int k,
176  int min_cluster_size,
177  int max_cluster_size,
178  unsigned int neighbour_number,
179  float smoothness_theta,
180  float curvature);
181 
192 GetRegionGrowingRGB(const PointCloudRGB::ConstPtr cloud,
193  std::vector<pcl::PointIndices> &clusters,
194  PointCloudRGB::Ptr cloud_segmented,
195  int min_cluster_size,
196  float neighbors_distance,
197  float point_color_diff,
198  float region_color_diff);
199 
201 GetSACSegmentation(const PointCloudT::ConstPtr cloud,
202  pcl::PointIndices::Ptr inliers,
203  pcl::ModelCoefficients::Ptr coefficients = nullptr,
204  const int &methodType = 0 /* = pcl::SAC_RANSAC*/,
205  const int &modelType = 0 /* = pcl::SACMODEL_PLANE*/,
206  float distanceThreshold = 0.02f,
207  float probability = 0.95f,
208  int maxIterations = 100,
209  float minRadiusLimits = -10000.0f,
210  float maxRadiusLimits = 10000.0f,
211  float normalDisWeight = 0.1f);
212 } // namespace PCLModules
213 
214 // surface reconstruction
215 namespace PCLModules {
217 template <typename PointInT>
218 int GetMarchingCubes(const typename pcl::PointCloud<PointInT>::ConstPtr inCloud,
219  const MarchingMethod &marchingMethod,
220  PCLMesh &outMesh,
221  float epsilon = 0.01f,
222  float isoLevel = 0.0f,
223  float gridResolution = 50,
224  float percentageExtendGrid = 0.0f) {
225  // Create a search tree, use KDTreee for non-organized data.
226  typename pcl::search::Search<PointInT>::Ptr tree;
227  if (inCloud->isOrganized()) {
228  tree.reset(new pcl::search::OrganizedNeighbor<PointInT>());
229  } else {
230  tree.reset(new pcl::search::KdTree<PointInT>());
231  }
232  tree->setInputCloud(inCloud);
233 
234  typename pcl::MarchingCubes<PointInT>::Ptr mc;
235  switch (marchingMethod) {
236  case MarchingMethod::HOPPE: {
237  mc.reset(new pcl::MarchingCubesHoppe<PointInT>());
238  break;
239  }
240  case MarchingMethod::RBF: {
241  typename pcl::MarchingCubesRBF<PointInT>::Ptr rbf(
242  new pcl::MarchingCubesRBF<PointInT>());
243  rbf->setOffSurfaceDisplacement(epsilon);
244  mc = rbf;
245  break;
246  }
247  default:
248  return -1;
249  }
250 
251  mc->setIsoLevel(isoLevel);
252  mc->setGridResolution(gridResolution, gridResolution, gridResolution);
253  mc->setPercentageExtendGrid(percentageExtendGrid);
254  mc->setInputCloud(inCloud);
255  mc->reconstruct(outMesh);
256  return 1;
257 }
258 } // namespace PCLModules
259 
260 // template function
261 namespace PCLModules {
262 template <typename PointInOutT>
263 int SwapAxis(const typename pcl::PointCloud<PointInOutT>::ConstPtr inCloud,
264  typename pcl::PointCloud<PointInOutT>::Ptr outcloud,
265  const std::string &flag) {
266  pcl::copyPointCloud<PointInOutT, PointInOutT>(*inCloud, *outcloud);
267  typename pcl::PointCloud<PointInOutT>::iterator it;
268  for (it = outcloud->begin(); it != outcloud->end();) {
269  float x = it->x;
270  float y = it->y;
271  float z = it->z;
272 
273  if ("zxy" == flag) {
274  it->x = z;
275  it->y = x;
276  it->z = y;
277  } else if ("zyx" == flag) {
278  it->x = z;
279  it->z = x;
280  } else if ("xzy" == flag) {
281  it->y = z;
282  it->z = y;
283  } else if ("yxz" == flag) {
284  it->x = y;
285  it->y = x;
286  } else if ("yzx" == flag) {
287  it->x = y;
288  it->y = z;
289  it->z = x;
290  }
291  ++it;
292  }
293  return 1;
294 }
295 
296 template <typename PointInT>
297 int RemoveNaN(const typename pcl::PointCloud<PointInT>::ConstPtr inCloud,
298  typename pcl::PointCloud<PointInT>::Ptr outcloud,
299  std::vector<int> &index) {
300  pcl::removeNaNFromPointCloud(*inCloud, *outcloud, index);
301  return 1;
302 }
303 
304 #if defined(WITH_PCL_NURBS)
305 struct QPCL_ENGINE_LIB_API NurbsParameters {
306  NurbsParameters()
307  : order_(3),
308  twoDim_(true),
309  iterations_(10),
310  refinements_(4),
311  curveResolution_(4),
312  meshResolution_(128) {}
313 
314  int order_;
315  bool twoDim_;
316  int iterations_;
317  int refinements_;
318  unsigned curveResolution_;
319  unsigned meshResolution_;
320  pcl::on_nurbs::FittingSurface::Parameter fittingParams_;
321 };
322 template <typename PointInT>
323 int NurbsSurfaceFitting(
324  const typename pcl::PointCloud<PointInT>::ConstPtr inCloud,
325  const NurbsParameters &nurbsParams,
326  PCLMesh &outMesh,
327  PointCloudRGB::Ptr outCurve = nullptr) {
328  // step 1. convert point cloud to nurbs data vector3d
329  pcl::on_nurbs::NurbsDataSurface data;
330  for (unsigned i = 0; i < inCloud->size(); i++) {
331  const PointInT &p = inCloud->at(i);
332  if (!std::isnan(p.x) && !std::isnan(p.y) && !std::isnan(p.z))
333  data.interior.push_back(Eigen::Vector3d(p.x, p.y, p.z));
334  }
335 
336  // step 2. initialize and get first inital surface reconstruction
337  ON_NurbsSurface nurbs =
338  pcl::on_nurbs::FittingSurface::initNurbsPCABoundingBox(
339  nurbsParams.order_, &data);
340  pcl::on_nurbs::FittingSurface fit(&data, nurbs);
341  // fit.setQuiet (false); // enable/disable debug output
342 
343  // step 3. surface refinement
344  for (int i = 0; i < nurbsParams.refinements_; i++) {
345  fit.refine(0);
346  if (nurbsParams.twoDim_) fit.refine(1);
347  fit.assemble(nurbsParams.fittingParams_);
348  fit.solve();
349  }
350 
351  // step 4. surface fitting with final refinement level
352  for (int i = 0; i < nurbsParams.iterations_; i++) {
353  fit.assemble(nurbsParams.fittingParams_);
354  fit.solve();
355  }
356 
357  // step 5. initialization (circular)
358  if (outCurve) {
359  pcl::on_nurbs::FittingCurve2dAPDM::FitParameter curve_params;
360  {
361  curve_params.addCPsAccuracy = 5e-2;
362  curve_params.addCPsIteration = 3;
363  curve_params.maxCPs = 200;
364  curve_params.accuracy = 1e-3;
365  curve_params.iterations = 100;
366 
367  curve_params.param.closest_point_resolution = 0;
368  curve_params.param.closest_point_weight = 1.0;
369  curve_params.param.closest_point_sigma2 = 0.1;
370  curve_params.param.interior_sigma2 = 0.00001;
371  curve_params.param.smooth_concavity = 1.0;
372  curve_params.param.smoothness = 1.0;
373  }
374 
375  CVLog::Print(
376  "[PCLModules::NurbsSurfaceReconstruction] Start curve fitting "
377  "...");
378  pcl::on_nurbs::NurbsDataCurve2d curve_data;
379  curve_data.interior = data.interior_param;
380  curve_data.interior_weight_function.push_back(true);
381  ON_NurbsCurve curve_nurbs =
382  pcl::on_nurbs::FittingCurve2dAPDM::initNurbsCurve2D(
383  nurbsParams.order_, curve_data.interior);
384  // curve fitting
385  pcl::on_nurbs::FittingCurve2dASDM curve_fit(&curve_data, curve_nurbs);
386  // curve_fit.setQuiet (false); // enable/disable debug output
387  curve_fit.fitting(curve_params);
388 
389  pcl::on_nurbs::Triangulation::convertCurve2PointCloud(
390  curve_fit.m_nurbs, fit.m_nurbs, outCurve,
391  nurbsParams.curveResolution_);
392  CVLog::Print(
393  "[PCLModules::NurbsSurfaceReconstruction] Triangulate trimmed "
394  "surface ...");
395  pcl::on_nurbs::Triangulation::convertTrimmedSurface2PolygonMesh(
396  fit.m_nurbs, curve_fit.m_nurbs, outMesh,
397  nurbsParams.meshResolution_);
398  } else {
399  pcl::on_nurbs::Triangulation::convertSurface2PolygonMesh(
400  fit.m_nurbs, outMesh, nurbsParams.meshResolution_);
401  }
402 
403  CVLog::Print(QString("[PCLModules::NurbsSurfaceReconstruction] Refines: "
404  "%1, Iterations: %2")
405  .arg(nurbsParams.refinements_)
406  .arg(nurbsParams.iterations_));
407  return 1;
408 }
409 
410 enum CurveFittingMethod { PD, SD, APD, TD, ASD };
411 template <typename PointInT>
412 int BSplineCurveFitting2D(
413  const typename pcl::PointCloud<PointInT>::ConstPtr inCloud,
414  const CurveFittingMethod &fittingMethod,
415  PointCloudRGB::Ptr outCurve,
416  int order = 3,
417  int controlPointsNum = 10,
418  unsigned curveResolution = 8,
419  double smoothness = 0.000001,
420  double rScale = 1.0,
421  bool closed = false) {
422  // initialize curve
423  ON_NurbsCurve curve;
424  // curve fitting
425  ON_NurbsCurve nurbs;
426 
427  // convert to NURBS data 2D structure
428  pcl::on_nurbs::NurbsDataCurve2d data;
429  for (unsigned i = 0; i < inCloud->size(); i++) {
430  const PointInT &p = inCloud->at(i);
431  if (!std::isnan(p.x) && !std::isnan(p.y))
432  data.interior.push_back(Eigen::Vector2d(p.x, p.y));
433  }
434 
435  if (closed) {
436  curve = pcl::on_nurbs::FittingCurve2dSDM::initNurbsCurve2D(
437  order, data.interior, controlPointsNum);
438  switch (fittingMethod) {
439  case CurveFittingMethod::PD: {
440  pcl::on_nurbs::FittingCurve2dPDM::Parameter curve_params;
441  curve_params.smoothness = smoothness;
442  curve_params.rScale = rScale;
443 
444  pcl::on_nurbs::FittingCurve2dPDM fit(&data, curve);
445  fit.assemble(curve_params);
446  fit.solve();
447  nurbs = fit.m_nurbs;
448  break;
449  }
450  case CurveFittingMethod::TD: {
451  pcl::on_nurbs::FittingCurve2dTDM::Parameter curve_params;
452  curve_params.smoothness = smoothness;
453  curve_params.rScale = rScale;
454 
455  pcl::on_nurbs::FittingCurve2dTDM fit(&data, curve);
456  fit.assemble(curve_params);
457  fit.solve();
458  nurbs = fit.m_nurbs;
459  break;
460  }
461  case CurveFittingMethod::SD: {
462  pcl::on_nurbs::FittingCurve2dSDM::Parameter curve_params;
463  curve_params.smoothness = smoothness;
464  curve_params.rScale = rScale;
465 
466  pcl::on_nurbs::FittingCurve2dSDM fit(&data, curve);
467  fit.assemble(curve_params);
468  fit.solve();
469  nurbs = fit.m_nurbs;
470  break;
471  }
472  case CurveFittingMethod::APD: {
473  pcl::on_nurbs::FittingCurve2dAPDM::Parameter curve_params;
474  curve_params.smoothness = smoothness;
475  curve_params.rScale = rScale;
476 
477  pcl::on_nurbs::FittingCurve2dAPDM fit(&data, curve);
478  fit.assemble(curve_params);
479  fit.solve();
480  nurbs = fit.m_nurbs;
481  break;
482  }
483  case CurveFittingMethod::ASD: {
484  pcl::on_nurbs::FittingCurve2dASDM::Parameter curve_params;
485  curve_params.smoothness = smoothness;
486  curve_params.rScale = rScale;
487 
488  pcl::on_nurbs::FittingCurve2dASDM fit(&data, curve);
489  fit.assemble(curve_params);
490  fit.solve();
491  nurbs = fit.m_nurbs;
492  break;
493  }
494  default:
495  break;
496  }
497  } else {
498  curve = pcl::on_nurbs::FittingCurve2d::initNurbsPCA(order, &data,
499  controlPointsNum);
500  pcl::on_nurbs::FittingCurve2d::Parameter curve_params;
501  curve_params.smoothness = smoothness;
502  curve_params.rScale = rScale;
503  pcl::on_nurbs::FittingCurve2d fit(&data, curve);
504 
505  fit.assemble(curve_params);
506  fit.solve();
507 
508  // for (int i = 0; i < 3; i++)
509  //{
510  // fit.refine(0);
511  // fit.refine(1);
512  // fit.assemble(curve_params);
513  // fit.solve();
514  // }
515 
516  // for (int i = 0; i < 3; i++)
517  //{
518  // fit.assemble(curve_params);
519  // fit.solve();
520  // }
521 
522  nurbs = fit.m_nurbs;
523  }
524 
525  pcl::on_nurbs::Triangulation::convertCurve2PointCloud(nurbs, outCurve,
526  curveResolution);
527  return 1;
528 }
529 
530 template <typename PointInT>
531 int BSplineCurveFitting3D(
532  const typename pcl::PointCloud<PointInT>::ConstPtr inCloud,
533  PointCloudRGB::Ptr outCurve,
534  int order = 3,
535  int controlPointsNum = 10,
536  unsigned curveResolution = 8,
537  double smoothness = 0.000001,
538  double rScale = 1.0,
539  bool closed = false) {
540  if (closed) {
541  // convert to NURBS data 3D structure
542  pcl::on_nurbs::NurbsDataCurve data;
543  for (unsigned i = 0; i < inCloud->size(); i++) {
544  const PointInT &p = inCloud->at(i);
545  if (!std::isnan(p.x) && !std::isnan(p.y) && !std::isnan(p.z)) {
546  data.interior.push_back(Eigen::Vector3d(p.x, p.y, p.z));
547  }
548  }
549 
550  ON_NurbsCurve curve = pcl::on_nurbs::FittingCurve::initNurbsCurvePCA(
551  order, data.interior, controlPointsNum);
552  pcl::on_nurbs::FittingCurve::Parameter curve_params;
553  curve_params.smoothness = smoothness;
554 
555  pcl::on_nurbs::FittingCurve fit(&data, curve);
556  fit.assemble(curve_params);
557  fit.solve();
558  // fit.m_nurbs.Trim(ON_Interval(
559  // fit.m_nurbs.m_knot[0],
560  // fit.m_nurbs.m_knot[fit.m_nurbs.KnotCount() -
561  // fit.m_nurbs.Order()]
562  //));
563  pcl::on_nurbs::Triangulation::convertCurve2PointCloud(
564  fit.m_nurbs, outCurve, curveResolution);
565  } else {
566  // step 1. xoy plane 2d curve fitting
567  PointCloudRGB::Ptr xoyCurve(new PointCloudRGB);
568  PCLModules::CurveFittingMethod fittingMethod =
569  PCLModules::CurveFittingMethod::PD;
570  if (!PCLModules::BSplineCurveFitting2D<PointInT>(
571  inCloud, fittingMethod, xoyCurve, order, controlPointsNum,
572  curveResolution, smoothness, rScale, closed) ||
573  xoyCurve->size() == 0) {
574  return -1;
575  }
576 
577  PointInT minPt;
578  PointInT maxPt;
579  pcl::getMinMax3D<PointInT>(*inCloud, minPt, maxPt);
580  double dis_x = maxPt.x - minPt.x;
581  double dis_y = maxPt.y - minPt.y;
582 
583  PointCloudRGB::Ptr xozCurve(new PointCloudRGB);
584  PointCloudRGB::Ptr zoyCurve(new PointCloudRGB);
585  if (dis_x > dis_y) {
586  // xoz plane 2d curve fitting
587  typename pcl::PointCloud<PointInT>::Ptr xozCloud(
588  new pcl::PointCloud<PointInT>);
589  SwapAxis<PointInT>(inCloud, xozCloud, "xzy");
590  if (!BSplineCurveFitting2D<PointInT>(
591  xozCloud, fittingMethod, xozCurve, order,
592  controlPointsNum, curveResolution, smoothness, rScale,
593  closed) ||
594  xozCurve->size() == 0) {
595  return -1;
596  }
597  if (xoyCurve->size() != xozCurve->size()) {
598  return -53;
599  }
600 
601  } else {
602  // zoy plane 2d curve fitting
603  typename pcl::PointCloud<PointInT>::Ptr zoyCloud(
604  new pcl::PointCloud<PointInT>);
605  SwapAxis<PointInT>(inCloud, zoyCloud, "zyx");
606  if (!BSplineCurveFitting2D<PointInT>(
607  zoyCloud, fittingMethod, zoyCurve, order,
608  controlPointsNum, curveResolution, smoothness, rScale,
609  closed) ||
610  zoyCurve->size() == 0) {
611  return -1;
612  }
613  if (xoyCurve->size() != zoyCurve->size()) {
614  return -53;
615  }
616  }
617 
618  // out result
619  outCurve->resize(xoyCurve->size());
620  for (unsigned i = 0; i < xoyCurve->size(); ++i) {
621  const PointRGB &xoy_p = xoyCurve->at(i);
622  if (!std::isnan(xoy_p.x) && !std::isnan(xoy_p.y)) {
623  outCurve->points[i].x = xoy_p.x;
624  outCurve->points[i].y = xoy_p.y;
625  if (dis_x > dis_y) {
626  const PointRGB &xoz_p = xozCurve->at(i);
627  outCurve->points[i].z = xoz_p.y;
628  } else {
629  const PointRGB &zoy_p = zoyCurve->at(i);
630  outCurve->points[i].z = zoy_p.x;
631  }
632  }
633  }
634  }
635  return 1;
636 }
637 
638 #endif
639 
641 
650 template <typename PointInT, typename PointOutT>
651 int EstimateSIFT(const typename pcl::PointCloud<PointInT>::ConstPtr inCloud,
652  typename pcl::PointCloud<PointOutT>::Ptr outcloud,
653  int nr_octaves = 0,
654  float min_scale = 0,
655  int nr_scales_per_octave = 0,
656  float min_contrast = 0) {
657  typename pcl::SIFTKeypoint<PointInT, PointOutT> sift_detector;
658  typename pcl::search::KdTree<PointInT>::Ptr tree(
659  new pcl::search::KdTree<PointInT>());
660  sift_detector.setSearchMethod(tree);
661 
662  if (nr_octaves != 0 && min_scale != 0 && nr_scales_per_octave != 0) {
663  sift_detector.setScales(min_scale, nr_octaves, nr_scales_per_octave);
664  }
665 
666  // DGM the min_contrast must be positive
667  sift_detector.setMinimumContrast(min_contrast > 0 ? min_contrast : 0);
668 
669  sift_detector.setInputCloud(inCloud);
670  sift_detector.compute(*outcloud);
671  return 1;
672 }
673 
674 template <typename PointInT,
675  typename NormalType,
676  typename DescriptorType = pcl::SHOT352>
677 int EstimateShot(const typename pcl::PointCloud<PointInT>::ConstPtr inCloud,
678  const typename pcl::PointCloud<PointInT>::ConstPtr keyPoints,
679  const typename pcl::PointCloud<NormalType>::ConstPtr normals,
680  typename pcl::PointCloud<DescriptorType>::Ptr outDescriptors,
681  float searchRadius = 0.03f,
682  int maxThreadCount = QThread::idealThreadCount()) {
683  pcl::SHOTEstimationOMP<PointInT, NormalType, DescriptorType> shot_detector;
684  shot_detector.setRadiusSearch(searchRadius);
685  shot_detector.setNumberOfThreads(maxThreadCount);
686 
687  shot_detector.setInputCloud(keyPoints);
688  shot_detector.setSearchSurface(inCloud);
689  shot_detector.setInputNormals(normals);
690  shot_detector.compute(*outDescriptors);
691  return 1;
692 }
693 
694 template <typename PointInT>
696  const typename pcl::PointCloud<PointInT>::ConstPtr inCloud) {
697  int nres;
698  double res = 0.0;
699  std::vector<int> indices(2);
700  std::vector<float> sqr_distances(2);
701 
702  // Create a search tree, use KDTreee for non-organized data.
703  typename pcl::search::Search<PointInT>::Ptr tree;
704  if (inCloud->isOrganized()) {
705  tree.reset(new pcl::search::OrganizedNeighbor<PointInT>());
706  } else {
707  tree.reset(new pcl::search::KdTree<PointInT>());
708  }
709  tree->setInputCloud(inCloud);
710 
711  int size_cloud = static_cast<int>(inCloud->size());
712 
713  std::vector<float> nn_dis(size_cloud);
714 
715 #ifdef _OPENMP
716 #pragma omp parallel for schedule(static)
717 #endif
718  for (int i = 0; i < size_cloud; ++i) {
719  if (!std::isfinite((*inCloud)[i].x)) {
720  continue;
721  }
722 
723  // Considering the second neighbor since the first is the point itself.
724  nres = tree->nearestKSearch(i, 2, indices, sqr_distances);
725  if (nres == 2) {
726  nn_dis[i] = std::sqrt(sqr_distances[1]);
727  // res += sqr_distances[1];
728  //++n_points;
729  } else {
731  "[ComputeCloudResolution] Found a point without "
732  "neighbors.");
733  nn_dis[i] = 0.0f;
734  }
735  }
736 
737  // if (n_points != 0)
738  //{
739  // //res /= n_points;
740  // res = sqrt(res / n_points);
741  // }
742 
743  res = std::accumulate(std::begin(nn_dis), std::end(nn_dis), 0.0f) /
744  size_cloud;
745  return res;
746 }
747 
748 template <typename PointOutT>
749 int RemoveOutliersStatistical(const typename PointOutT::ConstPtr inCloud,
750  typename PointOutT::Ptr outCloud,
751  int knn,
752  double nSigma) {
753  pcl::StatisticalOutlierRemoval<PointOutT> remover;
754  remover.setInputCloud(inCloud);
755  remover.setMeanK(knn);
756  remover.setStddevMulThresh(nSigma);
757  remover.filter(*outCloud);
758  return 1;
759 }
760 
761 template <typename PointInT>
762 int EuclideanCluster(const typename pcl::PointCloud<PointInT>::ConstPtr inCloud,
763  std::vector<pcl::PointIndices> &cluster_indices,
764  float clusterTolerance = 0.02f,
765  int minClusterSize = 100,
766  int maxClusterSize = 250000) {
767  // Creating the KdTree object for the search method of the extraction
768  typename pcl::search::KdTree<PointInT>::Ptr tree(
769  new pcl::search::KdTree<PointInT>);
770  tree->setInputCloud(inCloud); //
771 
772  pcl::EuclideanClusterExtraction<PointInT> ece;
773  ece.setClusterTolerance(clusterTolerance); //
774  ece.setMinClusterSize(minClusterSize); //
775  ece.setMaxClusterSize(maxClusterSize); //
776  ece.setSearchMethod(tree); //
777  ece.setInputCloud(inCloud);
778  ece.extract(cluster_indices); //
779 
780  return 1;
781 }
782 
783 template <typename PointInT>
785  const typename pcl::PointCloud<PointInT>::ConstPtr inCloud,
786  pcl::PointIndicesPtr groundIndices,
787  int maxWindowSize = 20,
788  float slope = 1.0f,
789  float initialDistance = 0.5f,
790  float maxDistance = 3.0f) {
791  // Create the filtering object
792  pcl::ProgressiveMorphologicalFilter<PointInT> pmf;
793  pmf.setInputCloud(inCloud);
794  pmf.setMaxWindowSize(maxWindowSize);
795  pmf.setSlope(slope);
796  pmf.setInitialDistance(initialDistance);
797  pmf.setMaxDistance(maxDistance);
798  pmf.extract(groundIndices->indices);
799 
800  return 1;
801 }
802 
803 template <typename PointInT, typename NormalType, typename PointOutT>
805  const typename pcl::PointCloud<PointInT>::ConstPtr inCloud,
806  const typename pcl::PointCloud<NormalType>::ConstPtr normalsLargeScale,
807  const typename pcl::PointCloud<NormalType>::ConstPtr normalsSmallScale,
808  typename pcl::PointCloud<PointOutT>::Ptr outCloud) {
809  // Create DoN operator
810  pcl::DifferenceOfNormalsEstimation<PointInT, NormalType, PointOutT> don;
811  don.setInputCloud(inCloud);
812  don.setNormalScaleLarge(normalsLargeScale);
813  don.setNormalScaleSmall(normalsSmallScale);
814 
815  if (!don.initCompute()) {
816  return -1;
817  }
818 
819  // Compute DoN
820  don.computeFeature(*outCloud);
821  return 1;
822 }
823 
824 template <typename PointInT,
825  typename NormalType,
826  typename RFType = pcl::ReferenceFrame>
828  const typename pcl::PointCloud<PointInT>::ConstPtr inCloud,
829  const typename pcl::PointCloud<PointInT>::ConstPtr keyPoints,
830  const typename pcl::PointCloud<NormalType>::ConstPtr normals,
831  typename pcl::PointCloud<RFType>::Ptr outRF,
832  float searchRadius = 0.015f) {
833  pcl::BOARDLocalReferenceFrameEstimation<PointInT, NormalType, RFType>
834  rf_detector;
835  rf_detector.setRadiusSearch(searchRadius);
836  rf_detector.setFindHoles(true);
837  rf_detector.setInputCloud(keyPoints);
838  rf_detector.setInputNormals(normals);
839  rf_detector.setSearchSurface(inCloud);
840  rf_detector.compute(*outRF);
841  return 1;
842 }
843 
844 template <typename PointModelT,
845  typename PointSceneT,
846  typename PointModelRfT = pcl::ReferenceFrame,
847  typename PointSceneRfT = pcl::ReferenceFrame>
849  const typename pcl::PointCloud<PointModelT>::ConstPtr modelKeypoints,
850  const typename pcl::PointCloud<PointSceneT>::ConstPtr sceneKeypoints,
851  const typename pcl::PointCloud<PointModelRfT>::ConstPtr modelRF,
852  const typename pcl::PointCloud<PointSceneRfT>::ConstPtr sceneRF,
853  const typename pcl::CorrespondencesConstPtr modelSceneCorrs,
854  std::vector<Eigen::Matrix4f, Eigen::aligned_allocator<Eigen::Matrix4f>>
855  &rotoTranslations,
856  std::vector<pcl::Correspondences> &clusteredCorrs,
857  float houghBinSize = 0.01f,
858  float houghThreshold = 5.0f) {
859  pcl::Hough3DGrouping<PointModelT, PointSceneT, PointModelRfT, PointSceneRfT>
860  clusterer;
861  clusterer.setHoughBinSize(houghBinSize); //
862  clusterer.setHoughThreshold(houghThreshold); //
863  clusterer.setUseInterpolation(true); //
864  clusterer.setUseDistanceWeight(false); //
865 
866  clusterer.setInputCloud(modelKeypoints);
867  clusterer.setInputRf(modelRF);
868  clusterer.setSceneCloud(sceneKeypoints);
869  clusterer.setSceneRf(sceneRF);
870  clusterer.setModelSceneCorrespondences(modelSceneCorrs);
871 
872  bool flag = clusterer.recognize(rotoTranslations, clusteredCorrs);
873 
874  return flag ? 1 : -1;
875 }
876 
877 template <typename PointModelT, typename PointSceneT>
879  const typename pcl::PointCloud<PointModelT>::ConstPtr modelKeypoints,
880  const typename pcl::PointCloud<PointSceneT>::ConstPtr sceneKeypoints,
881  const typename pcl::CorrespondencesConstPtr modelSceneCorrs,
882  std::vector<Eigen::Matrix4f, Eigen::aligned_allocator<Eigen::Matrix4f>>
883  &rotoTranslations,
884  std::vector<pcl::Correspondences> &clusteredCorrs,
885  float gcSize = 0.01f,
886  float gcThreshold = 20.0f) {
887  pcl::GeometricConsistencyGrouping<PointModelT, PointSceneT> gc_clusterer;
888  gc_clusterer.setGCSize(gcSize); //
889  gc_clusterer.setGCThreshold(gcThreshold); //
890 
891  gc_clusterer.setInputCloud(modelKeypoints);
892  gc_clusterer.setSceneCloud(sceneKeypoints);
893  gc_clusterer.setModelSceneCorrespondences(modelSceneCorrs);
894 
895  bool flag = gc_clusterer.recognize(rotoTranslations, clusteredCorrs);
896 
897  return flag ? 1 : -1;
898 }
899 
900 template <typename PointInT>
901 int EstimateHarris3D(const typename pcl::PointCloud<PointInT>::ConstPtr inCloud,
902  pcl::PointCloud<pcl::PointXYZI>::Ptr outcloud,
903  float normalRadius = 0.1f,
904  float searchRadius = 0.1f) {
905  pcl::HarrisKeypoint3D<PointInT, pcl::PointXYZI, NormalT> harris_detector;
906 
907  harris_detector.setRadius(normalRadius); //
908  harris_detector.setRadiusSearch(searchRadius); //
909 
910  harris_detector.setInputCloud(inCloud);
911  harris_detector.compute(*outcloud);
912  return 1;
913 }
914 
915 template <typename PointInOut>
917  const typename pcl::PointCloud<PointInOut>::ConstPtr inCloud,
918  typename pcl::PointCloud<PointInOut>::Ptr outcloud,
919  const float &searchRadius = -1.0f /*0.03f*/) {
920  pcl::UniformSampling<PointInOut> uniform_sampling;
921 
922  if (searchRadius < 0) {
923  float cloudResolution =
924  static_cast<float>(ComputeCloudResolution<PointInOut>(inCloud));
925  assert(cloudResolution);
926  uniform_sampling.setRadiusSearch(10 * cloudResolution);
927  } else {
928  uniform_sampling.setRadiusSearch(searchRadius);
929  }
930 
931  uniform_sampling.setInputCloud(inCloud);
932  uniform_sampling.filter(*outcloud);
933  return 1;
934 }
935 
938  enum ConditionType { CONDITION_OR, CONDITION_AND };
939  enum ComparisonType { GT, GE, LT, LE, EQ };
940 
943  std::string fieldName_;
946  };
947 
948  ConditionParameters() : condition_type_(CONDITION_OR) {}
949 
951  std::vector<ComparisonParam> condition_params_;
952 };
953 
954 template <typename PointInOut>
956  const typename pcl::PointCloud<PointInOut>::ConstPtr inCloud,
957  const ConditionParameters &params,
958  typename pcl::PointCloud<PointInOut>::Ptr outCloud,
959  bool keepOrganized = false) {
960  typename pcl::ConditionBase<PointInOut>::Ptr condition;
961  switch (params.condition_type_) {
962  case ConditionParameters::ConditionType::CONDITION_OR: {
963  // Build the condition or for filtering
964  typename pcl::ConditionOr<PointInOut>::Ptr range_cond(
965  new pcl::ConditionOr<PointInOut>());
966  condition = range_cond;
967  break;
968  }
969  case ConditionParameters::ConditionType::CONDITION_AND: {
970  typename pcl::ConditionAnd<PointInOut>::Ptr range_cond(
971  new pcl::ConditionAnd<PointInOut>());
972  condition = range_cond;
973  break;
974  }
975  default:
976  break;
977  }
978 
979  for (size_t i = 0; i < params.condition_params_.size(); ++i) {
981  pcl::ComparisonOps::CompareOp ops =
982  static_cast<pcl::ComparisonOps::CompareOp>(
983  static_cast<int>(cp.comparison_type_));
984  double threshod = 0.0;
985  if (pcl::ComparisonOps::CompareOp::GT == ops ||
986  pcl::ComparisonOps::CompareOp::GE == ops) {
987  threshod = cp.min_threshold_;
988  } else if (pcl::ComparisonOps::CompareOp::LT == ops ||
989  pcl::ComparisonOps::CompareOp::LE == ops) {
990  threshod = cp.max_threshold_;
991  } else {
992  threshod = (cp.max_threshold_ + cp.min_threshold_) * 0.5;
993  }
994  condition->addComparison(
995  typename pcl::FieldComparison<PointInOut>::ConstPtr(
996  new pcl::FieldComparison<PointInOut>(cp.fieldName_, ops,
997  threshod)));
998  }
999 
1000  if (!condition->isCapable()) {
1001  return -1;
1002  }
1003 
1004  // Build the conditionRemoval Filter
1005  typename pcl::ConditionalRemoval<PointInOut> condrem(false);
1006  condrem.setCondition(condition);
1007  condrem.setInputCloud(inCloud);
1008  condrem.setKeepOrganized(keepOrganized);
1009  // Apply filter
1010  condrem.filter(*outCloud);
1011 
1012  return 1;
1013 }
1014 
1021  VOXEL_GRID_DILATION
1022  };
1023 
1025  : order_(0),
1026  polynomial_fit_(false),
1027  search_radius_(0),
1028  sqr_gauss_param_(0),
1029  compute_normals_(false),
1030  upsample_method_(NONE),
1031  upsampling_radius_(0),
1032  upsampling_step_(0),
1033  step_point_density_(0),
1034  dilation_voxel_size_(0),
1035  dilation_iterations_(0) {}
1036 
1037  int order_;
1048 };
1049 
1050 // for smooth filter
1051 template <typename PointInT, typename PointOutT>
1052 int SmoothMls(const typename pcl::PointCloud<PointInT>::ConstPtr &inCloud,
1053  const MLSParameters &params,
1054  typename pcl::PointCloud<PointOutT>::Ptr &outcloud
1055 #ifdef LP_PCL_PATCH_ENABLED
1056  ,
1057  pcl::PointIndicesPtr &mapping_ids
1058 #endif
1059 ) {
1060  typename pcl::search::KdTree<PointInT>::Ptr tree(
1061  new pcl::search::KdTree<PointInT>);
1062 
1063  // create the smoothing object
1064  pcl::MovingLeastSquares<PointInT, PointOutT> smoother;
1065  int n_threads = cloudViewer::utility::EstimateMaxThreads();
1066  smoother.setNumberOfThreads(n_threads);
1067 
1068  smoother.setInputCloud(inCloud);
1069  smoother.setSearchMethod(tree);
1070  smoother.setSearchRadius(params.search_radius_);
1071  smoother.setComputeNormals(params.compute_normals_);
1072  if (params.polynomial_fit_) {
1073  smoother.setPolynomialOrder(params.order_);
1074  smoother.setSqrGaussParam(params.sqr_gauss_param_);
1075  } else {
1076  smoother.setPolynomialOrder(0);
1077  }
1078 
1079  switch (params.upsample_method_) {
1080  case (MLSParameters::NONE): {
1081  smoother.setUpsamplingMethod(
1082  pcl::MovingLeastSquares<PointInT, PointOutT>::NONE);
1083  // no need to set other parameters here!
1084  break;
1085  }
1086 
1088  smoother.setUpsamplingMethod(
1089  pcl::MovingLeastSquares<PointInT,
1090  PointOutT>::SAMPLE_LOCAL_PLANE);
1091  smoother.setUpsamplingRadius(params.upsampling_radius_);
1092  smoother.setUpsamplingStepSize(params.upsampling_step_);
1093  break;
1094  }
1095 
1097  smoother.setUpsamplingMethod(
1098  pcl::MovingLeastSquares<PointInT,
1099  PointOutT>::RANDOM_UNIFORM_DENSITY);
1100  smoother.setPointDensity(params.step_point_density_);
1101  break;
1102  }
1103 
1105  smoother.setUpsamplingMethod(
1106  pcl::MovingLeastSquares<PointInT,
1107  PointOutT>::VOXEL_GRID_DILATION);
1108  smoother.setDilationVoxelSize(
1109  static_cast<float>(params.dilation_voxel_size_));
1110  smoother.setDilationIterations(params.dilation_iterations_);
1111  break;
1112  }
1113  }
1114 
1115  smoother.process(*outcloud);
1116 
1117 #ifdef LP_PCL_PATCH_ENABLED
1118  mapping_ids = smoother.getCorrespondingIndices();
1119 #endif
1120  return 1;
1121 }
1122 
1123 // for normal estimation
1124 template <typename PointInT, typename PointOutT>
1126  const typename pcl::PointCloud<PointInT>::ConstPtr inCloud,
1127  typename pcl::PointCloud<PointOutT>::Ptr outcloud,
1128  const float radius = -1.0f /*10.0f*/,
1129  const bool useKnn = true, // true if use knn, false if radius search
1130  bool normalConsistency = false,
1131  int maxThreadCount = QThread::idealThreadCount()) {
1132  typename pcl::NormalEstimationOMP<PointInT, PointOutT> normal_estimator;
1133 
1134  // Create a search tree, use KDTreee for non-organized data.
1135  typename pcl::search::Search<PointInT>::Ptr tree;
1136  if (inCloud->isOrganized()) {
1137  tree.reset(new pcl::search::OrganizedNeighbor<PointInT>());
1138  } else {
1139  tree.reset(new pcl::search::KdTree<PointInT>());
1140  }
1141  tree->setInputCloud(inCloud);
1142 
1143  normal_estimator.setSearchMethod(tree);
1144 
1145  if (useKnn) // use knn
1146  {
1147  int knn_radius = static_cast<int>(radius); // cast to int
1148  normal_estimator.setKSearch(knn_radius);
1149  } else // use radius search
1150  {
1151  if (radius < 0) {
1152  float cloudResolution = static_cast<float>(
1153  ComputeCloudResolution<PointInT>(inCloud));
1154  assert(cloudResolution);
1155  normal_estimator.setRadiusSearch(10 * cloudResolution);
1156  } else {
1157  normal_estimator.setRadiusSearch(radius);
1158  }
1159  }
1160 
1161  if (normalConsistency) {
1166  normal_estimator.setViewPoint(std::numeric_limits<float>::max(),
1167  std::numeric_limits<float>::max(),
1168  std::numeric_limits<float>::max());
1169  }
1170 
1171  normal_estimator.setInputCloud(inCloud);
1172  normal_estimator.setNumberOfThreads(maxThreadCount);
1173  normal_estimator.compute(*outcloud);
1174 
1175  return 1;
1176 }
1177 
1178 template <typename PointInOut>
1180  const typename pcl::PointCloud<PointInOut>::ConstPtr inCloud,
1181  typename pcl::PointCloud<PointInOut>::Ptr outcloud,
1182  const QString &filterFieldName = "z",
1183  const float &limit_min = 0.1f,
1184  const float &limit_max = 1.1f) {
1185  pcl::PassThrough<PointInOut> pass;
1186  pass.setInputCloud(inCloud);
1187  pass.setFilterFieldName(filterFieldName.toStdString());
1188  pass.setFilterLimits(limit_min, limit_max);
1189  pass.filter(*outcloud);
1190  return 1;
1191 }
1192 
1193 template <typename PointInOut>
1195  const typename pcl::PointCloud<PointInOut>::ConstPtr inCloud,
1196  typename pcl::PointCloud<PointInOut>::Ptr outcloud,
1197  const float &leafSizeX = -0.01f,
1198  const float &leafSizeY = -0.01f,
1199  const float &leafSizeZ = -0.01f) {
1200  // Create the filtering object: downsample the dataset using a leaf size of
1201  // 1cm
1202  pcl::VoxelGrid<PointInOut> vg;
1203  vg.setInputCloud(inCloud);
1204  if (leafSizeX < 0 || leafSizeY < 0 || leafSizeZ < 0) {
1205  float cloudResolution =
1206  static_cast<float>(ComputeCloudResolution<PointInOut>(inCloud));
1207  assert(cloudResolution);
1208  float newLeafSize = 10 * cloudResolution;
1209  vg.setLeafSize(newLeafSize, newLeafSize, newLeafSize);
1210  } else {
1211  vg.setLeafSize(leafSizeX, leafSizeY, leafSizeZ);
1212  }
1213 
1214  vg.filter(*outcloud);
1215  if (outcloud->points.size() == inCloud->points.size()) {
1217  "[PCLModules::VoxelGridFilter] leaf size is too small, voxel "
1218  "grid filter failed!");
1219  } else {
1220  CVLog::Print(QString("[PCLModules::VoxelGridFilter] Filter original "
1221  "size[%1] to size[%2]!")
1222  .arg(inCloud->size())
1223  .arg(outcloud->size()));
1224  }
1225  return 1;
1226 }
1227 
1228 template <typename PointInOut>
1230  const typename pcl::PointCloud<PointInOut>::ConstPtr inCloud,
1231  const pcl::PointIndices::ConstPtr inliers,
1232  typename pcl::PointCloud<PointInOut>::Ptr outcloud = nullptr,
1233  typename pcl::PointCloud<PointInOut>::Ptr outcloud2 = nullptr) {
1234  pcl::ExtractIndices<PointInOut> extract;
1235  extract.setInputCloud(inCloud);
1236  extract.setIndices(inliers);
1237 
1238  if (outcloud) {
1239  extract.setNegative(false);
1240  extract.filter(*outcloud);
1241  }
1242 
1243  if (outcloud2) {
1244  extract.setNegative(true);
1245  extract.filter(*outcloud2);
1246  }
1247  return 1;
1248 }
1249 
1250 // for convexHull reconstruction
1251 template <typename PointInT>
1253  const typename pcl::PointCloud<PointInT>::ConstPtr inCloud,
1254  PCLMesh &outMesh,
1255  int dimension = 3) {
1256  pcl::ConvexHull<PointInT> hull;
1257  hull.setInputCloud(inCloud);
1258  hull.setDimension(dimension);
1259 
1260  typename pcl::PointCloud<PointInT>::Ptr surface_hull(
1261  new pcl::PointCloud<PointInT>());
1262  hull.reconstruct(*surface_hull, outMesh.polygons);
1263 
1264  CVLog::Print(QString("convex hull area [1%], convex hull volume [%2]")
1265  .arg(hull.getTotalArea())
1266  .arg(hull.getTotalVolume()));
1267 
1268  // Convert the PointCloud into a PCLPointCloud2
1269  TO_PCL_CLOUD(*surface_hull, outMesh.cloud);
1270 
1271  return 1;
1272 }
1273 
1274 // for concaveHull reconstruction
1275 template <typename PointInT>
1277  const typename pcl::PointCloud<PointInT>::ConstPtr inCloud,
1278  PCLMesh &outMesh,
1279  int dimension = 3,
1280  float alpha = 0.05f) {
1281  pcl::ConcaveHull<PointInT> chull;
1282  chull.setInputCloud(inCloud);
1283  chull.setAlpha(alpha);
1284  chull.setDimension(dimension);
1285  typename pcl::PointCloud<PointInT>::Ptr surface_hull(
1286  new pcl::PointCloud<PointInT>());
1287  chull.reconstruct(*surface_hull, outMesh.polygons);
1288 
1289  // Convert the PointCloud into a PCLPointCloud2
1290  TO_PCL_CLOUD(*surface_hull, outMesh.cloud);
1291 
1292  return 1;
1293 }
1294 
1295 template <typename PointInT>
1296 int CropHullFilter(const typename pcl::PointCloud<PointInT>::ConstPtr inCloud,
1297  const PointCloudT::ConstPtr boundingBox,
1298  typename pcl::PointCloud<PointInT>::Ptr outCloud,
1299  int dimensions = 2) {
1300  // reconstruction
1301  PCLMesh mesh;
1302  if (!PCLModules::GetConvexHullReconstruction<PointT>(boundingBox, mesh,
1303  dimensions)) {
1304  return -1;
1305  }
1306 
1307  pcl::CropHull<PointInT> bb_filter;
1308  bb_filter.setInputCloud(inCloud);
1309  bb_filter.setDim(dimensions);
1310  bb_filter.setHullIndices(mesh.polygons);
1311  typename pcl::PointCloud<PointInT>::Ptr surface_hull(
1312  new pcl::PointCloud<PointInT>);
1313  FROM_PCL_CLOUD(mesh.cloud, *surface_hull);
1314  if (surface_hull->width * surface_hull->height == 0) {
1315  return -1;
1316  }
1317  bb_filter.setHullCloud(surface_hull);
1318  bb_filter.filter(*outCloud);
1319  return 1;
1320 }
1321 
1322 template <typename PointInT>
1324  const typename pcl::PointCloud<PointInT>::ConstPtr inCloud,
1325  std::vector<pcl::PointIndices> &outClusters,
1326  PointCloudRGB::Ptr cloud_segmented,
1327  const PointInT foregroundPoint,
1328  int neighboursNumber = 14,
1329  float smoothSigma = 0.25f,
1330  float backWeightRadius = 0.8f,
1331  float foreWeight = 0.5f,
1332  const pcl::IndicesConstPtr indices = nullptr) {
1333  typename pcl::MinCutSegmentation<PointInT> seg;
1334  seg.setInputCloud(inCloud);
1335  if (indices) {
1336  seg.setIndices(indices);
1337  }
1338 
1339  typename pcl::PointCloud<PointInT>::Ptr foreground_points(
1340  new pcl::PointCloud<PointInT>());
1341  foreground_points->points.push_back(foregroundPoint);
1342  seg.setForegroundPoints(foreground_points);
1343 
1344  seg.setSigma(smoothSigma);
1345  seg.setRadius(backWeightRadius);
1346  seg.setNumberOfNeighbours(neighboursNumber);
1347  seg.setSourceWeight(foreWeight);
1348  seg.extract(outClusters);
1349  pcl::copyPointCloud(*seg.getColoredCloud(), *cloud_segmented);
1350 
1351  return 1;
1352 }
1353 
1354 template <typename PointInOut, typename NormalType>
1356  const typename pcl::PointCloud<PointInOut>::ConstPtr inCloud,
1357  const typename pcl::PointCloud<NormalType>::ConstPtr normals,
1358  typename pcl::PointCloud<PointInOut>::Ptr boundaryCloud,
1359  const float angleThreshold =
1360  90.0f, // 45.0f for radius search && 90.0f for knn search
1361  const float radius =
1362  -1.0f, // 0.05f for radius search && 20.0f for knn search
1363  const bool useKnn = true // true if use knn, false if radius search
1364 ) {
1365  pcl::BoundaryEstimation<PointInOut, NormalType, pcl::Boundary> boundEst;
1366  pcl::PointCloud<pcl::Boundary> boundaries;
1367  boundEst.setInputCloud(inCloud);
1368  boundEst.setInputNormals(normals);
1369  if (useKnn) {
1370  boundEst.setKSearch(int(radius)); // the bigger the more accurate
1371  } else // slow
1372  {
1373  if (radius < 0) {
1374  float cloudResolution = static_cast<float>(
1375  ComputeCloudResolution<PointInOut>(inCloud));
1376  assert(cloudResolution);
1377  boundEst.setRadiusSearch(10 * cloudResolution);
1378  } else {
1379  boundEst.setRadiusSearch(radius);
1380  }
1381  }
1382 
1383  typename pcl::search::KdTree<PointInOut>::Ptr searchTree(
1384  new pcl::search::KdTree<PointInOut>());
1385  boundEst.setSearchMethod(searchTree);
1386  boundEst.setAngleThreshold(cloudViewer::DegreesToRadians(angleThreshold));
1387  boundEst.compute(boundaries);
1388 
1389  boundaryCloud->clear();
1390  for (size_t i = 0; i < inCloud->size(); i++) {
1391  if (boundaries[i].boundary_point > 0) {
1392  boundaryCloud->push_back(inCloud->points[i]);
1393  }
1394  }
1395 
1396  return 1;
1397 }
1398 
1399 template <typename PointInT, typename PointOutT>
1401  const typename pcl::PointCloud<PointInT>::ConstPtr targetCloud,
1402  const typename pcl::PointCloud<PointOutT>::ConstPtr sourceCloud,
1403  typename pcl::PointCloud<PointOutT>::Ptr outRegistered,
1404  int ipcMaxIterations = 5,
1405  float icpCorrDistance = 0.005f) {
1406  pcl::IterativeClosestPoint<PointInT, PointOutT> icp;
1407  icp.setMaximumIterations(ipcMaxIterations);
1408  icp.setMaxCorrespondenceDistance(icpCorrDistance);
1409  icp.setInputTarget(targetCloud);
1410  icp.setInputSource(sourceCloud);
1411  icp.align(*outRegistered);
1412 
1413  return icp.hasConverged();
1414 }
1415 #if 0
1416  template <typename PointSceneT, typename PointModelT>
1417  int GetHypothesesVerification(
1418  const typename pcl::PointCloud<PointSceneT>::Ptr sceneCloud,
1419  std::vector<typename pcl::PointCloud<PointModelT>::ConstPtr> modelClouds,
1420  std::vector<bool> &hypothesesMask,
1421  float clusterReg = 5.0f,
1422  float inlierThreshold = 0.005f,
1423  float occlusionThreshold = 0.01f,
1424  float radiusClutter = 0.03f,
1425  float regularizer = 3.0f,
1426  float radiusNormals = 0.05f,
1427  bool detectClutter = true)
1428  {
1429  pcl::GlobalHypothesesVerification<PointModelT, PointSceneT> GoHv;
1430  GoHv.setSceneCloud(sceneCloud); // Scene Cloud
1431  GoHv.addModels(modelClouds, true); // Models to verify
1432 
1433  GoHv.setInlierThreshold(inlierThreshold);
1434  GoHv.setOcclusionThreshold(occlusionThreshold);
1435  GoHv.setRadiusClutter(radiusClutter);
1436  GoHv.setClutterRegularizer(clusterReg);
1437  GoHv.setRegularizer(regularizer);
1438  GoHv.setRadiusNormals(radiusNormals);
1439  GoHv.setDetectClutter(detectClutter);
1440 
1441  GoHv.verify();
1442  GoHv.getMask(hypothesesMask); // i-element TRUE if hvModels[i] verifies hypotheses
1443 
1444  return 1;
1445  }
1446 #endif
1447 } // namespace PCLModules
1448 
1449 // class
1450 namespace PCLModules {
1452 public:
1453  // A bit of shorthand
1454  typedef pcl::PointCloud<NormalT> SurfaceNormals;
1455  typedef pcl::PointCloud<pcl::FPFHSignature33> LocalFeatures;
1456  typedef pcl::search::KdTree<PointT> SearchMethod;
1457 
1458  FeatureCloud();
1460 
1461  void setNormalRadius(float normalRadius) { m_normalRadius = normalRadius; }
1462  void setFeatureRadius(float featureRadius) {
1463  m_featureRadius = featureRadius;
1464  }
1465  void setmaxThreadCount(int maxThreadCount) {
1466  m_maxThreadCount = maxThreadCount;
1467  }
1468 
1469  // Process the given cloud
1470  void setInputCloud(PointCloudT::Ptr xyz) {
1471  m_xyz = xyz;
1472  processInput();
1473  }
1474 
1475  // Load and process the cloud in the given PCD file
1476  void loadInputCloud(const std::string &pcd_file);
1477 
1478  // Get a pointer to the cloud 3D points
1479  PointCloudT::Ptr getPointCloud() const { return (m_xyz); }
1480 
1481  // Get a pointer to the cloud of 3D surface normals
1482  SurfaceNormals::Ptr getSurfaceNormals() const { return (m_normals); }
1483 
1484  // Get a pointer to the cloud of feature descriptors
1485  LocalFeatures::Ptr getLocalFeatures() const { return (m_features); }
1486 
1487 protected:
1488  // Compute the surface normals and local features
1489  void processInput() {
1490  computeSurfaceNormals();
1491  computeLocalFeatures();
1492  }
1493 
1494  // Compute the surface normals
1495  void computeSurfaceNormals();
1496 
1497  // Compute the local feature descriptors
1498  void computeLocalFeatures();
1499 
1500 private:
1501  // Point cloud data
1502  PointCloudT::Ptr m_xyz;
1503  SurfaceNormals::Ptr m_normals;
1504  LocalFeatures::Ptr m_features;
1505  SearchMethod::Ptr m_searchMethod;
1506 
1507  // Parameters
1508  float m_normalRadius;
1509  float m_featureRadius;
1510  int m_maxThreadCount;
1511 };
1512 
1514 public:
1515  // A struct for storing alignment results
1516  struct Result {
1518  Eigen::Matrix4f final_transformation;
1519  };
1520 
1521  TemplateMatching();
1523 
1524  void setminSampleDis(float minSampleDistance) {
1525  m_minSampleDistance = minSampleDistance;
1526  }
1527  void setmaxCorrespondenceDis(float maxCorrespondenceDistance) {
1528  m_maxCorrespondenceDistance = maxCorrespondenceDistance;
1529  }
1530  void setmaxIterations(int maxIterations) {
1531  m_nr_iterations = maxIterations;
1532  }
1533 
1534  // Set the given cloud as the target to which the templates will be aligned
1535  void setTargetCloud(FeatureCloud &target_cloud);
1536 
1537  // Add the given cloud to the list of template clouds
1538  void addTemplateCloud(FeatureCloud &template_cloud) {
1539  m_templates.push_back(template_cloud);
1540  }
1541 
1542  // get the template cloud by the given index
1544  if (static_cast<size_t>(index) > m_templates.size()) return nullptr;
1545  return &m_templates[static_cast<size_t>(index)];
1546  }
1547 
1548  // Align the given template cloud to the target specified by setTargetCloud
1549  // ()
1550  void align(FeatureCloud &template_cloud, TemplateMatching::Result &result);
1551 
1552  // Align all of template clouds set by addTemplateCloud to the target
1553  // specified by setTargetCloud ()
1554  void alignAll(std::vector<TemplateMatching::Result,
1555  Eigen::aligned_allocator<Result>> &results);
1556 
1557  // Align all of template clouds to the target cloud to find the one with
1558  // best alignment score
1559  int findBestAlignment(TemplateMatching::Result &result);
1560 
1561  void clear() { m_templates.clear(); }
1562 
1563 private:
1564  // A list of template clouds and the target to which they will be aligned
1565  std::vector<FeatureCloud> m_templates;
1566  FeatureCloud m_target;
1567 
1568  // The Sample Consensus Initial Alignment (SAC-IA) registration routine and
1569  // its parameters
1570  pcl::SampleConsensusInitialAlignment<PointT, PointT, pcl::FPFHSignature33>
1571  m_sac_ia;
1572  float m_minSampleDistance;
1573  float m_maxCorrespondenceDistance;
1574  int m_nr_iterations;
1575 };
1576 
1577 } // namespace PCLModules
pcl::PointXYZRGB PointRGB
Definition: PCLCloud.h:20
pcl::PointCloud< PointRGB > PointCloudRGB
Definition: PCLCloud.h:21
pcl::PolygonMesh PCLMesh
Definition: PCLCloud.h:31
#define TO_PCL_CLOUD
Definition: PCLConv.h:12
#define FROM_PCL_CLOUD
Definition: PCLConv.h:11
core::Tensor result
Definition: VtkUtils.cpp:76
static bool WarningDebug(const char *format,...)
Same as Warning, but works only in Debug mode.
Definition: CVLog.cpp:167
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
Definition: CVLog.cpp:133
static bool Print(const char *format,...)
Prints out a formatted message in console.
Definition: CVLog.cpp:113
pcl::PointCloud< pcl::FPFHSignature33 > LocalFeatures
Definition: PCLModules.h:1455
pcl::search::KdTree< PointT > SearchMethod
Definition: PCLModules.h:1456
void setmaxThreadCount(int maxThreadCount)
Definition: PCLModules.h:1465
pcl::PointCloud< NormalT > SurfaceNormals
Definition: PCLModules.h:1454
void setNormalRadius(float normalRadius)
Definition: PCLModules.h:1461
void setInputCloud(PointCloudT::Ptr xyz)
Definition: PCLModules.h:1470
LocalFeatures::Ptr getLocalFeatures() const
Definition: PCLModules.h:1485
SurfaceNormals::Ptr getSurfaceNormals() const
Definition: PCLModules.h:1482
void setFeatureRadius(float featureRadius)
Definition: PCLModules.h:1462
PointCloudT::Ptr getPointCloud() const
Definition: PCLModules.h:1479
void addTemplateCloud(FeatureCloud &template_cloud)
Definition: PCLModules.h:1538
void setminSampleDis(float minSampleDistance)
Definition: PCLModules.h:1524
void setmaxCorrespondenceDis(float maxCorrespondenceDistance)
Definition: PCLModules.h:1527
void setmaxIterations(int maxIterations)
Definition: PCLModules.h:1530
FeatureCloud * getTemplateCloud(int index)
Definition: PCLModules.h:1543
double normals[3]
const double * e
GraphType data
Definition: graph_cut.cc:138
normal_z y
normal_z x
normal_z z
int GetConvexHullReconstruction(const typename pcl::PointCloud< PointInT >::ConstPtr inCloud, PCLMesh &outMesh, int dimension=3)
Definition: PCLModules.h:1252
int GetGreedyTriangulation(const PointCloudNormal::ConstPtr &cloudWithNormals, PCLMesh &outMesh, int trigulationSearchRadius, float weightingFactor, int maxNearestNeighbors, int maxSurfaceAngle, int minAngle, int maxAngle, bool normalConsistency)
Definition: PCLModules.cpp:270
int EstimateGeometricConsistencyGrouping(const typename pcl::PointCloud< PointModelT >::ConstPtr modelKeypoints, const typename pcl::PointCloud< PointSceneT >::ConstPtr sceneKeypoints, const typename pcl::CorrespondencesConstPtr modelSceneCorrs, std::vector< Eigen::Matrix4f, Eigen::aligned_allocator< Eigen::Matrix4f >> &rotoTranslations, std::vector< pcl::Correspondences > &clusteredCorrs, float gcSize=0.01f, float gcThreshold=20.0f)
Definition: PCLModules.h:878
int GetUniformSampling(const typename pcl::PointCloud< PointInOut >::ConstPtr inCloud, typename pcl::PointCloud< PointInOut >::Ptr outcloud, const float &searchRadius=-1.0f)
Definition: PCLModules.h:916
int RemoveNaN(const typename pcl::PointCloud< PointInT >::ConstPtr inCloud, typename pcl::PointCloud< PointInT >::Ptr outcloud, std::vector< int > &index)
Definition: PCLModules.h:297
int GetRegionGrowingRGB(const PointCloudRGB::ConstPtr cloud, std::vector< pcl::PointIndices > &clusters, PointCloudRGB::Ptr cloud_segmented, int min_cluster_size, float neighbors_distance, float point_color_diff, float region_color_diff)
Color based Region Growing.
Definition: PCLModules.cpp:98
int EstimateHarris3D(const typename pcl::PointCloud< PointInT >::ConstPtr inCloud, pcl::PointCloud< pcl::PointXYZI >::Ptr outcloud, float normalRadius=0.1f, float searchRadius=0.1f)
Definition: PCLModules.h:901
int GetPoissonReconstruction(const PointCloudNormal::ConstPtr &cloudWithNormals, PCLMesh &outMesh, int degree, int treeDepth, int isoDivideDepth, int solverDivideDepth, float scale, float samplesPerNode, bool useConfidence, bool useManifold, bool outputPolygons)
Definition: PCLModules.cpp:237
int VoxelGridFilter(const typename pcl::PointCloud< PointInOut >::ConstPtr inCloud, typename pcl::PointCloud< PointInOut >::Ptr outcloud, const float &leafSizeX=-0.01f, const float &leafSizeY=-0.01f, const float &leafSizeZ=-0.01f)
Definition: PCLModules.h:1194
int EstimateHough3DGrouping(const typename pcl::PointCloud< PointModelT >::ConstPtr modelKeypoints, const typename pcl::PointCloud< PointSceneT >::ConstPtr sceneKeypoints, const typename pcl::PointCloud< PointModelRfT >::ConstPtr modelRF, const typename pcl::PointCloud< PointSceneRfT >::ConstPtr sceneRF, const typename pcl::CorrespondencesConstPtr modelSceneCorrs, std::vector< Eigen::Matrix4f, Eigen::aligned_allocator< Eigen::Matrix4f >> &rotoTranslations, std::vector< pcl::Correspondences > &clusteredCorrs, float houghBinSize=0.01f, float houghThreshold=5.0f)
Definition: PCLModules.h:848
int GetRegionGrowing(const PointCloudT::ConstPtr cloud, std::vector< pcl::PointIndices > &clusters, PointCloudRGB::Ptr cloud_segmented, int k, int min_cluster_size, int max_cluster_size, unsigned int neighbour_number, float smoothness_theta, float curvature)
Basic Region Growing.
Definition: PCLModules.cpp:46
int GetSACSegmentation(const PointCloudT::ConstPtr cloud, pcl::PointIndices::Ptr inliers, pcl::ModelCoefficients::Ptr coefficients, const int &methodType, const int &modelType, float distanceThreshold, float probability, int maxIterations, float minRadiusLimits, float maxRadiusLimits, float normalDisWeight)
Definition: PCLModules.cpp:142
int RemoveOutliersStatistical(const typename PointOutT::ConstPtr inCloud, typename PointOutT::Ptr outCloud, int knn, double nSigma)
Definition: PCLModules.h:749
int CropHullFilter(const typename pcl::PointCloud< PointInT >::ConstPtr inCloud, const PointCloudT::ConstPtr boundingBox, typename pcl::PointCloud< PointInT >::Ptr outCloud, int dimensions=2)
Definition: PCLModules.h:1296
int ProgressiveMpFilter(const typename pcl::PointCloud< PointInT >::ConstPtr inCloud, pcl::PointIndicesPtr groundIndices, int maxWindowSize=20, float slope=1.0f, float initialDistance=0.5f, float maxDistance=3.0f)
Definition: PCLModules.h:784
int ComputeNormals(const typename pcl::PointCloud< PointInT >::ConstPtr inCloud, typename pcl::PointCloud< PointOutT >::Ptr outcloud, const float radius=-1.0f, const bool useKnn=true, bool normalConsistency=false, int maxThreadCount=QThread::idealThreadCount())
Definition: PCLModules.h:1125
int DONEstimation(const typename pcl::PointCloud< PointInT >::ConstPtr inCloud, const typename pcl::PointCloud< NormalType >::ConstPtr normalsLargeScale, const typename pcl::PointCloud< NormalType >::ConstPtr normalsSmallScale, typename pcl::PointCloud< PointOutT >::Ptr outCloud)
Definition: PCLModules.h:804
int ConditionalRemovalFilter(const typename pcl::PointCloud< PointInOut >::ConstPtr inCloud, const ConditionParameters &params, typename pcl::PointCloud< PointInOut >::Ptr outCloud, bool keepOrganized=false)
Definition: PCLModules.h:955
int EstimateShot(const typename pcl::PointCloud< PointInT >::ConstPtr inCloud, const typename pcl::PointCloud< PointInT >::ConstPtr keyPoints, const typename pcl::PointCloud< NormalType >::ConstPtr normals, typename pcl::PointCloud< DescriptorType >::Ptr outDescriptors, float searchRadius=0.03f, int maxThreadCount=QThread::idealThreadCount())
Definition: PCLModules.h:677
int GetMarchingCubes(const typename pcl::PointCloud< PointInT >::ConstPtr inCloud, const MarchingMethod &marchingMethod, PCLMesh &outMesh, float epsilon=0.01f, float isoLevel=0.0f, float gridResolution=50, float percentageExtendGrid=0.0f)
Definition: PCLModules.h:218
int GridProjection(const PointCloudNormal::ConstPtr &cloudWithNormals, PCLMesh &outMesh, float resolution, int paddingSize, int maxSearchLevel)
Definition: PCLModules.cpp:217
int EuclideanCluster(const typename pcl::PointCloud< PointInT >::ConstPtr inCloud, std::vector< pcl::PointIndices > &cluster_indices, float clusterTolerance=0.02f, int minClusterSize=100, int maxClusterSize=250000)
Definition: PCLModules.h:762
int PassThroughFilter(const typename pcl::PointCloud< PointInOut >::ConstPtr inCloud, typename pcl::PointCloud< PointInOut >::Ptr outcloud, const QString &filterFieldName="z", const float &limit_min=0.1f, const float &limit_max=1.1f)
Definition: PCLModules.h:1179
double ComputeCloudResolution(const typename pcl::PointCloud< PointInT >::ConstPtr inCloud)
Definition: PCLModules.h:695
bool ICPRegistration(const typename pcl::PointCloud< PointInT >::ConstPtr targetCloud, const typename pcl::PointCloud< PointOutT >::ConstPtr sourceCloud, typename pcl::PointCloud< PointOutT >::Ptr outRegistered, int ipcMaxIterations=5, float icpCorrDistance=0.005f)
Definition: PCLModules.h:1400
template int GetConvexHullReconstruction< PointT >(const PointCloudT::ConstPtr inCloud, PCLMesh &outMesh, int dimension)
int GetConcaveHullReconstruction(const typename pcl::PointCloud< PointInT >::ConstPtr inCloud, PCLMesh &outMesh, int dimension=3, float alpha=0.05f)
Definition: PCLModules.h:1276
int SmoothMls(const typename pcl::PointCloud< PointInT >::ConstPtr &inCloud, const MLSParameters &params, typename pcl::PointCloud< PointOutT >::Ptr &outcloud)
Definition: PCLModules.h:1052
int GetProjection(const PointCloudT::ConstPtr &originCloud, PointCloudT::Ptr &projectedCloud, const pcl::ModelCoefficients::ConstPtr coefficients, const int &modelType)
Definition: PCLModules.cpp:298
int GetBoundaryCloud(const typename pcl::PointCloud< PointInOut >::ConstPtr inCloud, const typename pcl::PointCloud< NormalType >::ConstPtr normals, typename pcl::PointCloud< PointInOut >::Ptr boundaryCloud, const float angleThreshold=90.0f, const float radius=-1.0f, const bool useKnn=true)
Definition: PCLModules.h:1355
int SwapAxis(const typename pcl::PointCloud< PointInOutT >::ConstPtr inCloud, typename pcl::PointCloud< PointInOutT >::Ptr outcloud, const std::string &flag)
Definition: PCLModules.h:263
int GetMinCutSegmentation(const typename pcl::PointCloud< PointInT >::ConstPtr inCloud, std::vector< pcl::PointIndices > &outClusters, PointCloudRGB::Ptr cloud_segmented, const PointInT foregroundPoint, int neighboursNumber=14, float smoothSigma=0.25f, float backWeightRadius=0.8f, float foreWeight=0.5f, const pcl::IndicesConstPtr indices=nullptr)
Definition: PCLModules.h:1323
int EstimateLocalReferenceFrame(const typename pcl::PointCloud< PointInT >::ConstPtr inCloud, const typename pcl::PointCloud< PointInT >::ConstPtr keyPoints, const typename pcl::PointCloud< NormalType >::ConstPtr normals, typename pcl::PointCloud< RFType >::Ptr outRF, float searchRadius=0.015f)
Definition: PCLModules.h:827
int ExtractIndicesFilter(const typename pcl::PointCloud< PointInOut >::ConstPtr inCloud, const pcl::PointIndices::ConstPtr inliers, typename pcl::PointCloud< PointInOut >::Ptr outcloud=nullptr, typename pcl::PointCloud< PointInOut >::Ptr outcloud2=nullptr)
Definition: PCLModules.h:1229
int EstimateSIFT(const typename pcl::PointCloud< PointInT >::ConstPtr inCloud, typename pcl::PointCloud< PointOutT >::Ptr outcloud, int nr_octaves=0, float min_scale=0, int nr_scales_per_octave=0, float min_contrast=0)
Extract SIFT keypoints.
Definition: PCLModules.h:651
int EstimateMaxThreads()
Estimate the maximum number of threads to be used in a parallel region.
Definition: Parallel.cpp:31
float DegreesToRadians(int degrees)
Convert degrees to radians.
Definition: CVMath.h:98
ccGenericPointCloud * sourceCloud
static const double TD
#define QPCL_ENGINE_LIB_API
Definition: qPCL.h:15
ConditionType
NOTE: DISTINCT CLOUD METHOD NOT IMPLEMENTED.
Definition: PCLModules.h:938
std::vector< ComparisonParam > condition_params_
Definition: PCLModules.h:951
UpsamplingMethod upsample_method_
Definition: PCLModules.h:1042
UpsamplingMethod
NOTE: DISTINCT CLOUD METHOD NOT IMPLEMENTED.
Definition: PCLModules.h:1017