Skip to content

Commit

Permalink
Resolve some dangling references to deprecated extract and classify o…
Browse files Browse the repository at this point in the history
…ptions

extract and classify have been used in several filters, namely outlier and PMF.
With the release of PDAL v1.5, we removed these options, opting to always
classify points, and to force users to ignore or extract them as they see fit
in their pipelines.

The outlier filter's extract option can be replicated by adding a range filter
stage as shown following the outlier filter:

    {
      "type":"filters.range",
      "limits":"Classification![7:7]"
    }

The PMF filter's extract option can be replicated by adding the following range
filter:

    {
      "type":"filters.range",
      "limits":"Classification[2:2]"
    }

The intention here was to remove any ambiguity as to how individual filters
implement "extract", and to instead be explicit in the pipeline specification
as to how points are extracted.
  • Loading branch information
chambbj committed Apr 17, 2017
1 parent 22bae5e commit 8f9c895
Show file tree
Hide file tree
Showing 9 changed files with 90 additions and 63 deletions.
12 changes: 6 additions & 6 deletions doc/apps/translate.rst
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,16 @@ Example 2:
--------------------------------------------------------------------------------

Given these tools, we can now construct a custom pipeline on-the-fly. The
example below uses a simple LAS reader and writer, but stages a PCL-based
voxel grid filter, followed by the PMF filter. We can even set
example below uses a simple LAS reader and writer, but stages a PCL-based voxel
grid filter, followed by the PMF filter and a range filter. We can even set
stage-specific parameters as shown.

::

$ pdal translate input.las output.las pclblock pmf \
--filters.pclblock.json="{\"pipeline\":{\"filters\":[{\"name\":\"VoxelGrid\"}]}}" \
--filters.pmf.approximate=true --filters.pmf.extract=true
$ pdal translate input.las output.las pclblock pmf range \
--filters.pclblock.methods="[{\"name\":\"VoxelGrid\"}]" \
--filters.pmf.approximate=true \
--filters.range.limits="Classification[2:2]"

Example 3:
--------------------------------------------------------------------------------
Expand All @@ -113,4 +114,3 @@ reference system and writes the result to the file "output.las".

$ pdal translate input.las output.las -f filters.reprojection \
--filters.reprojection.out_srs="EPSG:4326"

14 changes: 8 additions & 6 deletions doc/pipeline.rst
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,9 @@ DTM

A common task is to create a digital terrain model (DTM) from the input point
cloud. This pipeline infers the reader type, applies an approximate ground
segmentation filter using :ref:`filters.pmf`, and then creates the DTM using
the :ref:`writers.gdal` with only the ground returns.
segmentation filter using :ref:`filters.pmf`, filters out all points but the
ground returns (classification value of 2) using the :ref:`filters.range`, and
then creates the DTM using the :ref:`writers.gdal`.

