I understand that normalize_height() in lidR creates a Zref attribute so that it can be unnormalized. While I can print Z for the normalized file, I cannot print Zref. Subsequently, when I apply find_trees() Z values are carried over but of course Zref again returns NULL. My goal is to have tree tops with height and original elevation (so that it can be displayed in software that allows it to be seen in 3D along with imagery) and I was thinking this would be more efficient than extracting values from the raster DEM.

myLas <- readLAS('C:/ITD/normtest.las')
ttops <- find_trees(myLas, lmf(ws = 5))
ttops$Z     # this prints a series of values for tree heights
ttops$Zref  # this results in NULL

1 Answer 1


The use case you are describing is not natively covered. You can normalize a point cloud. In this case the output is a LAS object with an attribute Zref that can be unnormalized easily

LASfile <- system.file("extdata", "Topography.laz", package="lidR")
las <- readLAS(LASfile)
nlas <- normalize_height(las, tin())
#> [1] 806.5340 806.5635 806.0248 809.6303 809.3880 809.4847

However the output of find_trees is SpatialPointsDataFrame with two attributes: an ID and the Z elevations.

ttops <- find_trees(nlas, lmf(ws = 5))
#> class       : SpatialPointsDataFrame 
#> features    : 2047 
#> extent      : 273357.3, 273642.8, 5274357, 5274643  (xmin, xmax, ymin, ymax)
#> crs         : +proj=tmerc +lat_0=0 +lon_0=-70.5 +k=0.9999 +x_0=304800 +y_0=0 +ellps=GRS80 +units=m +no_defs 
#> variables   : 2
#> names       : treeID,        Z 
#> min values  :      1,  2.00275 
#> max values  :   2047, 20.97725

You could retrieve the original points by matching coordinates but I really think that the simplest way is to add the DTM elevation

dtm <- grid_terrain(las, 0.5, tin())
Zdtm <- dtm[ttops]
ttops$Z <- ttops$Z + Zdtm

plot(las) |> add_treetops3d(ttops)

or maybe even simpler/faster using a CHM

chm <- grid_canopy(las, 0.5, p2r())
ttops$Z <- chm[ttops]

plot(las) |> add_treetops3d(ttops)
  • thank you. In summary then, the normalized LAS object has Zref, but it is not carried on to the normalized LAS file that is written to the disk.
    – Ray J
    Nov 25, 2021 at 18:07
  • 1
    Zref is not carried to written las file by default. But you can use add_lasattribute = TRUE. However it is not carried to the tree location at all. This might be the object of a feature request.
    – JRR
    Nov 25, 2021 at 18:35
  • 1
    just a quick comment to follow on the code in the answer... I used ttops$Zref <- ttops$Z + Zdtm so that both tree height and elevation at the tree top are attributes. So far the process of extracting from the DEM is quick but I can put in a feature request as it is more streamlined for the user.
    – Ray J
    Nov 25, 2021 at 21:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.