# \donttest{
# Set the number of threads to use in lidR
set_lidr_threads(8)
LASfile = system.file("extdata", "TLS_Clip.laz", package="spanner")
las = readTLSLAS(LASfile, select = "xyzcr", "-filter_with_voxel 0.01")
# Don't forget to make sure the las object has a projection
sf::st_crs(las) <- 26912
# Pre-process the example lidar dataset by classifying the ground and noise points
# using lidR::csf(), normalizing it, and removing outlier points
# using lidR::ivf()
# las = classify_ground(las, csf(sloop_smooth = FALSE,
# class_threshold = 0.5,
# cloth_resolution = 0.5, rigidness = 1L,
# iterations = 500L, time_step = 0.65))
# las = normalize_height(las, tin())
# las = classify_noise(las, ivf(0.25, 3))
# las = filter_poi(las, Classification != LASNOISE)
# Plot the non-ground points, colored by height
# plot(filter_poi(las, Classification != 2), color = "Z")
# Perform a deep inspection of the las object. If you see any
# red text, you may have issues!
las_check(las)
# Find individual tree locations and attribute data
# find tree locations and attribute data
myTreeLocs = get_raster_eigen_treelocs(las = las, res = 0.025, pt_spacing = 0.0254,
dens_threshold = 0.25,
neigh_sizes = c(0.25, 0.15, 0.66),
eigen_threshold = 0.75,
grid_slice_min = 1,
grid_slice_max = 2,
minimum_polygon_area = 0.005,
cylinder_fit_type = "ransac",
max_dia = 1,
SDvert = 0.33,
n_pts = 20,
n_best = 25,
inliers = 0.9,
conf = 0.99,
max_angle = 20)
# Plot results if trees were found
if (!is.null(myTreeLocs) && nrow(myTreeLocs) > 0) {
plot(lidR::rasterize_canopy(las, res = 0.2, p2r()))
symbols(sf::st_coordinates(myTreeLocs)[,1], sf::st_coordinates(myTreeLocs)[,2],
circles = myTreeLocs$Radius^2*3.14, inches = FALSE, add = TRUE, bg = 'black')
} else {
message("No tree locations were found. Try adjusting the parameters.")
}
# Segment the point cloud
# For areas with interlocking crowns and trees of different sizes,
# enable metabolic scaling to prevent height overestimation
myTreeGraph = segment_graph(las = las, tree.locations = myTreeLocs, k = 50,
distance.threshold = 0.5,
use.metabolic.scale = FALSE,
ptcloud_slice_min = 1,
ptcloud_slice_max = 2,
subsample.graph = 0.1,
return.dense = TRUE)
# Plot it in 3D colored by treeID
plot(myTreeGraph, color = "treeID", pal=spanner_pal())
# Optional: Use a custom metabolic scaling function
# myTreeGraph = segment_graph(las = las, tree.locations = myTreeLocs, k = 50,
# distance.threshold = 0.5,
# use.metabolic.scale = TRUE,
# metabolic.scale.function = '1/((2*x)^(1/8))',
# ptcloud_slice_min = 1,
# ptcloud_slice_max = 2,
# subsample.graph = 0.1,
# return.dense = TRUE)
# }
Run the code above in your browser using DataLab