# filters.pmf#

The **Progressive Morphological Filter (PMF)** is a method of
segmenting ground and non-ground returns. This filter is an implementation
of the method described in
[Zhang *et al.*, 2003].

## Example#

```
[
"input.las",
{
"type":"filters.pmf"
},
"output.las"
]
```

## Notes#

[slope] controls the height threshold at each iteration. A slope of 1.0 represents a 1:1 or 45º.

[initial_distance] is _intended_ to be set to account for z noise, so for a flat surface if you have an uncertainty of around 15 cm, you set [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 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.

[exponential] is used to control the rate of growth of morphological window sizes toward [max_window_size]. Linear growth preserves gradually changing topographic features well, but demands considerable compute time. The default behavior is to grow the window sizes exponentially, thus reducing the number of iterations.

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 range filter to the pipeline.

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

Note

[Zhang *et al.*, 2003] describes the consequences and relationships of the parameters
in more detail and is the canonical resource on the topic.

## Options#

- cell_size
Cell Size. [Default: 1]

- exponential
Use exponential growth for window sizes? [Default: true]

- ignore
Range of values to ignore. [Optional]

- initial_distance
Initial distance. [Default: 0.15]

- returns
Comma-separated list of return types into which data should be segmented. Valid groups are “last”, “first”, “intermediate” and “only”. [Default: “last, only”]

- max_distance
Maximum distance. [Default: 2.5]

- max_window_size
Maximum window size. [Default: 33]

- slope
Slope. [Default: 1.0]

- where
An expression that limits points passed to a filter. Points that don’t pass the expression skip the stage but are available to subsequent stages in a pipeline. [Default: no filtering]

- where_merge
A strategy for merging points skipped by a

`where`

option when running in standard mode. If`true`

, the skipped points are added to the first point view returned by the skipped filter. If`false`

, skipped points are placed in their own point view. If`auto`

, skipped points are merged into the returned point view provided that only one point view is returned and it has the same point count as it did when the filter was run. [Default:`auto`

]