Examples
Height-normalization
Almost all functions in the module expect a height-normalized point cloud to work as intended. If your point cloud is not height-normalized, you can do it in a simple way using some of the module functions:
import laspy
import numpy as np
import dendromatics as dm
# Reading the point cloud
filename_las = 'example_data.las' # your .las file
entr = laspy.read(filename_las)
coords = np.vstack((entr.x, entr.y, entr.z)).transpose()
# Normalizing the point cloud
dtm = dm.generate_dtm(clean_points)
z0_values = dm.normalize_heights(coords, dtm)
# adding the normalized heights to the point cloud
coords = np.append(coords, np.expand_dims(z0_values, axis = 1), 1)
If the point cloud is noisy, you might want to denoise it first before generating the DTM:
clean_points = dm.clean_ground(coords)
Identifying stems from a stripe
Simply provide a stripe (from a height-normalized point cloud) as follows to iteratively ‘peel off’ the stems:
# Defining the stripe
lower_limit = 0.5
upper_limit = 2.5
stripe = coords[(coords[:, 3] > lower_limit) & (coords[:, 3] < upper_limit), 0:4]
stripe_stems = dm.verticality_clustering(stripe, n_iter = 2)
Individualizing trees
Once the stems have been identified in the stripe, they can be used to individualize the trees in the point cloud:
assigned_cloud, tree_vector, tree_heights = dm.individualize_trees(coords, stripe_stems)
Computing sections along the stems
compute_sections() can be used to compute sections along the stems of the individualized trees:
# Preprocessing: reducing the point cloud size by keeping only the points that are closer than some radius (expected_R) to the tree axes
# and those that are whithin the lowest section (min_h) and the uppest section (max_h) to be computed.
expected_R = 0.5
min_h = 0.5
max_h = 25
section_width = 0.02
xyz0_coords = assigned_cloud[(assigned_cloud[:, 5] < expected_R) & (assigned_cloud[:, 3] > min_h) & (assigned_cloud[:,3] < max_h + section_width), :]
stems = dm.verticality_clustering(xyz0_coords, n_iter = 2)[:, 0:6]
# Computing the sections
section_len = 0.2
sections = np.arange(min_h, max_h, section_len) # Range of uniformly spaced values within the specified interval
X_c, Y_c, R, check_circle, second_time, sector_perct, n_points_in = dm.compute_sections(stems, sections)
Tilt detection
tilt_detection() computes an ‘outlier probability’ for each section based on its tilting relative to neighbour sections and the relative to the tree axis:
outlier_prob = dm.tilt_detection(X_c, Y_c, R, sections)
For further examples and more thorough explanations, please check example.py script in /examples folder in the official GitHub repository: