39 #include "Eigen/Eigenvalues" 
   45 #include <boost/format.hpp> 
   76         inPlaceFilter(output);
 
   93         const int pointsCount(cloud.
features.cols());
 
   94         const int featDim(cloud.
features.rows());
 
  100         for(
unsigned int i = 0; i < labelDim ; ++i)
 
  102         if (insertDim != descDim)
 
  103                 throw InvalidField(
"SurfaceNormalDataPointsFilter: Error, descriptor labels do not match descriptor data");
 
  106         const int dimNormals(featDim-1);
 
  107         const int dimDensities(1);
 
  108         const int dimEigValues(featDim-1);
 
  109         const int dimEigVectors((featDim-1)*(featDim-1));
 
  111         const int dimMeanDist(1);
 
  113         boost::optional<View> normals;
 
  114         boost::optional<View> densities;
 
  115         boost::optional<View> eigenValues;
 
  116         boost::optional<View> eigenVectors;
 
  117         boost::optional<View> matchedValues;
 
  118         boost::optional<View> matchIds;
 
  119         boost::optional<View> meanDists;
 
  123                 cloudLabels.push_back(
Label(
"normals", dimNormals));
 
  125                 cloudLabels.push_back(
Label(
"densities", dimDensities));
 
  127                 cloudLabels.push_back(
Label(
"eigValues", dimEigValues));
 
  128         if (keepEigenVectors)
 
  129                 cloudLabels.push_back(
Label(
"eigVectors", dimEigVectors));
 
  131                 cloudLabels.push_back(
Label(
"matchedIds", 
knn));
 
  133                 cloudLabels.push_back(
Label(
"meanDists", dimMeanDist));
 
  144         if (keepEigenVectors)
 
  154         boost::assign::insert(param) ( 
"knn", 
toParam(
knn) );
 
  155         boost::assign::insert(param) ( 
"epsilon", 
toParam(epsilon) );
 
  156         boost::assign::insert(param) ( 
"maxDist", 
toParam(maxDist) );
 
  161         Matches matches(
typename Matches::Dists(
knn, pointsCount), 
typename Matches::Ids(
knn, pointsCount));
 
  165         int degenerateCount(0);
 
  166         for (
int i = 0; i < pointsCount; ++i)
 
  168                 bool isDegenerate = 
false;
 
  173                 for(
int j = 0; j < int(
knn); ++j)
 
  175                         if (
matches.dists(j,i) != Matches::InvalidDist)
 
  177                                 const int refIndex(
matches.ids(j,i));
 
  178                                 d.col(realKnn) = cloud.
features.block(0, refIndex, featDim-1, 1);
 
  182                 d.conservativeResize(Eigen::NoChange, realKnn);
 
  184                 const Vector mean = d.rowwise().sum() / 
T(realKnn);
 
  185                 const Matrix NN = d.colwise() - mean;
 
  187                 const Matrix C((NN * NN.transpose()) / 
T(realKnn));
 
  188                 Vector eigenVa = Vector::Zero(featDim-1, 1);
 
  189                 Matrix eigenVe = Matrix::Zero(featDim-1, featDim-1);
 
  191                 if(keepNormals || keepEigenValues || keepEigenVectors)
 
  193                         if(C.fullPivHouseholderQr().rank()+1 >= featDim-1)
 
  195                                 const Eigen::EigenSolver<Matrix> solver(C);
 
  196                                 eigenVa = solver.eigenvalues().real();
 
  197                                 eigenVe = solver.eigenvectors().real();
 
  201                                         const std::vector<size_t> idx = sortIndexes<T>(eigenVa);
 
  202                                         const size_t idxSize = idx.size();
 
  203                                         Vector tmp_eigenVa = eigenVa;
 
  204                                         Matrix tmp_eigenVe = eigenVe;
 
  205                                         for(
size_t j=0; j<idxSize; ++j)
 
  207                                                 eigenVa(j,0) = tmp_eigenVa(idx[j], 0);
 
  208                                                 eigenVe.col(j) = tmp_eigenVe.col(idx[j]);
 
  223                                 normals->col(i) = eigenVe.col(0);
 
  225                                 normals->col(i) = computeNormal<T>(eigenVa, eigenVe);
 
  228                         normals->col(i) = normals->col(i).cwiseMax(-1.0).cwiseMin(1.0);
 
  233                                 (*densities)(0, i) = 0.;
 
  235                                 (*densities)(0, i) = computeDensity<T>(NN);
 
  238                         eigenValues->col(i) = eigenVa;
 
  240                         eigenVectors->col(i) = serializeEigVec<T>(eigenVe);
 
  244                                 (*meanDists)(0, i) = std::numeric_limits<std::size_t>::max();
 
  248                                 (*meanDists)(0, i) = (point - mean).norm();
 
  256                 matchIds.get() = 
matches.ids.template cast<T>();
 
  261                 for (
int i = 0; i < pointsCount; ++i)
 
  263                         const Vector currentNormal = normals->col(i);
 
  264                         Vector mean = Vector::Zero(featDim-1);
 
  266                         for(
int j = 0; j < int(
knn); ++j)
 
  268                                 if (
matches.dists(j,i) != Matches::InvalidDist)
 
  270                                         const int refIndex(
matches.ids(j,i));
 
  271                                         const Vector normal = normals->col(refIndex);
 
  272                                         if(currentNormal.dot(normal) > 0.)
 
  281                         normals->col(i) = mean / 
T(n);
 
  287                 LOG_WARNING_STREAM(
"WARNING: Matrix C needed for eigen decomposition was degenerated in " << degenerateCount << 
" points over " << pointsCount << 
" (" << 
float(degenerateCount)*100.f/
float(pointsCount) << 
" %)");