1

I have used the lidR package in R to run a point cloud segmentation of trees using the li2012 algorithm. I am interested in exporting my results to a csv file, but the methods I have tried did not include the treeID column.

As suggested in this post: (Exporting coordinates from LAS files to CSV?) I used las2txt and rLiDAR but neither option included the treeID column in the csv it generated.

  • How is it possible to export to csv and include the tree segmentation results?
  • Would it work best to create a spatial points data frame following lidR book Chapter 11 then use the SF or SP package to convert it to a csv? (https://jean-romain.github.io/lidRbook/tba.html)

Additionally as a second topic, I am interested in linking my results with a postgresql / postGIS database. Is a conversion to csv followed by a table creation in postgresql efficient? Any better way?

1
  • Do you want to output one row per tree (ie with unique treeIDs) or one row per lidar point, giving how each lidar point has been classified? If one row per tree, what do you want for the tree coordinate? tree_metrics uses the highest point. Use that, then write the spatial object to CSV.
    – Spacedman
    Commented Oct 7, 2021 at 17:33

2 Answers 2

2

Run the example code in the help:

LASfile <- system.file("extdata", "MixedConifer.laz", package="lidR")
 las <- readLAS(LASfile, select = "xyz", filter = "-drop_z_below 0")
 
 # Using Li et al. (2012)
 las <- segment_trees(las, li2012(R = 3, speed_up = 5))

Converting that to an sf object gives one point per LAS input point (37,000 of them), with tree ID of 269 trees:

library(sf)
lsp = st_as_sf(as.spatial(las))
plot(lsp[,"treeID"])
range(lsp$treeID,na.rm=TRUE)
# [1]   1 269

enter image description here

(Note that I can't find a direct las-to-sf function, so I'm using lidR::as.spatial to make an sp object, then st_as_sf to convert to sf.)

To save that as CSV, convert to a data frame with the coordinates:

> lspdf = cbind(st_drop_geometry(lsp), st_coordinates(lsp))
> head(lspdf)
     Z treeID        X       Y
1 0.07     80 481349.5 3813011
2 0.11     80 481348.7 3813011
3 0.04     80 481348.7 3813010

and that can be saved using write.csv or write.table or whatever.

If you want one record per tree, use tree_metrics to summarize over trees, convert to sf:

metrics <- tree_metrics(las, ~list(z_max = max(Z))) # calculate tree metrics
metrics.sf = st_as_sf(metrics)
head(metrics.sf)
# Simple feature collection with 6 features and 2 fields
# Geometry type: POINT
# Dimension:     XY
# Bounding box:  xmin: 481325.2 ymin: 3813006 xmax: 481349.8 ymax: 3813011
# Projected CRS: NAD83 / UTM zone 12N
#   treeID z_max                 geometry
# 1     80 23.00 POINT (481349.9 3813011)
# 2     83 22.96 POINT (481336.1 3813011)
# 3     67 23.46 POINT (481334.6 3813006)

that is 269 rows, one per tree. Convert to data frame as before and save as before.

3
  • 2
    Converting to sf is not in lidR because of the memory size of an sf POINT object compared to LAS/SpatialPointDataFrame is ~7 times more. It is better/faster/memory optimized to use data.table::fwrite(las@data, "file.csv")
    – JRR
    Commented Oct 7, 2021 at 18:23
  • 1
    Wow that's bonkers. Done some tests and sf objects can be 20x the size of data frames. Is there a method to get the @data element because direct access like that is usually not a good idea...
    – Spacedman
    Commented Oct 7, 2021 at 21:20
  • 1
    The sf design is awesome for its capacity at storing so many different stuff in a single consistent form compatible with other modern R idioms. But this comes with a cost and is inefficient at storing large data. This is why the LAS class is not a sf, sfc_POINT. And no, no function for las@data but I do agree with you and I plan to add something.
    – JRR
    Commented Oct 8, 2021 at 0:01
0

The input is a classified las with segmented trees assigned unique tree id in a field "treeID" that doesn't export if using the average las to csv applications or functions.

Here's how I did it, regardless of efficiency or lack thereof.

## write las w/ all fields to csv ##
segtree <- readLAS(". /input/path/lasfile.las")
segtreespatpnts <- as.spatial(segtree)
segtreelist <- list(segtreespatpts)
write.csv(segtreelist, "./output/path/lasascsv.csv", row.names = TRUE)

## check file output ##
csvinsegtree <- read.csv("./output/path/lasascsv.csv")
head(csvinsegtree,   = 20L)

I also used future::plan(multisession) but it made no difference. I suppose that's next on the list.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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