void EstimateRankFilter::filter(PointView& view) { KD3Index& kdi = view.build3dIndex(); for (PointId i = 0; i < view.size(); ++i) { // find the k-nearest neighbors auto ids = kdi.neighbors(i, m_knn); view.setField(m_rank, i, eigen::computeRank(view, ids, m_thresh)); } }
void NormalFilter::filter(PointView& view) { KD3Index& kdi = view.build3dIndex(); for (PointId i = 0; i < view.size(); ++i) { // find the k-nearest neighbors auto ids = kdi.neighbors(i, m_knn); // compute covariance of the neighborhood auto B = eigen::computeCovariance(view, ids); // perform the eigen decomposition Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> solver(B); if (solver.info() != Eigen::Success) throwError("Cannot perform eigen decomposition."); auto eval = solver.eigenvalues(); Eigen::Vector3f normal = solver.eigenvectors().col(0); if (m_viewpointArg->set()) { PointRef p = view.point(i); Eigen::Vector3f vp( m_viewpoint.x - p.getFieldAs<double>(Dimension::Id::X), m_viewpoint.y - p.getFieldAs<double>(Dimension::Id::Y), m_viewpoint.z - p.getFieldAs<double>(Dimension::Id::Z)); if (vp.dot(normal) < 0) normal *= -1.0; } else if (m_up) { if (normal[2] < 0) normal *= -1.0; } view.setField(Dimension::Id::NormalX, i, normal[0]); view.setField(Dimension::Id::NormalY, i, normal[1]); view.setField(Dimension::Id::NormalZ, i, normal[2]); double sum = eval[0] + eval[1] + eval[2]; view.setField(Dimension::Id::Curvature, i, sum ? std::fabs(eval[0] / sum) : 0); } }
void LOFFilter::filter(PointView& view) { using namespace Dimension; KD3Index& index = view.build3dIndex(); // Increment the minimum number of points, as knnSearch will be returning // the neighbors along with the query point. m_minpts++; // First pass: Compute the k-distance for each point. // The k-distance is the Euclidean distance to k-th nearest neighbor. log()->get(LogLevel::Debug) << "Computing k-distances...\n"; for (PointId i = 0; i < view.size(); ++i) { std::vector<PointId> indices(m_minpts); std::vector<double> sqr_dists(m_minpts); index.knnSearch(i, m_minpts, &indices, &sqr_dists); view.setField(m_kdist, i, std::sqrt(sqr_dists[m_minpts-1])); } // Second pass: Compute the local reachability distance for each point. // For each neighbor point, the reachability distance is the maximum value // of that neighbor's k-distance and the distance between the neighbor and // the current point. The lrd is the inverse of the mean of the reachability // distances. log()->get(LogLevel::Debug) << "Computing lrd...\n"; for (PointId i = 0; i < view.size(); ++i) { std::vector<PointId> indices(m_minpts); std::vector<double> sqr_dists(m_minpts); index.knnSearch(i, m_minpts, &indices, &sqr_dists); double M1 = 0.0; point_count_t n = 0; for (PointId j = 0; j < indices.size(); ++j) { double k = view.getFieldAs<double>(m_kdist, indices[j]); double reachdist = (std::max)(k, std::sqrt(sqr_dists[j])); M1 += (reachdist - M1) / ++n; } view.setField(m_lrd, i, 1.0 / M1); } // Third pass: Compute the local outlier factor for each point. // The LOF is the average of the lrd's for a neighborhood of points. log()->get(LogLevel::Debug) << "Computing LOF...\n"; for (PointId i = 0; i < view.size(); ++i) { double lrdp = view.getFieldAs<double>(m_lrd, i); std::vector<PointId> indices(m_minpts); std::vector<double> sqr_dists(m_minpts); index.knnSearch(i, m_minpts, &indices, &sqr_dists); double M1 = 0.0; point_count_t n = 0; for (auto const& j : indices) { M1 += (view.getFieldAs<double>(m_lrd, j) / lrdp - M1) / ++n; } view.setField(m_lof, i, M1); } }