diff --git a/README.md b/README.md index 49eab30..42bb14b 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ git clone https://github.com/apburt/treeseg.git; mkdir ./treeseg/build; cd ./treeseg/build; cmake ..; make; ``` -Optionally, for users with RIEGL V-Line scan data, treeseg includes the executable `rxp2pcd`, to convert and preprocess data in RXP data stream format, to binary PCD format. This executable will be automatically built if the directories `./treeseg/include/reigl/` and `./treeseg/lib/riegl/` are populated with the RIEGL RiVLIB headers and libraries (as appropriate for the user's particular CPU architecture and gcc version), which can be downloaded from the Members Area of the RIEGL website (e.g., rivlib-2_5_10-x86_64-linux-gcc9.zip). +Optionally, for users with RIEGL V-Line scan data, treeseg includes the executable `rxp2pcd`, to convert and preprocess data in RXP data stream format, to binary PCD format. This executable will automatically be built if the directories `./treeseg/include/reigl/` and `./treeseg/lib/riegl/` are populated with the RIEGL RiVLIB headers and libraries (as appropriate for the user's particular CPU architecture and gcc version), which can be downloaded from the Members Area of the RIEGL website (e.g., rivlib-2_5_10-x86_64-linux-gcc9.zip). Finally, the environment variable `PATH` can then be updated to include the directory containing the built treeseg executables, either temporarily, by calling the following, or permanently, by inserting it at the top of `~/.bashrc`: diff --git a/doc/tutorial_downsample.md b/doc/tutorial_downsample.md index c7c2236..c51f8ff 100644 --- a/doc/tutorial_downsample.md +++ b/doc/tutorial_downsample.md @@ -20,7 +20,7 @@ Note: if the preprocessor macro [XYZRRDRS](../include/treeseg_pointtype.h#L29) i ## Downsampling resolution -A potential place to start when determining the downsampling resolution, is to consider the characteristics of the lidar instrument (i.e., beam divergence, diameter of the beam at emission, and ranging accuracy), and to compare them with the observed distances between individual points in the point clouds collected by that instrument. For the data considered in this tutorial, this exercise was undertaken in figure 2 of our [paper](https://doi.org/10.1111/2041-210X.13121), where it can be seen that a voxel edge length of 0.04 m provided some balance between removing redundant points close to the ground (e.g., points on the stems where the beam overlapped), whilst conserving important data from the canopy. +A potential place to start when determining the downsampling resolution, is to consider the characteristics of the lidar instrument (i.e., beam divergence, diameter of the beam at emission, and ranging accuracy), and to compare them with the observed distances between individual points in the point clouds collected by that instrument. For the data considered in this tutorial, this exercise was undertaken in figure 2 of our [paper](https://doi.org/10.1111/2041-210X.13121), where it can be seen that a voxel edge length of 0.04 m provided some balance between removing redundant points close to the ground (e.g., returns from the stems whose beam overlapped), whilst conserving important data from the canopy. treeseg includes the executable `nearestneighbour`, which may help in making this decision, by outputting the mean vertically-resolved nearest neighbour distances through a point cloud (i.e., the cloud is partitioned into height bins, and the mean distance of each point to its N nearest neighbours is calculated and averaged for each bin): diff --git a/doc/tutorial_findstems.md b/doc/tutorial_findstems.md index 1ffc820..382bb61 100644 --- a/doc/tutorial_findstems.md +++ b/doc/tutorial_findstems.md @@ -4,7 +4,7 @@ Individual tree stems are then identified in this slice across the larger-area p 1. Euclidean clustering: the slice is organised into individual clusters, based on the spatial distances between points. 2. Region-based segmentation: these clusters are further reduced to regions, based on the properties of their underlying surfaces (themselves inferred from point normals). -3. Shape fitting: RANSAC methods are used to fit cylinders to each region, and fit diagnostics are used determine the likelihood of the underlying surface being a stem. +3. Shape fitting: RANSAC methods are used to fit cylinders to each region, and fit diagnostics are used to determine the likelihood of the underlying surface being a stem. 4. Principal component analysis: the angle between the principal components of each region and the ground are calculated, with regions broadly perpendicular to the ground deemed to be stems. These steps are implemented in the `findstems` executable, which can be called: diff --git a/doc/tutorial_getcrownvolume.md b/doc/tutorial_getcrownvolume.md index 6b0fc64..31d5b97 100644 --- a/doc/tutorial_getcrownvolume.md +++ b/doc/tutorial_getcrownvolume.md @@ -1,6 +1,6 @@ # Crown segmentation - Part 1 -At this point, the stems of the 10 largest trees inside the 1 ha tropical forest stand have been successfully segmented. It is now necessary to extract their crowns from the neighbouring vegetation. The first part of this two step process is to generate a point cloud for each tree, containing: i) the stem, ii) the crown, and iii) neighbouring crown vegetation. This is undertaken using the following methods: +At this point, the stems of the 10 largest trees inside the 1 ha stand have been successfully segmented. It is now necessary to extract their crowns from the neighbouring vegetation. The first part of this two step process is to generate a point cloud for each tree, containing: i) the stem, ii) the crown, and iii) neighbouring crown vegetation. This is undertaken using the following methods: 1. Shape fitting: RANSAC methods are used to fit a cylinder to each of the stem point clouds, to estimate the stem diameter of each tree. 2. Spatial filtering: pass-through filters (closed cylinder) are applied to the larger-area point cloud, as driven by stem-diameter:tree-height and stem-diameter:crown-diameter allometries, to generate point clouds containing the crown of each tree. @@ -25,6 +25,6 @@ Which will look something similar to: ## Allometrics -The purpose of the [stem-diameter:tree-height](../src/getcrownvolume.cpp#L7) and [stem-diameter:crown-diameter](../src/getcrownvolume.cpp#L15) allometries, is to segment an appropriately sized section of the larger-area point cloud containing the entirety of the crown of the tree of interest. These allometries were constructed using terrestrial lidar data collected across the tropics via a non-linear power-law model. The parameters used in these models are the upper 95% confidence intervals, and also include a further relaxation term. When applied to other lidar datasets, it may be necessary to relax these allometries further, to avoid accidental clipping out of crowns. +The purpose of the [stem-diameter:tree-height](../src/getcrownvolume.cpp#L7) and [stem-diameter:crown-diameter](../src/getcrownvolume.cpp#L15) allometries, is to segment an appropriately sized section of the larger-area point cloud containing the entirety of the crown of the tree of interest. These allometries were constructed using terrestrial lidar data collected across the tropics via a non-linear power-law model. The parameters used in these models are the upper 95% confidence intervals, and also include a further relaxation term. When applied to other lidar datasets, it may be necessary to relax these allometries further, to avoid accidental cropping of crowns. ## [Next: Crown segmentation - Part 2](tutorial_segmentcrown.md) diff --git a/doc/tutorial_getdtmslice.md b/doc/tutorial_getdtmslice.md index 0bade34..c9a9ebb 100644 --- a/doc/tutorial_getdtmslice.md +++ b/doc/tutorial_getdtmslice.md @@ -6,7 +6,7 @@ The first principal step of treeseg is to identify the individual trees in the l getdtmslice 2 2.5 3 6 NOU11.tile.downsample.*.pcd > NOU11.dtm.dat ``` -Where the inputs are: 1) the resolution of the DTM (m), 2) the percentile of the z-coordinates inside each DTM grid which is considered to constitute the ground (this is used, rather than the absolute minimum, to provide more robust results in noisy point clouds), 3) the minimum height of the slice above-ground (m), 4) the maximum height of the slice above-ground (m), and 5) the downsampled tiles constituting the larger-area point cloud. +Where the inputs are: 1) the resolution of the DTM (m), 2) the percentile of the z-coordinates of the points inside each DTM grid which is considered to constitute the ground (this is used, rather than the absolute minimum, to provide more robust results in noisy point clouds), 3) the minimum height of the slice above-ground (m), 4) the maximum height of the slice above-ground (m), and 5) the downsampled tiles constituting the larger-area point cloud. The resulting slice can be viewed using: diff --git a/doc/tutorial_segmentcrown.md b/doc/tutorial_segmentcrown.md index 5173aee..dc157cd 100644 --- a/doc/tutorial_segmentcrown.md +++ b/doc/tutorial_segmentcrown.md @@ -32,11 +32,11 @@ The connectivity testing is implemented in the [buildtree](../src/treeseg.cpp#L9 buildTree(regions,20,1,0.2,5,1.0,tree); ``` -Where the input parameters are: i) the vector of point clouds derived from the region-based segmentation, ii) cyclecount (integer), iii) firstcount (integer), iv) firstdist (m), v) nnearest (integer), vi) seconddist (m), and vii) the resulting tree-level point cloud. That is, first, the region representing the stem is designated the seed. For `firstcount` iteration(s), regions within the distance `firstdist` to the seed(s) are added to the tree and designated the new seeds. For the remaining `cyclecount` iterations, the `nnearest` regions closest to each seed and within the distance `seconddist` are added to the tree and designated the new seeds. These parameters may require further experimentation when applied to other lidar datasets. For example, for very high-quality lidar data, it might be possible to significantly reduce `cyclecount`. This will substantially reduce compute time. +Where the input parameters are: i) the vector of point clouds derived from the region-based segmentation, ii) cyclecount (integer), iii) firstcount (integer), iv) firstdist (m), v) nnearest (integer), vi) seconddist (m), and vii) the resulting tree-level point cloud. That is, first, the region representing the stem is designated the seed. For `firstcount` iteration(s), regions within the distance `firstdist` to the seed(s) are added to the tree and designated the new seeds. For the remaining `cyclecount` iterations, the `nnearest` regions closest to each seed and within the distance `seconddist` are added to the tree and designated the new seeds. These parameters may require further experimentation when applied to other lidar datasets. For example, for very high-quality lidar data, or for more sparsely populated forest scenes, it might be possible to significantly reduce `cyclecount`. This will substantially reduce compute time. In addition to this function, other important parameters have been hard-coded into `segmentcrown`: -1. Region-based segmentation: [nnearest](../src/segmentcrown.cpp#L31), [nneighbours](../src/segmentcrown.cpp#L32), [nmin](../src/segmentcrown.cpp#L32), [nmax](../src/segmentcrown.cpp#L32) and [curvature](../src/segmentcrown.cpp#L32). +1. Region-based segmentation: [nnearest](../src/segmentcrown.cpp#L24), [nneighbours](../src/segmentcrown.cpp#L25), [nmin](../src/segmentcrown.cpp#L25), [nmax](../src/segmentcrown.cpp#L25) and [curvature](../src/segmentcrown.cpp#L25). # Errors of commission