示例#1
0
PointViewSet LocateFilter::run(PointViewPtr inView)
{
    PointViewSet viewSet;
    if (!inView->size())
        return viewSet;

    PointId minidx, maxidx;
    double minval = (std::numeric_limits<double>::max)();
    double maxval = std::numeric_limits<double>::lowest();

    for (PointId idx = 0; idx < inView->size(); idx++)
    {
        double val = inView->getFieldAs<double>(m_dimId, idx);
        if (val > maxval)
        {
            maxval = val;
            maxidx = idx;
        }
        if (val < minval)
        {
            minval = val;
            minidx = idx;
        }
    }

    PointViewPtr outView = inView->makeNew();

    if (Utils::iequals("min", m_minmax))
        outView->appendPoint(*inView.get(), minidx);
    if (Utils::iequals("max", m_minmax))
        outView->appendPoint(*inView.get(), maxidx);

    viewSet.insert(outView);
    return viewSet;
}
示例#2
0
void ignoreDimRange(DimRange dr, PointViewPtr input, PointViewPtr keep,
                    PointViewPtr ignore)
{
    PointRef point(*input, 0);
    for (PointId i = 0; i < input->size(); ++i)
    {
        point.setPointId(i);
        if (dr.valuePasses(point.getFieldAs<double>(dr.m_id)))
            ignore->appendPoint(*input, i);
        else
            keep->appendPoint(*input, i);
    }
}
示例#3
0
void segmentLastReturns(PointViewPtr input, PointViewPtr last,
                        PointViewPtr other)
{
    PointRef point(*input, 0);
    for (PointId i = 0; i < input->size(); ++i)
    {
        point.setPointId(i);
        if (point.getFieldAs<uint8_t>(Dimension::Id::ReturnNumber) ==
            point.getFieldAs<uint8_t>(Dimension::Id::NumberOfReturns))
            last->appendPoint(*input, i);
        else
            other->appendPoint(*input, i);
    }
}
示例#4
0
PointViewSet PredicateFilter::run(PointViewPtr view)
{
    MetadataNode n;

    m_pythonMethod->resetArguments();
    m_pythonMethod->begin(*view, n);
    m_pythonMethod->execute();

    if (!m_pythonMethod->hasOutputVariable("Mask"))
        throw pdal::pdal_error("Mask variable not set in predicate "
            "filter function.");

    PointViewPtr outview = view->makeNew();

    void *pydata =
        m_pythonMethod->extractResult("Mask", Dimension::Type::Unsigned8);
    char *ok = (char *)pydata;
    for (PointId idx = 0; idx < view->size(); ++idx)
        if (*ok++)
            outview->appendPoint(*view, idx);

    PointViewSet viewSet;
    viewSet.insert(outview);
    return viewSet;
}
示例#5
0
void HAGFilter::filter(PointView& view)
{
    PointViewPtr gView = view.makeNew();
    PointViewPtr ngView = view.makeNew();
    std::vector<PointId> gIdx, ngIdx;

    // First pass: Separate into ground and non-ground views.
    for (PointId i = 0; i < view.size(); ++i)
    {
        double c = view.getFieldAs<double>(Dimension::Id::Classification, i);
        if (c == 2)
        {
            gView->appendPoint(view, i);
            gIdx.push_back(i);
        }
        else
        {
            ngView->appendPoint(view, i);
            ngIdx.push_back(i);
        }
    }

    // Bail if there weren't any points classified as ground.
    if (gView->size() == 0)
        throwError("Input PointView does not have any points classified "
            "as ground");

    // Build the 2D KD-tree.
    KD2Index kdi(*gView);
    kdi.build();

    // Second pass: Find Z difference between non-ground points and the nearest
    // neighbor (2D) in the ground view.
    for (PointId i = 0; i < ngView->size(); ++i)
    {
        PointRef point = ngView->point(i);
        double z0 = point.getFieldAs<double>(Dimension::Id::Z);
        auto ids = kdi.neighbors(point, 1);
        double z1 = gView->getFieldAs<double>(Dimension::Id::Z, ids[0]);
        view.setField(Dimension::Id::HeightAboveGround, ngIdx[i], z0 - z1);
    }

    // Final pass: Ensure that all ground points have height value pegged at 0.
    for (auto const& i : gIdx)
        view.setField(Dimension::Id::HeightAboveGround, i, 0.0);
}
示例#6
0
MetadataNode InfoKernel::dumpQuery(PointViewPtr inView) const
{
    int count;
    std::string location;

    // See if there's a provided point count.
    StringList parts = Utils::split2(m_queryPoint, '/');
    if (parts.size() == 2)
    {
        location = parts[0];
        count = atoi(parts[1].c_str());
    }
    else if (parts.size() == 1)
    {
        location = parts[0];
        count = inView->size();
    }
    else
        count = 0;
    if (count == 0)
        throw pdal_error("Invalid location specificiation. "
            "--query=\"X,Y[/count]\"");

    auto seps = [](char c){ return (c == ',' || c == '|' || c == ' '); };

    std::vector<std::string> tokens = Utils::split2(location, seps);
    std::vector<double> values;
    for (auto ti = tokens.begin(); ti != tokens.end(); ++ti)
    {
        double d;
        if (Utils::fromString(*ti, d))
            values.push_back(d);
    }

    if (values.size() != 2 && values.size() != 3)
        throw pdal_error("--points must be two or three values");

    PointViewPtr outView = inView->makeNew();

    std::vector<PointId> ids;
    if (values.size() >= 3)
    {
        KD3Index kdi(*inView);
        kdi.build();
        ids = kdi.neighbors(values[0], values[1], values[2], count);
    }
    else
    {
        KD2Index kdi(*inView);
        kdi.build();
        ids = kdi.neighbors(values[0], values[1], count);
    }

    for (auto i = ids.begin(); i != ids.end(); ++i)
        outView->appendPoint(*inView.get(), *i);

    return outView->toMetadata();
}
示例#7
0
PointViewSet PMFFilter::run(PointViewPtr input)
{
    bool logOutput = log()->getLevel() > LogLevel::Debug1;
    if (logOutput)
        log()->floatPrecision(8);
    log()->get(LogLevel::Debug2) << "Process PMFFilter...\n";

    auto idx = processGround(input);

    PointViewSet viewSet;
    if (!idx.empty() && (m_classify || m_extract))
    {

        if (m_classify)
        {
            log()->get(LogLevel::Debug2) << "Labeled " << idx.size() << " ground returns!\n";

            // set the classification label of ground returns as 2
            // (corresponding to ASPRS LAS specification)
            for (const auto& i : idx)
            {
                input->setField(Dimension::Id::Classification, i, 2);
            }

            viewSet.insert(input);
        }

        if (m_extract)
        {
            log()->get(LogLevel::Debug2) << "Extracted " << idx.size() << " ground returns!\n";

            // create new PointView containing only ground returns
            PointViewPtr output = input->makeNew();
            for (const auto& i : idx)
            {
                output->appendPoint(*input, i);
            }

            viewSet.erase(input);
            viewSet.insert(output);
        }
    }
    else
    {
        if (idx.empty())
            log()->get(LogLevel::Debug2) << "Filtered cloud has no ground returns!\n";

        if (!(m_classify || m_extract))
            log()->get(LogLevel::Debug2) << "Must choose --classify or --extract\n";

        // return the input buffer unchanged
        viewSet.insert(input);
    }

    return viewSet;
}
示例#8
0
point_count_t RxpPointcloud::writeSavedPoints(PointViewPtr view, point_count_t count)
{
    point_count_t numRead = 0;
    while (m_idx < m_view->size() && numRead < count)
    {
        view->appendPoint(*m_view, m_idx);
        ++m_idx, ++numRead;
    }
    return numRead;
};
示例#9
0
文件: SMRFilter.cpp 项目: PDAL/PDAL
PointViewSet SMRFilter::run(PointViewPtr view)
{
    log()->get(LogLevel::Info) << "run: Process SMRFilter...\n";

    std::vector<PointId> idx = processGround(view);

    PointViewSet viewSet;

    if (!idx.empty() && (m_classify || m_extract))
    {

        if (m_classify)
        {
            log()->get(LogLevel::Info) << "run: Labeled " << idx.size() << " ground returns!\n";

            // set the classification label of ground returns as 2
            // (corresponding to ASPRS LAS specification)
            for (const auto& i : idx)
            {
                view->setField(Dimension::Id::Classification, i, 2);
            }

            viewSet.insert(view);
        }

        if (m_extract)
        {
            log()->get(LogLevel::Info) << "run: Extracted " << idx.size() << " ground returns!\n";

            // create new PointView containing only ground returns
            PointViewPtr output = view->makeNew();
            for (const auto& i : idx)
            {
                output->appendPoint(*view, i);
            }

            viewSet.erase(view);
            viewSet.insert(output);
        }
    }
    else
    {
        if (idx.empty())
            log()->get(LogLevel::Info) << "run: Filtered cloud has no ground returns!\n";

        if (!(m_classify || m_extract))
            log()->get(LogLevel::Info) << "run: Must choose --classify or --extract\n";

        // return the view buffer unchanged
        viewSet.insert(view);
    }

    return viewSet;
}
示例#10
0
 PointViewSet run(PointViewPtr view)
 {
     if (m_count > view->size())
         log()->get(LogLevel::Warning)
             << "Requested number of points (count=" << m_count
             << ") exceeds number of available points.\n";
     PointViewSet viewSet;
     PointViewPtr outView = view->makeNew();
     for (PointId i = view->size() - std::min(m_count, view->size());
          i < view->size(); ++i)
         outView->appendPoint(*view, i);
     viewSet.insert(outView);
     return viewSet;
 }
