LiDAR – Fix Point Cloud lidR Normalize Height Failure

lidarlidr

I'm working on an airborne lidar survey of around a thousand tiles (500m * 500m) using LAScatalog with lidR. I firstly ran a las_check()… No issues reported:

las_check(CTG_Bertrix)

#>  Checking headers consistency
#>   - Checking file version consistency... ✓
#>   - Checking scale consistency... ✓
#>   - Checking offset consistency... ✓
#>   - Checking point type consistency... ✓
#>   - Checking VLR consistency... ✓
#>   - Checking CRS consistency... ✓  
#>  Checking the headers
#>   - Checking scale factor validity... ✓
#>   - Checking Point Data Format ID validity... ✓  
#>  Checking preprocessing already done 
#>   - Checking negative outliers... ✓
#>   - Checking normalization... no  
#>  Checking the geometry
#>   - Checking overlapping tiles... ✓
#>   - Checking point indexation... yes

After this initial check, I still ran filter_duplicates() and after ran a normalize_height() process which actually failed:

#> An error occurred when processing the chunk 998. Try to load this chunk with:  chunk <-
#> readRDS("C:\Users\gef\AppData\Local\Temp\RtmpWK6Gyw/chunk998.rds") 
#> las <- readLAS(chunk) 3044 points were not normalizable. Process aborted.

I loaded the considered chunk and ran again las_check():

#>  Checking the data
#>   - Checking coordinates... ✓
#>   - Checking coordinates type... ✓
#>   - Checking coordinates range... ✓
#>   - Checking coordinates quantization... ✓
#>   - Checking attributes type... ✓
#>   - Checking ReturnNumber validity... ✓
#>   - Checking NumberOfReturns validity... ✓
#>   - Checking ReturnNumber vs. NumberOfReturns... ✓
#>   - Checking RGB validity... ✓
#>   - Checking absence of NAs... ✓
#>   - Checking duplicated points... ✓
#>   - Checking degenerated ground points... ✓
#>   - Checking attribute population...
#>     🛈 'EdgeOfFlightline' attribute is not populated
#>   - Checking gpstime incoherances
#>     ✗ 1263 pulses (points with the same gpstime) have points with identical ReturnNumber
#>   - Checking flag attributes... ✓
#>   - Checking user data attribute... ✓  
#>  Checking the header
#>   - Checking header completeness... ✓
#>   - Checking scale factor validity... ✓
#>   - Checking point data format ID validity... ✓
#>   - Checking extra bytes attributes validity... ✓
#>   - Checking the bounding box validity... ✓
#>   - Checking coordinate reference system... ✓  
#>  Checking header vs data adequacy
#>   - Checking attributes vs. point format... ✓
#>   - Checking header bbox vs. actual content... ✓
#>   - Checking header number of points vs. actual content... ✓
#>   - Checking header return number vs. actual content... ✓  
#>  Checking coordinate reference system...
#>   - Checking if the CRS was understood by R... ✓  
#>  Checking preprocessing already done 
#>   - Checking ground classification... yes
#>   - Checking normalization... no
#>   - Checking negative outliers... ✓
#>   - Checking flightline classification... yes

This las file can be downloaded HERE

As the error message is not really self-explanatory, I would like to know how to find the not normalizable points? How to fix/remove them ?

Best Answer

The question has already been asked here at least twice. One occurrence here.

library(lidR)
las = readLAS("bertrix.laz")
normalize_height(las, tin())
#> Interpolation of 3044 points outside the convex hull defined by ground points (outside the triangulation) failed and returned NAs.
#> Erreur : 3044 points were not normalizable. Process aborted. 

plot(las, color = "Classification")

enter image description here

As you can see, on the top right you have a building with no ground points at all. All the points are too far from a ground point to allow interpolation especially with TIN. You have three options.

  1. Discard those points normalize_height(las, tin(), na.rm = TRUE) but I don't think it is a good idea
  2. Use a much larger buffer to catch more ground point after the building. e.g. 80 meters opt_chunk_buffer(ctg) = 80
  3. Allow interpolation where TIN is not defined even if it's far (e.g. 100 meters) normalize_height(las, tin(extrapolate = knnidw(rmax = 100)))

In all cases interpolation in region with no ground point is relatively weak

Related Question