43 #include "Eigen/Eigenvalues"
67 averageExistingDescriptors(
Parametrizable::
get<bool>(
"averageExistingDescriptors")),
82 inPlaceFilter(output);
95 const int pointsCount(cloud.
features.cols());
96 const int featDim(cloud.
features.rows());
101 if (averageExistingDescriptors)
105 for(
unsigned int i = 0; i < labelDim; ++i)
107 if (insertDim != descDim)
108 throw InvalidField(
"GestaltDataPointsFilter: Error, descriptor labels do not match descriptor data");
112 const int dimNormals(featDim-1);
113 const int dimMeans(featDim-1);
114 const int dimEigValues(featDim-1);
115 const int dimEigVectors((featDim-1)*(featDim-1));
116 const int dimCovariances((featDim-1)*(featDim-1));
117 const int dimGestalt = 32;
120 Labels cloudLabels, timeLabels;
123 cloudLabels.push_back(
Label(
"normals", dimNormals));
125 cloudLabels.push_back(
Label(
"means", dimMeans));
127 cloudLabels.push_back(
Label(
"eigValues", dimEigValues));
128 if (keepEigenVectors)
129 cloudLabels.push_back(
Label(
"eigVectors", dimEigVectors));
131 cloudLabels.push_back(
Label(
"covariance", dimCovariances));
132 if (keepGestaltFeatures)
134 cloudLabels.push_back(
Label(
"gestaltMeans", dimGestalt));
135 cloudLabels.push_back(
Label(
"gestaltVariances", dimGestalt));
136 cloudLabels.push_back(
Label(
"warpedXYZ", 3));
137 cloudLabels.push_back(
Label(
"gestaltShapes", 2));
139 timeLabels.push_back(
Label(
"time", 3));
146 TimeView cloudExistingTimes(cloud.
times.block(0,0,cloud.
times.rows(),cloud.
times.cols()));
156 if (keepEigenVectors)
160 if (keepGestaltFeatures)
172 cloud.
features.rowwise().minCoeff(),
177 fuseRange(buildData, cloud, 0, pointsCount);
183 for (
int i = 0; i < ptsOut; ++i)
194 buildData.
means->col(i) = buildData.
means->col(k);
201 if(keepGestaltFeatures)
209 cloud.
features.conservativeResize(Eigen::NoChange, ptsOut);
210 cloud.
descriptors.conservativeResize(Eigen::NoChange, ptsOut);
211 cloud.
times.conservativeResize(Eigen::NoChange, ptsOut);
225 const T minBoundX = minValues.x() / vSizeX;
226 const T maxBoundX = maxValues.x() / vSizeX;
227 const T minBoundY = minValues.y() / vSizeY;
228 const T maxBoundY = maxValues.y() / vSizeY;
229 const T minBoundZ = minValues.z() / vSizeZ;
230 const T maxBoundZ = maxValues.z() / vSizeZ;
234 const unsigned int numDivX = 1 + maxBoundX - minBoundX;
235 const unsigned int numDivY = 1 + maxBoundY - minBoundY;;
236 const unsigned int numDivZ = 1 + maxBoundZ - minBoundZ;
237 const unsigned int numVox = numDivX * numDivY * numDivZ;
244 const int numPoints = last - first;
245 std::vector<unsigned int> indices(numPoints);
250 std::vector<Voxel> voxels;
255 voxels = std::vector<Voxel>(numVox);
257 catch (std::bad_alloc&)
259 throw InvalidParameter((boost::format(
"GestaltDataPointsFilter: Memory allocation error with %1% voxels. Try increasing the voxel dimensions.") % numVox).str());
262 const int featDim(
data.features.rows());
264 for (
int p = 0; p < numPoints; ++p)
266 const unsigned int i = floor(
data.features(0,p)/vSizeX - minBoundX);
267 const unsigned int j = floor(
data.features(1,p)/vSizeY- minBoundY);
272 k = floor(
data.features(2,p)/vSizeZ - minBoundZ);
273 idx = i + j * numDivX + k * numDivX * numDivY;
277 idx = i + j * numDivX;
280 const unsigned int pointsInVox = voxels[idx].numPoints + 1;
282 if (pointsInVox == 1)
284 voxels[idx].firstPoint = p;
287 voxels[idx].numPoints = pointsInVox;
294 std::vector<unsigned int> pointsToKeep;
298 for (
int p = 0; p < numPoints ; ++p)
300 const unsigned int idx = indices[p];
301 const unsigned int firstPoint = voxels[idx].firstPoint;
304 const int randomIndex = std::rand() % numPoints;
305 for (
int f = 0; f < (featDim - 1); ++f)
307 data.features(f,firstPoint) =
data.features(f,randomIndex);
311 for (
unsigned int idx = 0; idx < numVox; ++idx)
313 const unsigned int numPoints = voxels[idx].numPoints;
314 const unsigned int firstPoint = voxels[idx].firstPoint;
322 pointsToKeep.push_back(firstPoint);
326 const unsigned int nbPointsToKeep(pointsToKeep.size());
329 for(
unsigned int i=0; i<nbPointsToKeep; ++i)
331 const float r = (float)std::rand()/(float)RAND_MAX;
335 const int k = pointsToKeep[i];
337 data.indicesToKeep.push_back(k);
348 typedef typename Eigen::Matrix<std::int64_t, Eigen::Dynamic, Eigen::Dynamic>
Int64Matrix;
350 const unsigned int nbIdxToKeep(
data.indicesToKeep.size());
351 const int inputFeatDim(input.
features.cols());
353 std::vector<int> indicesToKeepStrict;
354 for (
unsigned int i = 0; i < nbIdxToKeep ; ++i)
356 Eigen::Matrix<T,3,1> keyPoint;
360 const T minBoundX = keyPoint(0,0) - radius;
361 const T maxBoundX = keyPoint(0,0) + radius;
362 const T minBoundY = keyPoint(1,0) - radius;
363 const T maxBoundY = keyPoint(1,0) + radius;
364 const T minBoundZ = keyPoint(2,0) - radius;
365 const T maxBoundZ = keyPoint(2,0) + radius;
367 Eigen::Matrix<T,3,1> feature;
368 std::vector<int> goodIndices;
369 for (
int j = 0; j < inputFeatDim; ++j)
372 if(feature(0,0) <= maxBoundX && feature(0,0) >= minBoundX &&
373 feature(1,0) <= maxBoundY && feature(1,0) >= minBoundY &&
374 feature(2,0) <= maxBoundZ && feature(2,0) >= minBoundZ &&
377 goodIndices.push_back(j);
380 const int colCount = goodIndices.size();
384 ++(
data.unfitPointsCount);
388 const int featDim(
data.features.rows());
390 Matrix d(featDim-1, colCount);
393 for (
int j = 0; j < colCount; ++j)
395 d.col(j) =
data.features.block(0,
data.indices[goodIndices[j]],featDim-1, 1);
396 t.col(j) =
data.times.col(
data.indices[goodIndices[j]]);
399 const Vector mean = d.rowwise().sum() /
T(colCount);
400 const Matrix NN = d.colwise() - mean;
401 const std::int64_t minTime = t.minCoeff();
402 const std::int64_t maxTime = t.maxCoeff();
403 const std::int64_t meanTime = t.sum() /
T(colCount);
405 const Matrix C(NN * NN.transpose());
406 Vector eigenVa = Vector::Identity(featDim-1, 1);
407 Matrix eigenVe = Matrix::Identity(featDim-1, featDim-1);
409 if(keepNormals || keepEigenValues || keepEigenVectors || keepCovariances || keepGestaltFeatures)
411 if(C.fullPivHouseholderQr().rank()+1 >= featDim-1)
413 const Eigen::EigenSolver<Matrix> solver(C);
414 eigenVa = solver.eigenvalues().real();
415 eigenVe = solver.eigenvectors().real();
419 data.unfitPointsCount += colCount;
423 Eigen::Matrix<T,3,1> normal, newX, newY;
424 Eigen::Matrix<T,3,3> newBasis;
425 double planarity = 0.;
426 double cylindricality = 0.;
428 if(keepNormals || keepGestaltFeatures)
431 normal = computeNormal<T>(eigenVa, eigenVe);
433 if(keepGestaltFeatures)
435 Vector eigenVaSort = sortEigenValues<T>(eigenVa);
436 planarity = 2 * (eigenVaSort(1) - eigenVaSort(0))/eigenVaSort.sum();
437 cylindricality = (eigenVaSort(2) - eigenVaSort(1))/eigenVaSort.sum();
439 Eigen::Matrix<T,3,1> up, base;
442 newX << normal(0), normal(1), 0;
444 newY = up.cross(newX);
445 newY = newY / newY.norm();
447 newBasis << newX(0), newY(0), up(0),
448 newX(1), newY(1), up(1),
449 newX(2), newY(2), up(2);
454 data.unfitPointsCount += colCount;
458 if(acos(normal.dot(up)) < abs(10 * M_PI/180))
460 data.unfitPointsCount += colCount;
465 for (
int j = 0; j < colCount; ++j)
467 data.warpedXYZ->col(j) = ((
data.features.block(0,j,3,1) - keyPoint).transpose() * newBasis).transpose();
471 Vector angles(colCount), radii(colCount), heights(colCount);
472 Matrix gestaltMeans(4, 8), gestaltVariances(4, 8), numOfValues(4, 8);
473 if(keepGestaltFeatures)
478 heights =
data.warpedXYZ->row(2);
481 const T angularBinWidth = M_PI/4;
482 const T radialBinWidth = radius/4;
483 Eigen::MatrixXi indices(2, colCount);
484 gestaltMeans = Matrix::Zero(4, 8);
485 gestaltVariances = Matrix::Zero(4, 8);
486 numOfValues = Matrix::Zero(4, 8);
488 for (
int it=0; it < colCount; ++it)
490 indices(0,it) = floor(radii(it)/radialBinWidth);
492 if(indices(0,it) > 3)
495 indices(1,it) = floor(angles(it)/angularBinWidth);
496 if(indices(1,it) > 7)
498 gestaltMeans(indices(0,it), indices(1,it)) += heights(it);
499 ++(numOfValues(indices(0,it), indices(1,it)));
502 for (
int radial=0; radial < 4; ++radial)
504 for (
int angular = 0; angular < 8; ++angular)
506 if (numOfValues(radial, angular) > 0)
508 gestaltMeans(radial, angular) = gestaltMeans(radial, angular)/numOfValues(radial, angular);
512 for (
int it=0; it < colCount; ++it)
514 gestaltVariances(indices(0,it), indices(1,it)) += (heights(it)-gestaltMeans(indices(0,it), indices(1,it))) * (heights(it)-gestaltMeans(indices(0,it), indices(1,it)));
516 for (
int radial=0; radial < 4; ++radial)
518 for (
int angular = 0; angular < 8; ++angular)
521 if (gestaltMeans(radial,angular) == 0 && radial > 0)
523 gestaltMeans(radial, angular) = gestaltMeans(radial-1, angular);
524 gestaltVariances(radial, angular) = gestaltVariances(radial-1, angular);
526 else if (numOfValues(radial, angular) > 0)
528 gestaltVariances(radial, angular) = gestaltVariances(radial, angular)/numOfValues(radial, angular);
536 serialEigVector = serializeEigVec<T>(eigenVe);
539 serialCovVector = serializeEigVec<T>(C);
540 Vector serialGestaltMeans;
541 Vector serialGestaltVariances;
542 if(keepGestaltFeatures)
548 if(
data.descriptors.rows() != 0)
549 assert(
data.descriptors.cols() != 0);
552 data.times(0,
data.indicesToKeep[i]) = minTime;
553 data.times(1,
data.indicesToKeep[i]) = maxTime;
554 data.times(2,
data.indicesToKeep[i]) = meanTime;
558 data.normals->col(
data.indicesToKeep[i]) = normal;
560 data.means->col(
data.indicesToKeep[i]) = mean;
562 data.eigenValues->col(
data.indicesToKeep[i]) = eigenVa;
564 data.eigenVectors->col(
data.indicesToKeep[i]) = serialEigVector;
566 data.covariance->col(
data.indicesToKeep[i]) = serialCovVector;
567 if(keepGestaltFeatures)
570 data.gestaltMeans->col(
data.indicesToKeep[i]) = serialGestaltMeans;
571 data.gestaltVariances->col(
data.indicesToKeep[i]) = serialGestaltVariances;
572 (*
data.gestaltShapes)(0,
data.indicesToKeep[i]) = planarity;
573 (*
data.gestaltShapes)(1,
data.indicesToKeep[i]) = cylindricality;
576 indicesToKeepStrict.push_back(
data.indicesToKeep[i]);
578 data.indicesToKeep = indicesToKeepStrict;
586 const int dim = gestaltFeatures.rows() * gestaltFeatures.cols();
588 for(
int k=0; k < gestaltFeatures.rows(); ++k)
590 output.segment(k*gestaltFeatures.cols(), gestaltFeatures.cols()) =
591 gestaltFeatures.row(k).transpose();
599 const Matrix& points,
const Eigen::Matrix<T,3,1>& keyPoint)
const
601 const unsigned int dim(points.cols());
604 for (
unsigned int i = 0; i <
dim; ++i)
606 angles(i) = atan2(points(0,i), points(1,i));
608 angles(i) += (2 * M_PI);
617 const Matrix& points,
const Eigen::Matrix<T,3,1>& keyPoint)
const
619 const unsigned int dim(points.cols());
622 for (
unsigned int i = 0; i <
dim; ++i)
624 radii(i) = sqrt((points(0,i)) * (points(0,i)) + (points(1,i)) * (points(1,i)));