示例#11
0
 virtual PointViewSet run(PointViewPtr view)
 {
     PointViewSet out;
     PointViewPtr v = view->makeNew();
     for (PointId i = 0; i < view->size(); ++i)
     {
         if (i && (i % m_viewSize == 0))
         {
             out.insert(v);
             v = v->makeNew();
         }
         v->appendPoint(*view, i);
     }
     out.insert(v);
     return out;
 }
示例#12
0
PointViewSet SampleFilter::run(PointViewPtr inView)
{
    point_count_t np = inView->size();

    // Return empty PointViewSet if the input PointView has no points.
    // Otherwise, make a new output PointView.
    PointViewSet viewSet;
    if (!np)
        return viewSet;
    PointViewPtr outView = inView->makeNew();

    // Build the 3D KD-tree.
    KD3Index index(*inView);
    index.build();

    // All points are marked as kept (1) by default. As they are masked by
    // neighbors within the user-specified radius, their value is changed to 0.
    std::vector<int> keep(np, 1);

    // We are able to subsample in a single pass over the shuffled indices.
    for (PointId i = 0; i < np; ++i)
    {
        // If a point is masked, it is forever masked, and cannot be part of the
        // sampled cloud. Otherwise, the current index is appended to the output
        // PointView.
        if (keep[i] == 0)
            continue;
        outView->appendPoint(*inView, i);

        // We now proceed to mask all neighbors within m_radius of the kept
        // point.
        auto ids = index.radius(i, m_radius);
        for (auto const& id : ids)
            keep[id] = 0;
    }

    // Simply calculate the percentage of retained points.
    double frac = (double)outView->size() / (double)inView->size();
    log()->get(LogLevel::Debug2)
        << "Retaining " << outView->size() << " of " << inView->size()
        << " points (" << 100 * frac << "%)\n";

    viewSet.insert(outView);
    return viewSet;
}
示例#13
0
PointViewSet RangeFilter::run(PointViewPtr inView)
{
    PointViewSet viewSet;
    if (!inView->size())
        return viewSet;

    PointViewPtr outView = inView->makeNew();

    for (PointId i = 0; i < inView->size(); ++i)
    {
        PointRef point = inView->point(i);
        if (processOne(point))
            outView->appendPoint(*inView, i);
    }

    viewSet.insert(outView);
    return viewSet;
}
示例#14
0
PointViewSet MADFilter::run(PointViewPtr view)
{
    using namespace Dimension;

    PointViewSet viewSet;
    PointViewPtr output = view->makeNew();

    auto estimate_median = [](std::vector<double> vals)
    {
        std::nth_element(vals.begin(), vals.begin()+vals.size()/2, vals.end());
        return *(vals.begin()+vals.size()/2);
    };

    std::vector<double> z(view->size());
    for (PointId j = 0; j < view->size(); ++j)
        z[j] = view->getFieldAs<double>(m_dimId, j);

    double median = estimate_median(z);
    log()->get(LogLevel::Debug) << getName() << " estimated median value: " << median << std::endl;

    std::transform(z.begin(), z.end(), z.begin(),
       [median](double v) { return std::fabs(v - median); });
    double mad = estimate_median(z)*m_madMultiplier;
    log()->get(LogLevel::Debug) << getName() << " mad " << mad << std::endl;

    for (PointId j = 0; j < view->size(); ++j)
    {
        if (z[j]/mad < m_multiplier)
            output->appendPoint(*view, j);
    }

    double low_fence = median - m_multiplier * mad;
    double hi_fence = median + m_multiplier * mad;

    log()->get(LogLevel::Debug) << getName() << " cropping " << m_dimName
                                << " in the range (" << low_fence
                                << "," << hi_fence << ")" << std::endl;

    viewSet.erase(view);
    viewSet.insert(output);

    return viewSet;
}
示例#15
0
MetadataNode InfoKernel::dumpPoints(PointViewPtr inView) const
{
    MetadataNode root;
    PointViewPtr outView = inView->makeNew();

    // Stick points in a inViewfer.
    std::vector<PointId> points = getListOfPoints(m_pointIndexes);
    for (size_t i = 0; i < points.size(); ++i)
    {
        PointId id = (PointId)points[i];
        if (id < inView->size())
            outView->appendPoint(*inView.get(), id);
    }

    MetadataNode tree = outView->toMetadata();
    std::string prefix("point ");
    for (size_t i = 0; i < outView->size(); ++i)
    {
        MetadataNode n = tree.findChild(std::to_string(i));
        n.add("PointId", points[i]);
        root.add(n.clone("point"));
    }
    return root;
}
void RialtoReader::doQuery(const TileMath& tmm,
                           const GpkgTile& tile,
                           PointViewPtr view,
                           double qMinX, double qMinY, double qMaxX, double qMaxY)
{
    const uint32_t level = tile.getLevel();
    const uint32_t column = tile.getColumn();
    const uint32_t row = tile.getRow();
    const uint32_t numPoints = tile.getNumPoints();
    
    // if this tile is entirely inside the query box, then
    // we won't need to check each point
    double tileMinX, tileMinY, tileMaxX, tileMaxY;
    tmm.getTileBounds(column, row, level,
                      tileMinX, tileMinY, tileMaxX, tileMaxY);
    const bool tileEntirelyInsideQueryBox =
        tmm.rectContainsRect(qMinX, qMinY, qMaxX, qMaxY,
                             tileMinX, tileMinY, tileMaxX, tileMaxY);

    log()->get(LogLevel::Debug) << "  intersecting tile "
        << "(" << level << "," << column << "," << row << ")" 
        << " contains " << numPoints << " points" << std::endl;

    PointViewPtr tempView = view->makeNew();

    GpkgTile::exportToPV(numPoints, tempView, tile.getBlob());

    for (uint32_t i=0; i<tempView->size(); i++) {
        const double x = tempView->getFieldAs<double>(Dimension::Id::X, i);
        const double y = tempView->getFieldAs<double>(Dimension::Id::Y, i);
        if (tileEntirelyInsideQueryBox || (x >= qMinX && x <= qMaxX && y >= qMinY && y <= qMaxY))
        {
            view->appendPoint(*tempView, i);
        }
    }
}
示例#17
0
PointViewSet RadiusOutlierFilter::run(PointViewPtr input)
{
    bool logOutput = log()->getLevel() > LogLevel::Debug1;
    if (logOutput)
        log()->floatPrecision(8);
    log()->get(LogLevel::Debug2) << "Process RadiusOutlierFilter...\n";

    // convert PointView to PointXYZ
    typedef pcl::PointCloud<pcl::PointXYZ> Cloud;
    Cloud::Ptr cloud(new Cloud);
    BOX3D bounds;
    input->calculateBounds(bounds);
    pclsupport::PDALtoPCD(input, *cloud, bounds);

    pclsupport::setLogLevel(log()->getLevel());

    // setup the outlier filter
    pcl::RadiusOutlierRemoval<pcl::PointXYZ> ror(true);
    ror.setInputCloud(cloud);
    ror.setMinNeighborsInRadius(m_min_neighbors);
    ror.setRadiusSearch(m_radius);

    pcl::PointCloud<pcl::PointXYZ> output;
    ror.setNegative(true);
    ror.filter(output);

    // filtered to return inliers
    pcl::PointIndicesPtr inliers(new pcl::PointIndices);
    ror.getRemovedIndices(*inliers);

    PointViewSet viewSet;
    if (inliers->indices.empty())
    {
        log()->get(LogLevel::Warning) << "Requested filter would remove all points. Try a larger radius/smaller minimum neighbors.\n";
        viewSet.insert(input);
        return viewSet;
    }

    // inverse are the outliers
    std::vector<int> outliers(input->size()-inliers->indices.size());
    for (PointId i = 0, j = 0, k = 0; i < input->size(); ++i)
    {
        if (i == (PointId)inliers->indices[j])
        {
            j++;
            continue;
        }
        outliers[k++] = i;
    }

    if (!outliers.empty() && (m_classify || m_extract))
    {

        if (m_classify)
        {
            log()->get(LogLevel::Debug2) << "Labeled " << outliers.size() << " outliers as noise!\n";

            // set the classification label of outlier returns as 18
            // (corresponding to ASPRS LAS specification for high noise)
            for (const auto& i : outliers)
            {
                input->setField(Dimension::Id::Classification, i, 18);
            }

            viewSet.insert(input);
        }

        if (m_extract)
        {
            log()->get(LogLevel::Debug2) << "Extracted " << inliers->indices.size() << " inliers!\n";

            // create new PointView containing only outliers
            PointViewPtr output = input->makeNew();
            for (const auto& i : inliers->indices)
            {
                output->appendPoint(*input, i);
            }

            viewSet.erase(input);
            viewSet.insert(output);
        }
    }
    else
    {
        if (outliers.empty())
            log()->get(LogLevel::Warning) << "Filtered cloud has no outliers!\n";

        if (!(m_classify || m_extract))
            log()->get(LogLevel::Warning) << "Must choose --classify or --extract\n";

        // return the input buffer unchanged
        viewSet.insert(input);
    }

    return viewSet;
}
示例#18
0
std::vector<PointId> PMFFilter::processGround(PointViewPtr view)
{
    // Compute the series of window sizes and height thresholds
    std::vector<float> htvec;
    std::vector<float> wsvec;
    int iter = 0;
    float ws = 0.0f;
    float ht = 0.0f;

    while (ws < m_maxWindowSize)
    {
        // Determine the initial window size.
        if (1) // exponential
            ws = m_cellSize * (2.0f * std::pow(2, iter) + 1.0f);
        else
            ws = m_cellSize * (2.0f * (iter+1) * 2 + 1.0f);

        // Calculate the height threshold to be used in the next iteration.
        if (iter == 0)
            ht = m_initialDistance;
        else
            ht = m_slope * (ws - wsvec[iter-1]) * m_cellSize + m_initialDistance;

        // Enforce max distance on height threshold
        if (ht > m_maxDistance)
            ht = m_maxDistance;

        wsvec.push_back(ws);
        htvec.push_back(ht);

        iter++;
    }

    std::vector<PointId> groundIdx;
    for (PointId i = 0; i < view->size(); ++i)
        groundIdx.push_back(i);

    // Progressively filter ground returns using morphological open
    for (size_t j = 0; j < wsvec.size(); ++j)
    {
        // Limit filtering to those points currently considered ground returns
        PointViewPtr ground = view->makeNew();
        for (PointId i = 0; i < groundIdx.size(); ++i)
            ground->appendPoint(*view, groundIdx[i]);

        log()->get(LogLevel::Debug) <<  "Iteration " << j
                                    << " (height threshold = " << htvec[j]
                                    << ", window size = " << wsvec[j]
                                    << ")...\n";

        // Create new cloud to hold the filtered results. Apply the
        // morphological opening operation at the current window size.
        auto maxZ = morphOpen(ground, wsvec[j]*0.5);

        // Find indices of the points whose difference between the source and
        // filtered point clouds is less than the current height threshold.
        std::vector<PointId> groundNewIdx;
        for (PointId i = 0; i < ground->size(); ++i)
        {
            double z0 = ground->getFieldAs<double>(Dimension::Id::Z, i);
            float diff = z0 - maxZ[i];
            if (diff < htvec[j])
                groundNewIdx.push_back(groundIdx[i]);
        }
        groundIdx.swap(groundNewIdx);
        
        log()->get(LogLevel::Debug) << "Ground now has " << groundIdx.size()
                                    << " points.\n";
    }

    return groundIdx;
}
示例#19
0
std::vector<PointId> PMFFilter::processGround(PointViewPtr view)
{
    point_count_t np(view->size());

    // Compute the series of window sizes and height thresholds
    std::vector<float> height_thresholds;
    std::vector<float> window_sizes;
    int iteration = 0;
    float window_size = 0.0f;
    float height_threshold = 0.0f;

    while (window_size < m_maxWindowSize)
    {
        // Determine the initial window size.
        if (1) // exponential
            window_size = m_cellSize * (2.0f * std::pow(2, iteration) + 1.0f);
        else
            window_size = m_cellSize * (2.0f * (iteration+1) * 2 + 1.0f);

        // Calculate the height threshold to be used in the next iteration.
        if (iteration == 0)
            height_threshold = m_initialDistance;
        else
            height_threshold = m_slope * (window_size - window_sizes[iteration-1]) * m_cellSize + m_initialDistance;

        // Enforce max distance on height threshold
        if (height_threshold > m_maxDistance)
            height_threshold = m_maxDistance;

        window_sizes.push_back(window_size);
        height_thresholds.push_back(height_threshold);

        iteration++;
    }

    std::vector<PointId> groundIdx;
    for (PointId i = 0; i < np; ++i)
        groundIdx.push_back(i);

    // Progressively filter ground returns using morphological open
    for (size_t j = 0; j < window_sizes.size(); ++j)
    {
        // Limit filtering to those points currently considered ground returns
        PointViewPtr ground = view->makeNew();
        for (PointId i = 0; i < groundIdx.size(); ++i)
            ground->appendPoint(*view, groundIdx[i]);

        printf("      Iteration %ld (height threshold = %f, window size = %f)...",
               j, height_thresholds[j], window_sizes[j]);

        // Create new cloud to hold the filtered results. Apply the morphological
        // opening operation at the current window size.
        auto maxZ = morphOpen(ground, window_sizes[j]*0.5);

        // Find indices of the points whose difference between the source and
        // filtered point clouds is less than the current height threshold.
        std::vector<PointId> pt_indices;
        for (PointId i = 0; i < ground->size(); ++i)
        {
            double z0 = ground->getFieldAs<double>(Dimension::Id::Z, i);
            double z1 = maxZ[i];
            float diff = z0 - z1;
            if (diff < height_thresholds[j])
                pt_indices.push_back(groundIdx[i]);
        }
        groundIdx.swap(pt_indices);
    }

    return groundIdx;
}
示例#20
0
PointViewSet DartSampleFilter::run(PointViewPtr input)
{
    PointViewSet viewSet;
    PointViewPtr output = input->makeNew();

    log()->floatPrecision(2);
    log()->get(LogLevel::Info) << "DartSampleFilter (radius="
                               << m_radius << ")\n";

    BOX3D buffer_bounds;
    input->calculateBounds(buffer_bounds);

    typedef pcl::PointCloud<pcl::PointXYZ> Cloud;
    Cloud::Ptr cloud(new Cloud);
    pclsupport::PDALtoPCD(input, *cloud, buffer_bounds);

    int level = log()->getLevel();
    switch (level)
    {
        case 0:
            pcl::console::setVerbosityLevel(pcl::console::L_ALWAYS);
            break;
        case 1:
            pcl::console::setVerbosityLevel(pcl::console::L_ERROR);
            break;
        case 2:
            pcl::console::setVerbosityLevel(pcl::console::L_WARN);
            break;
        case 3:
            pcl::console::setVerbosityLevel(pcl::console::L_INFO);
            break;
        case 4:
            pcl::console::setVerbosityLevel(pcl::console::L_DEBUG);
            break;
        default:
            pcl::console::setVerbosityLevel(pcl::console::L_VERBOSE);
            break;
    }

    pcl::DartSample<pcl::PointXYZ> ds;
    ds.setInputCloud(cloud);
    ds.setRadius(m_radius);

    std::vector<int> samples;
    ds.filter(samples);

    if (samples.empty())
    {
        log()->get(LogLevel::Warning) << "Filtered cloud has no points!\n";
        return viewSet;
    }

    for (const auto& i : samples)
        output->appendPoint(*input, i);

    double frac = (double)samples.size() / (double)cloud->size();
    log()->get(LogLevel::Info) << "Retaining " << samples.size() << " of "
                               << cloud->size() << " points ("
                               <<  100*frac
                               << "%)\n";

    viewSet.insert(output);
    return viewSet;
}
示例#21
0
PointViewSet StatisticalOutlierFilter::run(PointViewPtr input)
{
    bool logOutput = log()->getLevel() > LogLevel::Debug1;
    if (logOutput)
        log()->floatPrecision(8);
    log()->get(LogLevel::Debug2) << "Process StatisticalOutlierFilter...\n";

    // convert PointView to PointXYZ
    typedef pcl::PointCloud<pcl::PointXYZ> Cloud;
    Cloud::Ptr cloud(new Cloud);
    BOX3D bounds;
    input->calculateBounds(bounds);
    pclsupport::PDALtoPCD(input, *cloud, bounds);

    // PCL should provide console output at similar verbosity level as PDAL
    int level = log()->getLevel();
    switch (level)
    {
        case 0:
            pcl::console::setVerbosityLevel(pcl::console::L_ALWAYS);
            break;
        case 1:
            pcl::console::setVerbosityLevel(pcl::console::L_ERROR);
            break;
        case 2:
            pcl::console::setVerbosityLevel(pcl::console::L_WARN);
            break;
        case 3:
            pcl::console::setVerbosityLevel(pcl::console::L_INFO);
            break;
        case 4:
            pcl::console::setVerbosityLevel(pcl::console::L_DEBUG);
            break;
        default:
            pcl::console::setVerbosityLevel(pcl::console::L_VERBOSE);
            break;
    }

    // setup the outlier filter
    pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor(true);
    sor.setInputCloud(cloud);
    sor.setMeanK(m_meanK);
    sor.setStddevMulThresh(m_multiplier);

    pcl::PointCloud<pcl::PointXYZ> output;
    sor.setNegative(true);
    sor.filter(output);

    // filtered to return inliers
    pcl::PointIndicesPtr inliers(new pcl::PointIndices);
    sor.getRemovedIndices(*inliers);

    log()->get(LogLevel::Debug2) << inliers->indices.size() << std::endl;

    PointViewSet viewSet;
    if (inliers->indices.empty())
    {
        log()->get(LogLevel::Warning) << "Requested filter would remove all points. Try increasing the multiplier.\n";
        viewSet.insert(input);
        return viewSet;
    }

    // inverse are the outliers
    std::vector<int> outliers(input->size()-inliers->indices.size());
    for (PointId i = 0, j = 0, k = 0; i < input->size(); ++i)
    {
        if (i == (PointId)inliers->indices[j])
        {
            j++;
            continue;
        }
        outliers[k++] = i;
    }

    if (!outliers.empty() && (m_classify || m_extract))
    {

        if (m_classify)
        {
            log()->get(LogLevel::Debug2) << "Labeled " << outliers.size() << " outliers as noise!\n";

            // set the classification label of outlier returns as 18
            // (corresponding to ASPRS LAS specification for high noise)
            for (const auto& i : outliers)
            {
                input->setField(Dimension::Id::Classification, i, 18);
            }

            viewSet.insert(input);
        }

        if (m_extract)
        {
            log()->get(LogLevel::Debug2) << "Extracted " << inliers->indices.size() << " inliers!\n";

            // create new PointView containing only outliers
            PointViewPtr output = input->makeNew();
            for (const auto& i : inliers->indices)
            {
                output->appendPoint(*input, i);
            }

            viewSet.erase(input);
            viewSet.insert(output);
        }
    }
    else
    {
        if (outliers.empty())
            log()->get(LogLevel::Warning) << "Filtered cloud has no outliers!\n";

        if (!(m_classify || m_extract))
            log()->get(LogLevel::Warning) << "Must choose --classify or --extract\n";

        // return the input buffer unchanged
        viewSet.insert(input);
    }

    return viewSet;
}