Пример #1
0
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));
    }
}
Пример #2
0
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);
    }
}
Пример #3
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);
    }
}