# Way to filter outliers from point cloud in lidr?

I have an ALS point cloud. I have been able to successfully normalize the height, but am wondering if there's any way to remove/filter some points that are obviously errors/outliers (points below 0 and a handful that are 30-50m or even 100m above the tallest trees). The data I'm using was downloaded from the USGS National Map with only ground points already classified.

If I normalize with the `tin()` algorithm and create my chm straight from the normalize point cloud, my chm min/max values are:

``````values     : -5.23, 129.98  (min, max)
``````

and if I normalize with a dtm:

``````values     : -14.65, 129.91  (min, max)
``````

Ultimately, I'm trying to segment trees and generate products of tree heights, canopy cover, tree density, etc. But I can't run my analysis when I know the max tree height will be < 30m across my study site.

If I try to reclassify the ground, will that help with the points below 0? But that won't address the 129m max...

I was thinking maybe I'd be better off smoothing my chm and using the chm/tree tops to segment trees as I was having trouble finding a good way to utilize the `li2012()` algorithm.

## 2 Answers

There is no 'advanced' outlier filtering in `lidR` yet. But for simple cases you can built a simple method yourself. Here are some hints and you can modify the examples to fit your need.

## Filter point of interest using thresholds

``````las <- filter_poi(las, Z >= 0, Z <= 30)
``````

## Filter high outliers using 95th percentile CHM

This is an example taken from this vignette. It builds a raster of 95th percentile and removes what is too high relatively to this height map.

``````filter_noise = function(las, sensitivity)
{
p95 <- grid_metrics(las, ~quantile(Z, probs = 0.95), 10)
las <- merge_spatial(las, p95, "p95")
las <- filter_poi(las, Z < p95*sensitivity)
las\$p95 <- NULL
return(las)
}

las <- filter_noise(las, sensitivity = 1.2)
``````

## Filter outliers using point based metrics

There is no example given but at the end of this chapter there is a section that explains how to build a pretty advanced outlier filter method with `point_metrics()`

## classify_noise() in v3.1.0

I put this information here for future readers. Starting from `v3.1.0` `lidR` will have (or 'already has' depending on when you are reading) a function `classify_noise()` with several possible algorithms.

As JRR mentioned, `lidr` now allows one to classify noise using `classify_noise`. Two algorithms are implemented: `sor` and `ivf`

However, a quick and dirty way is normalize the point cloud, then filter by removing points below zero and points above a reasonable estimate of the tallest trees in the study area, or use some quantile based metric.

for example:

``````norm<- normalize_height(las, knnidw())
#keep everything above zero and below the 99.99th quantile
filtered <- filter_poi(norm, Z >= 0 & Z < quantile(Z, .9999))
#use Z values (60 m) instead of quantiles
filtered <- filter_poi(norm, Z >= 0 & Z < 60)
``````

You could then `unnormalize_height()` the file if you wanted to.