40 #include <unordered_map> 44 #include "Eigen/Eigenvalues" 51 nbSample{Parametrizable::get<std::size_t>(
"nbSample")}
55 const std::uint8_t tnm = this->
template get<std::uint8_t>(
"torqueNorm");
76 const std::size_t featDim(cloud.
features.rows());
86 throw InvalidField(
"OrientNormalsDataPointsFilter: Error, cannot find normals in descriptors.");
90 std::vector<std::size_t> keepIndexes;
95 std::vector<std::size_t> candidates ;
96 candidates.resize(nbPoints);
98 for (std::size_t i = 0; i < nbPoints; ++i) candidates[i] = i;
100 const std::size_t nbCandidates = candidates.size();
104 for(std::size_t i = 0; i < featDim - 1; ++i) center(i) =
T(0.);
106 for (std::size_t i = 0; i < nbCandidates; ++i)
107 for (std::size_t f = 0; f < 3; ++f)
108 center(f) += cloud.
features(f,candidates[i]);
110 for(std::size_t i = 0; i < 3; ++i) center(i) /=
T(nbCandidates);
122 for (std::size_t i = 0; i < nbCandidates; ++i)
123 Lnorm += (cloud.
features.col(candidates[i]).head(3) - center).norm();
124 Lnorm /= nbCandidates;
130 const Vector3 radii = maxValues.head(3) - minValues.head(3);
132 Lnorm = radii.maxCoeff() / 2.;
136 auto computeCovariance = [Lnorm, nbCandidates, &cloud, ¢er, &normals, &candidates](
Matrix66 & cov) ->
void {
138 Eigen::Matrix<T, 6, Eigen::Dynamic> F(6, nbCandidates);
140 for(std::size_t i = 0; i < nbCandidates; ++i)
142 const Vector3 p = cloud.features.col(candidates[i]).head(3) - center;
143 const Vector3 ni = normals.col(candidates[i]).head(3);
146 F.template block<3, 1>(0, i) = (1. / Lnorm) * p.cross(ni);
148 F.template block<3, 1>(3, i) = ni;
152 cov = F * F.transpose();
156 computeCovariance(covariance);
158 Eigen::EigenSolver<Matrix66> solver(covariance);
159 const Matrix66 eigenVe = solver.eigenvectors().real();
160 const Vector6 eigenVa = solver.eigenvalues().real();
164 std::vector<Vector6, Eigen::aligned_allocator<Vector6>> v;
165 v.resize(nbCandidates);
167 for(std::size_t i = 0; i < nbCandidates; ++i)
169 const Vector3 p = cloud.features.col(candidates[i]).head(3) - center;
170 const Vector3 ni = normals.col(candidates[i]).head(3);
172 v[i].template block<3, 1>(0, 0) = (1. / Lnorm) * p.cross(ni);
173 v[i].template block<3, 1>(3, 0) = ni;
177 std::vector<std::list<std::pair<int, T>>> L;
181 auto comp = [](
const std::pair<int, T>& p1,
const std::pair<int, T>& p2) ->
bool {
182 return p1.second > p2.second;
185 for(std::size_t k = 0; k < 6; ++k)
187 for(std::size_t i = 0; i < nbCandidates; ++i )
189 L[k].push_back(std::make_pair(i, std::fabs( v[i].dot(eigenVe.template block<6,1>(0, k)) )));
195 std::vector<T> t(6,
T(0.));
196 std::vector<bool> sampledPoints(nbCandidates,
false);
199 for(std::size_t i = 0; i <
nbSample; ++i)
206 for (std::size_t i = 0; i < 6; ++i)
212 while(sampledPoints[L[k].front().first])
216 const std::size_t idToKeep =
static_cast<std::size_t
>(L[k].front().first);
219 sampledPoints[idToKeep] =
true;
222 for (std::size_t k = 0; k < 6; ++k)
224 const T magnitude = v[idToKeep].dot(eigenVe.template block<6, 1>(0, k));
225 t[k] += (magnitude * magnitude);
228 keepIndexes[i] = candidates[idToKeep];
233 std::unordered_map<std::size_t, std::size_t> mapidx;
237 for(std::size_t
id : keepIndexes)
243 cloud.swapCols(idx,
id);
249 cloud.conservativeResize(nbSample);
254 template <
typename T>
257 Vector eigenVa = Vector::Identity(6, 1);
259 Eigen::EigenSolver<Matrix66> solver(cov);
260 eigenVa = solver.eigenvalues().real();
262 return eigenVa.maxCoeff() / eigenVa.minCoeff();
static T computeConditionNumber(const Matrix66 &cov)
virtual void inPlaceFilter(DataPoints &cloud)
Apply these filters to a point cloud without copying.
ConstView getDescriptorViewByName(const std::string &name) const
Get a const view on a descriptor by name, throw an exception if it does not exist.
unsigned getNbPoints() const
Return the number of points contained in the point cloud.
Eigen::Matrix< T, 6, 1 > Vector6
CovarianceSamplingDataPointsFilter(const Parameters ¶ms=Parameters())
PointMatcher< T >::Vector Vector
Eigen::Matrix< T, 6, 6 > Matrix66
virtual DataPoints filter(const DataPoints &input)
Apply filters to input point cloud. This is the non-destructive version and returns a copy...
Functions and classes that are dependant on scalar type are defined in this templatized class...
bool descriptorExists(const std::string &name) const
Look if a descriptor with a given name exist.
A data filter takes a point cloud as input, transforms it, and produces another point cloud as output...
An exception thrown when one tries to fetch the value of an unexisting parameter. ...
PointMatcher< T >::DataPoints::InvalidField InvalidField
Eigen::Matrix< T, 3, 1 > Vector3
TorqueNormMethod normalizationMethod
Parametrizable::Parameters Parameters
Matrix features
features of points in the cloud