Skip to content

Commit

Permalink
Merge pull request #716 from PDAL/issue/689-ground-filter
Browse files Browse the repository at this point in the history
Add `filters.ground` and `kernels.ground`
  • Loading branch information
hobu committed Jan 21, 2015
2 parents 440fbd0 + d772274 commit f3a6db1
Show file tree
Hide file tree
Showing 5 changed files with 304 additions and 65 deletions.
16 changes: 12 additions & 4 deletions plugins/pcl/CMakeLists.txt
Expand Up @@ -29,6 +29,7 @@ set_package_properties(PCL PROPERTIES DESCRIPTION "Point Cloud Library"

include_directories(${PCL_INCLUDE_DIRS})
include_directories(${CMAKE_CURRENT_LIST_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/filters)
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
if (NOT WIN32)
Expand Down Expand Up @@ -122,6 +123,13 @@ PDAL_ADD_PLUGIN(pclblock_libname filter pclblock
FILES "${srcs}" "${incs}"
LINK_WITH ${PCL_LIBRARIES})

#
# Ground Filter
#
PDAL_ADD_PLUGIN(ground_filter_libname filter ground
FILES filters/GroundFilter.hpp filters/GroundFilter.cpp
LINK_WITH ${PCL_LIBRARIES})

#
# PCL Kernel
#
Expand All @@ -138,9 +146,9 @@ PDAL_ADD_PLUGIN(pcl_libname kernel pcl
set(srcs kernel/GroundKernel.cpp)
set(incs kernel/GroundKernel.hpp)

PDAL_ADD_PLUGIN(ground_libname kernel ground
PDAL_ADD_PLUGIN(ground_kernel_libname kernel ground
FILES "${srcs}" "${incs}"
LINK_WITH ${PCL_LIBRARIES} ${pclblock_libname})
LINK_WITH ${ground_filter_libname})

#
# Smooth Kernel
Expand All @@ -156,7 +164,7 @@ if (WITH_TESTS)
PDAL_ADD_TEST(pcltest
FILES test/PCLBlockFilterTest.cpp
LINK_WITH ${pclvisualizer_libname} ${pcd_reader_libname}
${pcd_writer_libname} ${pclblock_libname}
${pcl_libname} ${ground_libname} ${smooth_libname}
${pcd_writer_libname} ${pclblock_libname} ${ground_filter_libname}
${pcl_libname} ${ground_kernel_libname} ${smooth_libname}
)
endif()
167 changes: 167 additions & 0 deletions plugins/pcl/filters/GroundFilter.cpp
@@ -0,0 +1,167 @@
/******************************************************************************
* Copyright (c) 2015, Bradley J Chambers (brad.chambers@gmail.com)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following
* conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
****************************************************************************/

#include "GroundFilter.hpp"

#include "PCLConversions.hpp"

#include <pdal/Options.hpp>
#include <pdal/pdal_macros.hpp>
#include <pdal/PointBuffer.hpp>
#include <pdal/PointContext.hpp>
#include <pdal/StageFactory.hpp>

#include <pcl/point_types.h>
#include <pcl/console/print.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/io/pcd_io.h>
#include <pcl/segmentation/progressive_morphological_filter.h>

CREATE_FILTER_PLUGIN(ground, pdal::GroundFilter)

namespace pdal
{

void GroundFilter::processOptions(const Options& options)
{
m_maxWindowSize = options.getValueOrDefault<double>("maxWindowSize", 33);
m_slope = options.getValueOrDefault<double>("slope", 1);
m_maxDistance = options.getValueOrDefault<double>("maxDistance", 2.5);
m_initialDistance = options.getValueOrDefault<double>("initialDistance", 0.15);
m_cellSize = options.getValueOrDefault<double>("cellSize", 1);
m_classify = options.getValueOrDefault<bool>("classify", true);
m_extract = options.getValueOrDefault<bool>("extract", false);
}

void GroundFilter::addDimensions(PointContextRef ctx)
{ ctx.registerDim(Dimension::Id::Classification); }

PointBufferSet GroundFilter::run(PointBufferPtr input)
{
bool logOutput = log()->getLevel() > LogLevel::Debug1;
if (logOutput)
log()->floatPrecision(8);
log()->get(LogLevel::Debug2) << "Process GroundFilter...\n";

// convert PointBuffer to PointXYZ
typedef pcl::PointCloud<pcl::PointXYZ> Cloud;
Cloud::Ptr cloud(new Cloud);
BOX3D const& bounds = input->calculateBounds();
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 PMF filter
pcl::ProgressiveMorphologicalFilter<pcl::PointXYZ> pmf;
pmf.setInputCloud(cloud);
pmf.setMaxWindowSize(m_maxWindowSize);
pmf.setSlope(m_slope);
pmf.setMaxDistance(m_maxDistance);
pmf.setInitialDistance(m_initialDistance);
pmf.setCellSize(m_cellSize);

// run the PMF filter, grabbing indices of ground returns
pcl::PointIndicesPtr idx(new pcl::PointIndices);
pmf.extract(idx->indices);

if (!idx->indices.empty() && (m_classify || m_extract))
{
PointBufferSet pbSet;

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

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

pbSet.insert(input);
}

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

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

pbSet.erase(input);
pbSet.insert(output);
}

return pbSet;
}
else
{
if (idx->indices.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
PointBufferSet pbSet;
pbSet.insert(input);
return pbSet;
}
}

} // namespace pdal

81 changes: 81 additions & 0 deletions plugins/pcl/filters/GroundFilter.hpp
@@ -0,0 +1,81 @@
/******************************************************************************
* Copyright (c) 2015, Bradley J Chambers (brad.chambers@gmail.com)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following
* conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
****************************************************************************/

#pragma once

#include <pdal/Filter.hpp>
#include <pdal/Stage.hpp>

#include <memory>

namespace pdal
{

class Options;
class PointBuffer;
class PointContext;

typedef std::shared_ptr<PointBuffer> PointBufferPtr;
typedef PointContext PointContextRef;

class PDAL_DLL GroundFilter : public Filter
{
public:
SET_STAGE_NAME("filters.ground", "Progressive Morphological Filter")
SET_STAGE_LINK("http://www.pdal.io/stages/filters.ground.html")
SET_PLUGIN_VERSION("1.0.0b1")

GroundFilter() : Filter()
{}

private:
double m_maxWindowSize;
double m_slope;
double m_maxDistance;
double m_initialDistance;
double m_cellSize;
bool m_classify;
bool m_extract;

virtual void addDimensions(PointContextRef ctx);
virtual void processOptions(const Options& options);
virtual void ready(PointContext ctx) {};
virtual PointBufferSet run(PointBufferPtr buf);

GroundFilter& operator=(const GroundFilter&); // not implemented
GroundFilter(const GroundFilter&); // not implemented
};

} // namespace pdal

0 comments on commit f3a6db1

Please sign in to comment.