55 voxel_centroids_leaf_indices_.clear ();
61 PCL_WARN (
"[pcl::%s::applyFilter] No input dataset given!\n", getClassName ().c_str ());
62 output.width = output.height = 0;
69 output.is_dense =
true;
72 Eigen::Vector4f min_p, max_p;
74 if (!filter_field_name_.empty ())
75 getMinMax3D<PointT> (input_, filter_field_name_,
static_cast<float> (filter_limit_min_),
static_cast<float> (filter_limit_max_), min_p, max_p, filter_limit_negative_);
77 getMinMax3D<PointT> (*input_, min_p, max_p);
80 std::int64_t dx =
static_cast<std::int64_t
>((max_p[0] - min_p[0]) * inverse_leaf_size_[0])+1;
81 std::int64_t dy =
static_cast<std::int64_t
>((max_p[1] - min_p[1]) * inverse_leaf_size_[1])+1;
82 std::int64_t dz =
static_cast<std::int64_t
>((max_p[2] - min_p[2]) * inverse_leaf_size_[2])+1;
86 const float int_min_f =
static_cast<float> (std::numeric_limits<int>::lowest());
87 const float int_max_f =
static_cast<float> (std::numeric_limits<int>::max());
88 bool indices_fit =
true;
89 for (
int i = 0; i < 3; ++i)
92 if (min_p[i] > max_p[i])
94 const float min_index = std::floor (min_p[i] * inverse_leaf_size_[i]);
95 const float max_index = std::floor (max_p[i] * inverse_leaf_size_[i]);
96 indices_fit = indices_fit && min_index >= int_min_f && min_index < int_max_f &&
97 max_index >= int_min_f && max_index < int_max_f;
100 if((dx*dy*dz) > std::numeric_limits<std::int32_t>::max() || !indices_fit)
102 PCL_WARN(
"[pcl::%s::applyFilter] Leaf size is too small for the input dataset. Integer indices would overflow.\n", getClassName().c_str());
108 min_b_[0] =
static_cast<int> (std::floor (min_p[0] * inverse_leaf_size_[0]));
109 max_b_[0] =
static_cast<int> (std::floor (max_p[0] * inverse_leaf_size_[0]));
110 min_b_[1] =
static_cast<int> (std::floor (min_p[1] * inverse_leaf_size_[1]));
111 max_b_[1] =
static_cast<int> (std::floor (max_p[1] * inverse_leaf_size_[1]));
112 min_b_[2] =
static_cast<int> (std::floor (min_p[2] * inverse_leaf_size_[2]));
113 max_b_[2] =
static_cast<int> (std::floor (max_p[2] * inverse_leaf_size_[2]));
116 div_b_ = max_b_ - min_b_ + Eigen::Vector4i::Ones ();
120 divb_mul_ = Eigen::Vector4i (1, div_b_[0], div_b_[0] * div_b_[1], 0);
122 int centroid_size = 4;
124 if (downsample_all_data_)
125 centroid_size = boost::mpl::size<FieldList>::value;
128 std::vector<pcl::PCLPointField> fields;
130 rgba_index = pcl::getFieldIndex<PointT> (
"rgb", fields);
131 if (rgba_index == -1)
132 rgba_index = pcl::getFieldIndex<PointT> (
"rgba", fields);
135 rgba_index = fields[rgba_index].offset;
140 if (!filter_field_name_.empty ())
143 std::vector<pcl::PCLPointField> fields;
144 int distance_idx = pcl::getFieldIndex<PointT> (filter_field_name_, fields);
145 if (distance_idx == -1)
146 PCL_WARN (
"[pcl::%s::applyFilter] Invalid filter field name. Index is %d.\n", getClassName ().c_str (), distance_idx);
149 for (
const auto& point: *input_)
151 if (!input_->is_dense)
157 const auto* pt_data =
reinterpret_cast<const std::uint8_t*
> (&point);
158 float distance_value = 0;
159 memcpy (&distance_value, pt_data + fields[distance_idx].offset,
sizeof (
float));
161 if (filter_limit_negative_)
164 if ((distance_value < filter_limit_max_) && (distance_value > filter_limit_min_))
170 if ((distance_value > filter_limit_max_) || (distance_value < filter_limit_min_))
175 const Eigen::Vector4i ijk =
176 Eigen::floor(point.getArray4fMap() * inverse_leaf_size_.array())
177 .template cast<int>();
179 int idx = (ijk - min_b_).dot(divb_mul_);
181 Leaf& leaf = leaves_[idx];
184 leaf.
centroid.resize (centroid_size);
188 Eigen::Vector3d pt3d = point.getVector3fMap().template cast<double>();
192 leaf.
cov_.noalias() += pt3d * pt3d.transpose ();
195 if (!downsample_all_data_)
197 leaf.
centroid.template head<3> () += point.getVector3fMap();
202 Eigen::VectorXf centroid = Eigen::VectorXf::Zero (centroid_size);
208 const pcl::RGB& rgb = *
reinterpret_cast<const RGB*
> (
reinterpret_cast<const char*
> (&point) + rgba_index);
209 centroid[centroid_size - 4] = rgb.a;
210 centroid[centroid_size - 3] = rgb.r;
211 centroid[centroid_size - 2] = rgb.g;
212 centroid[centroid_size - 1] = rgb.b;
223 for (
const auto& point: *input_)
225 if (!input_->is_dense)
231 const Eigen::Vector4i ijk =
232 Eigen::floor(point.getArray4fMap() * inverse_leaf_size_.array())
233 .template cast<int>();
235 int idx = (ijk - min_b_).dot(divb_mul_);
237 Leaf& leaf = leaves_[idx];
240 leaf.
centroid.resize (centroid_size);
244 Eigen::Vector3d pt3d = point.getVector3fMap().template cast<double>();
248 leaf.
cov_.noalias() += pt3d * pt3d.transpose ();
251 if (!downsample_all_data_)
253 leaf.
centroid.template head<3> () += point.getVector3fMap();
258 Eigen::VectorXf centroid = Eigen::VectorXf::Zero (centroid_size);
264 const pcl::RGB& rgb = *
reinterpret_cast<const RGB*
> (
reinterpret_cast<const char*
> (&point) + rgba_index);
265 centroid[centroid_size - 4] = rgb.a;
266 centroid[centroid_size - 3] = rgb.r;
267 centroid[centroid_size - 2] = rgb.g;
268 centroid[centroid_size - 1] = rgb.b;
277 output.reserve (leaves_.size ());
279 voxel_centroids_leaf_indices_.reserve (leaves_.size ());
281 if (save_leaf_layout_)
282 leaf_layout_.resize (div_b_[0] * div_b_[1] * div_b_[2], -1);
285 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigensolver;
286 Eigen::Matrix3d eigen_val;
287 Eigen::Vector3d pt_sum;
290 double min_covar_eigvalue;
292 for (
auto it = leaves_.begin (); it != leaves_.end (); ++it)
296 Leaf& leaf = it->second;
307 if (leaf.
nr_points >= min_points_per_voxel_)
309 if (save_leaf_layout_)
310 leaf_layout_[it->first] = cp++;
312 output.push_back (
PointT ());
315 if (!downsample_all_data_)
317 output.back ().x = leaf.
centroid[0];
318 output.back ().y = leaf.
centroid[1];
319 output.back ().z = leaf.
centroid[2];
327 pcl::RGB& rgb = *
reinterpret_cast<RGB*
> (
reinterpret_cast<char*
> (&output.back ()) + rgba_index);
328 rgb.a = leaf.
centroid[centroid_size - 4];
329 rgb.r = leaf.
centroid[centroid_size - 3];
330 rgb.g = leaf.
centroid[centroid_size - 2];
331 rgb.b = leaf.
centroid[centroid_size - 1];
337 voxel_centroids_leaf_indices_.push_back (
static_cast<int> (it->first));
343 eigensolver.compute (leaf.
cov_);
344 eigen_val = eigensolver.eigenvalues ().asDiagonal ();
345 leaf.
evecs_ = eigensolver.eigenvectors ();
347 if (eigen_val (0, 0) < -Eigen::NumTraits<double>::dummy_precision () || eigen_val (1, 1) < -Eigen::NumTraits<double>::dummy_precision () || eigen_val (2, 2) <= 0)
349 PCL_WARN (
"[VoxelGridCovariance::applyFilter] Invalid eigen value! (%g, %g, %g)\n", eigen_val (0, 0), eigen_val (1, 1), eigen_val (2, 2));
356 min_covar_eigvalue = min_covar_eigvalue_mult_ * eigen_val (2, 2);
357 if (eigen_val (0, 0) < min_covar_eigvalue)
359 eigen_val (0, 0) = min_covar_eigvalue;
361 if (eigen_val (1, 1) < min_covar_eigvalue)
363 eigen_val (1, 1) = min_covar_eigvalue;
368 leaf.
evals_ = eigen_val.diagonal ();
371 if (leaf.
icov_.maxCoeff () == std::numeric_limits<float>::infinity ( )
372 || leaf.
icov_.minCoeff () == -std::numeric_limits<float>::infinity ( ) )
380 output.width = output.size ();
384template<
typename Po
intT>
int
390 Eigen::Vector4i ijk = Eigen::floor(reference_point.getArray4fMap() * inverse_leaf_size_).template cast<int>();
392 const Eigen::Array4i diff2min = min_b_ - ijk;
393 const Eigen::Array4i diff2max = max_b_ - ijk;
394 neighbors.reserve (relative_coordinates.cols ());
397 for (Eigen::Index ni = 0; ni < relative_coordinates.cols (); ni++)
399 const Eigen::Vector4i displacement = (Eigen::Vector4i () << relative_coordinates.col (ni), 0).finished ();
401 if ((diff2min <= displacement.array ()).all () && (diff2max >= displacement.array ()).all ())
403 const auto leaf_iter = leaves_.find (((ijk + displacement - min_b_).dot (divb_mul_)));
404 if (leaf_iter != leaves_.end () && leaf_iter->second.nr_points >= min_points_per_voxel_)
407 neighbors.push_back (leaf);
412 return static_cast<int> (neighbors.size());
416template<
typename Po
intT>
int
420 return getNeighborhoodAtPoint(relative_coordinates, reference_point, neighbors);
424template<
typename Po
intT>
int
427 return getNeighborhoodAtPoint(Eigen::Matrix<int, 3, Eigen::Dynamic>::Zero(3,1), reference_point, neighbors);
431template<
typename Po
intT>
int
434 Eigen::Matrix<int, 3, Eigen::Dynamic> relative_coordinates(3, 7);
435 relative_coordinates.setZero();
436 relative_coordinates(0, 1) = 1;
437 relative_coordinates(0, 2) = -1;
438 relative_coordinates(1, 3) = 1;
439 relative_coordinates(1, 4) = -1;
440 relative_coordinates(2, 5) = 1;
441 relative_coordinates(2, 6) = -1;
443 return getNeighborhoodAtPoint(relative_coordinates, reference_point, neighbors);
447template<
typename Po
intT>
int
450 Eigen::Matrix<int, 3, Eigen::Dynamic> relative_coordinates(3, 27);
451 relative_coordinates.col(0).setZero();
454 return getNeighborhoodAtPoint(relative_coordinates, reference_point, neighbors);
458template<
typename Po
intT>
void
465 boost::normal_distribution<> nd (0.0, 1.0);
466 boost::variate_generator<boost::mt19937&, boost::normal_distribution<> > var_nor (rng, nd);
468 Eigen::LLT<Eigen::Matrix3d> llt_of_cov;
469 Eigen::Matrix3d cholesky_decomp;
470 Eigen::Vector3d cell_mean;
471 Eigen::Vector3d rand_point;
472 Eigen::Vector3d dist_point;
474 cell_cloud.
reserve (pnt_per_cell * std::count_if (leaves_.begin (), leaves_.end (),
475 [
this] (
auto& l) { return (l.second.nr_points >= min_points_per_voxel_); }));
478 for (
auto it = leaves_.begin (); it != leaves_.end (); ++it)
480 const Leaf& leaf = it->second;
482 if (leaf.
nr_points >= min_points_per_voxel_)
484 cell_mean = leaf.
mean_;
485 llt_of_cov.compute (leaf.
cov_);
486 cholesky_decomp = llt_of_cov.matrixL ();
489 for (
int i = 0; i < pnt_per_cell; i++)
491 rand_point = Eigen::Vector3d (var_nor (), var_nor (), var_nor ());
492 dist_point.noalias() = cell_mean + cholesky_decomp * rand_point;
493 cell_cloud.
push_back (
PointXYZ (
static_cast<float> (dist_point (0)),
static_cast<float> (dist_point (1)),
static_cast<float> (dist_point (2))));
499#define PCL_INSTANTIATE_VoxelGridCovariance(T) template class PCL_EXPORTS pcl::VoxelGridCovariance<T>;