.. code-block:: json
Expand All @@ -267,9 +268,11 @@ the :ref:`writers.gdal` with only the ground returns.
"slope":1.0,
"max_distance":2.5,
"initial_distance":0.15,
"cell_size":1.0,
"extract":true,
"classify":false
"cell_size":1.0
},
{
"type":"range",
"limits":"Classification[2:2]"
},
{
"type":"writers.gdal",
Expand Down Expand Up @@ -460,4 +463,3 @@ PDAL. Readers follow the pattern of :ref:`readers.las` or

Issuing the command ``pdal info --options`` will list all available
stages and their options. See :ref:`info_command` for more.

29 changes: 15 additions & 14 deletions doc/stages/filters.outlier.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ filters.outlier
The Outlier filter provides two outlier filtering methods: radius and
statistical. These two approaches are discussed in further detail below.

It is worth noting that both filtering methods simply apply a classification
value of 7 to the noise points (per the LAS specification). To remove the noise
points altogether, users can add a :ref:`range filter<filters.range>` to their
pipeline, downstream from the outlier filter.

.. code-block:: json
{
"type":"filters.range",
"limits":"Classification![7:7]"
}
Statistical Method
-------------------------------------------------------------------------------

Expand Down Expand Up @@ -39,10 +51,6 @@ We now interate over the pre-computed mean distances :math:`\mu_i` and compare t
\text{false,} \phantom{true,} \text{otherwise} \\
\end{cases}
The ``classify`` and ``extract`` options are used to control whether outlier
points are labeled as noise, or removed from the output ``PointView``
completely.

.. figure:: filters.statisticaloutlier.img1.png
:scale: 70 %
:alt: Points before outlier removal
Expand Down Expand Up @@ -96,10 +104,6 @@ of neighbors specified by ``min_k``, it is marked as an outlier.
\text{false,} \phantom{true,} \text{otherwise} \\
\end{cases}
The ``classify`` and ``extract`` options are used to control whether outlier
points are labeled as noise, or removed from the output ``PointView``
completely.

Example
...............................................................................

Expand All @@ -124,6 +128,9 @@ four neighbors within a radius of 1.0.
Options
-------------------------------------------------------------------------------

class
The classification value to apply to outliers. [Default: **7**]

method
The outlier removal method. [Default: **statistical**]

Expand All @@ -138,9 +145,3 @@ mean_k

multiplier
Standard deviation threshold (statistical method only). [Default: **2.0**]

classify
Apply classification value of 18 (LAS high noise)? [Default: **true**]

extract
Extract inlier returns only? [Default: **false**]
50 changes: 31 additions & 19 deletions doc/stages/filters.pmf.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,25 +37,36 @@ Notes
``initial_distance`` large enough to not exclude these points from the ground.

* For a given iteration, the height threshold is determined by multiplying
``slope`` by ``cell_size`` by the difference in window size between the current
and last iteration, plus the ``initial_distance``. This height threshold is
constant across all cells and is maxed out at the ``max_distance`` value. If
the difference in elevation between a point and its “opened” value (from the
morphological operator) exceeds the height threshold, it is treated as
non-ground. So, bigger slope leads to bigger height thresholds, and these
grow with each iteration (not to exceed the max). With flat terrain,
keep this low, the thresholds are small, and stuff is more aggressively
dumped into non-ground class. In rugged terrain, open things up
``slope`` by ``cell_size`` by the difference in window size between the
current and last iteration, plus the ``initial_distance``. This height
threshold is constant across all cells and is maxed out at the
``max_distance`` value. If the difference in elevation between a point and its
“opened” value (from the morphological operator) exceeds the height threshold,
it is treated as non-ground. So, bigger slope leads to bigger height
thresholds, and these grow with each iteration (not to exceed the max). With
flat terrain, keep this low, the thresholds are small, and stuff is more
aggressively dumped into non-ground class. In rugged terrain, open things up
a little, but then you can start missing buildings, veg, etc.

* Very large ``max_window_size`` values will result in a lot of potentially
extra iteration. This parameter can have a strongly negative impact on
computation performance.

* This filter will mark all returns deemed to be ground returns with a
classification value of 2 (per the LAS specification). To extract only these
returns, users can add a :ref:`range filter<filters.range>` to the pipeline.

.. code-block:: json
{
"type":"filters.range",
"limits":"Classification[2:2]"
}
.. note::
[Zhang2003]_ describes the consequences and relationships of the
parameters in more detail and is the canonnical resource on the
topic.

[Zhang2003]_ describes the consequences and relationships of the parameters
in more detail and is the canonnical resource on the topic.

Options
-------------------------------------------------------------------------------
Expand All @@ -75,11 +86,12 @@ initial_distance
cell_size
Cell Size. [Default: **1**]

classify
Apply classification labels? [Default: **true**]

extract
Extract ground returns? [Default: **false**]

approximate
Use approximate algorithm? [Default:: **false**]
Use approximate algorithm? [Default: **false**]

ignore
Optional range of values to ignore.

last
Consider only last returns (when return information is available)? [Default:
**true**]
3 changes: 1 addition & 2 deletions doc/workshop/exercises/analysis/denoising/denoise.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@
{
"type": "filters.outlier",
"method": "statistical",
"extract": "true",
"multiplier": 3,
"mean_k": 8
},
{
"type": "filters.range",
"limits": "Z[-100:3000]"
"limits": "Classification![7:7],Z[-100:3000]"
},
{
"type": "writers.las",
Expand Down
21 changes: 15 additions & 6 deletions doc/workshop/exercises/analysis/denoising/denoising.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ This exercise uses PDAL to remove unwanted noise in an ALS collection.
Exercise
--------------------------------------------------------------------------------

PDAL provides a :ref:`filter <filters>` through |PCL| to apply a statistical
PDAL provides the :ref:`outlier filter<filters.outlier>` to apply a statistical
filter to data.

Because this operation is somewhat complex, we are going to use a pipeline to
Expand Down Expand Up @@ -58,14 +58,14 @@ point cloud file we're going to read.
2. :ref:`filters.outlier`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The :ref:`filters.outlier` PDAL filter does most of the work for this operation.
The PDAL :ref:`outlier filter<filters.outlier>` does most of the work for this
operation.

::

{
"type": "filters.outlier",
"method": "statistical",
"extract": "true",
"multiplier": 3,
"mean_k": 8
},
Expand All @@ -75,17 +75,26 @@ The :ref:`filters.outlier` PDAL filter does most of the work for this operation.
3. :ref:`filters.range`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

At this point, the outliers have been classified per the LAS specification as
low/noise points with a classification value of 7. The :ref:`range
filter<filters.range>` can remove these noise points by constructing a
:ref:`range <ranges>` with the value ``Classification![7:7]``, which passes
every point with a ``Classification`` value **not** equal to 7.

Even with the :ref:`filters.outlier` operation, there is still a cluster of
points with extremely negative ``Z`` values. These are some artifact or
miscomputation of processing, and we don't want these points. We are going to
use ::ref:`filters.range` to keep only points that are within the range
miscomputation of processing, and we don't want these points. We can construct
another :ref:`range <ranges>` to keep only points that are within the range
``-100 <= Z <= 3000``.

Both :ref:`ranges <ranges>` are passed as a comma-separated list to the
:ref:`range filter<filters.range>` via the ``limits`` option.

::

{
"type": "filters.range",
"limits": "Z[-100:3000]"
"limits": "Classification![7:7],Z[-100:3000]"
},

4. :ref:`writers.las`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ docker run -v /c/Users/Howard/PDAL:/data -t pdal/pdal \
pdal ground \
/data/exercises/analysis/ground/CSite1_orig-utm.laz \
-o /data/exercises/analysis/ground/ground-only.laz \
--classify=true --extract=true \
--extract=true \
--writers.las.compression=true --verbose 4
17 changes: 10 additions & 7 deletions doc/workshop/exercises/analysis/ground/ground.rst
Original file line number Diff line number Diff line change
Expand Up @@ -67,25 +67,28 @@ technique we learned about in :ref:`denoising`.

.. literalinclude:: ./ground-run-ground-only.txt
:linenos:
:emphasize-lines: 6
:emphasize-lines: 5

.. note::

The ``filters.pmf.extract=true`` item causes all data except
ground-classified points to be removed from the set.

Buildings and other non-ground points are removed with the ``extract`` option
of :ref:`filters.pmf`
The ``--extract=true`` option causes all data except ground-classified
points to be removed from the set.

.. image:: ../../../images/ground-ground-only-view.png


2. Now we will remove the noise, using the :ref:`translate_command` to stack the
2. Now we will instead use the :ref:`translate_command` command to stack the
:ref:`filters.outlier` and :ref:`filters.pmf` stages:

.. literalinclude:: ./translate-run-ground-only.txt
:linenos:

In this invocation, we have more control over the process. First the outlier
filter merely classifies outliers with a ``Classification`` value of 7. These
outliers are then ignored during PMF processing with the ``ignore`` option.
Finally, we add a range filter to extract only the ground returns (i.e.,
``Classification`` value of 2).

The result is a more accurate representation of the ground returns.

.. image:: ../../../images/ground-filtered.png
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ docker run -v /c/Users/Howard/PDAL:/data -t pdal/pdal \
pdal translate \
/data/exercises/analysis/ground/CSite1_orig-utm.laz \
-o /data/exercises/analysis/ground/denoised-ground-only.laz \
outlier pmf \
outlier pmf range \
--filters.outlier.method="statistical" \
--filters.outlier.mean_k=8 \
--filters.outlier.multiplier=3.0 \
--filters.pmf.cell_size=1.5 \
--filters.pmf.extract=true \
--filters.pmf.ignore="Classification[7:7]" \
--filters.range.limits="Classification[2:2]" \
--writers.las.compression=true --verbose 4

0 comments on commit 8f9c895

Please sign in to comment.