Skip to content

sylva.ground

sylva.ground

Ground classification, DTM generation, height normalisation and CHM.

classify_ground_csf

classify_ground_csf(cloud: PointCloud, cloth_resolution: float = 0.5, rigidness: int = 2, class_threshold: float = 0.3, iterations: int = 500, time_step: float = 0.65, return_mask: bool = False)

Classify ground with the Cloth Simulation Filter (Zhang et al. 2016).

The cloud is turned upside down and a cloth is dropped onto it; points within class_threshold of the settled cloth are ground. The default for TLS plots; robust to understorey and moderate slopes.

Parameters:

Name Type Description Default
cloud PointCloud

Points in a frame with z up (project or projected coordinates, not a tilted scanner frame). Thin to ~2-5 cm first for large plots.

required
cloth_resolution float

Cloth grid spacing (m). Smaller follows the terrain more closely but can drape over logs and low shrubs.

0.5
rigidness (1, 2, 3)

1 for steep terrain, 2 for moderate slopes, 3 for flat ground.

1
class_threshold float

Distance from the cloth (m) within which a point is ground.

0.3
iterations int

Maximum simulation steps.

500
time_step float

Simulation step; the default rarely needs changing.

0.65
return_mask bool

Return the boolean ground mask instead of the cloud.

False

Returns:

Type Description
PointCloud or ndarray

The cloud with classification set to 2 (ground) or 1 (other), overwriting any existing classification; or the mask (True = ground).

See Also

classify_ground_pmf : faster alternative. make_dtm : the next step.

classify_ground_pmf

classify_ground_pmf(cloud: PointCloud, cell_size: float = 0.5, max_window: float = 10.0, slope: float = 0.3, initial_distance: float = 0.15, max_distance: float = 2.0, return_mask: bool = False)

Classify ground with the Progressive Morphological Filter (Zhang et al. 2003).

Opens a minimum-height grid with growing windows; points close to the opened surface are ground. Faster than CSF but less robust under dense understorey.

Parameters:

Name Type Description Default
cloud PointCloud

Points in a frame with z up.

required
cell_size float

Grid cell size (m).

0.5
max_window float

Largest window (m); should exceed the largest non-ground object (e.g. crown or building) footprint.

10.0
slope float

Terrain slope (rise over run) used to grow the height threshold with window size.

0.3
initial_distance float

Height threshold (m) for the smallest window.

0.15
max_distance float

Upper limit on the height threshold (m).

2.0
return_mask bool

Return the boolean ground mask instead of the cloud.

False

Returns:

Type Description
PointCloud or ndarray

As for classify_ground_csf.

Raises:

Type Description
ValueError

For non-positive sizes.

ground_mask

ground_mask(cloud: PointCloud) -> np.ndarray

Which points are ground.

Parameters:

Name Type Description Default
cloud PointCloud

A cloud with a classification attribute (from a classifier here or from a LAS file).

required

Returns:

Type Description
ndarray

True where classification == 2 (ASPRS ground).

Raises:

Type Description
ValueError

If the cloud has no classification.

make_dtm

make_dtm(cloud: PointCloud, resolution: float = 0.5, bounds=None, method: str = 'lowest') -> Raster

Digital terrain model from the ground points.

By default each cell takes its lowest ground point. Empty cells (under stems, behind occlusion) are filled from the nearest measured cells and smoothed; measured cells keep their value.

Parameters:

Name Type Description Default
cloud PointCloud

A classified cloud (see ground_mask).

required
resolution float

Cell size (m).

0.5
bounds

(xmin, ymin, xmax, ymax) of the grid; the extent of the ground points if None. Pass the plot extent to get identical grids across dates.

None
method ('lowest', 'tin', 'natural', 'idw')

"lowest" (the default) is the per-cell minimum described above. The others interpolate the ground points at cell centres with sylva.geo.interpolate.grid (a triangulation, natural neighbours or inverse distance weighting with its defaults); cells outside the convex hull of the ground points are then filled from the nearest interpolated cell. Interpolation passes through every ground point, so thin the ground to one point per cell or so first (e.g. filters.voxel_downsample), or noise in the ground returns shows up as roughness in the surface.

"lowest"

Returns:

Type Description
Raster

Ground elevation, no NaN cells.

Raises:

Type Description
ValueError

With fewer than 3 ground points, no classification or an unknown method.

normalize_height

normalize_height(cloud: PointCloud, dtm: Raster, attr: str = 'height') -> PointCloud

Add height above ground as an attribute.

Parameters:

Name Type Description Default
cloud PointCloud

Points in the DTM's frame.

required
dtm Raster

Terrain from make_dtm.

required
attr str

Name of the new attribute.

'height'

Returns:

Type Description
PointCloud

The cloud with attr = z minus the interpolated DTM; coordinates are unchanged. Points outside the DTM take the edge value.

flatten

flatten(cloud: PointCloud, dtm: Raster) -> PointCloud

Replace z with height above ground.

Parameters:

Name Type Description Default
cloud PointCloud

Points in the DTM's frame.

required
dtm Raster

Terrain from make_dtm.

required

Returns:

Type Description
PointCloud

x, y unchanged and z = height above the DTM. Use for methods that read z as height; keep normalize_height when true elevations must be preserved.

make_chm

make_chm(cloud: PointCloud, resolution: float = 0.5, height_attr: str = 'height', bounds=None, min_height: float = 0.0) -> Raster

Canopy height model: the highest point in each cell.

Parameters:

Name Type Description Default
cloud PointCloud

Points with heights (see PointCloud.heights).

required
resolution float

Cell size (m).

0.5
height_attr str

Attribute holding height above ground; z is used if absent.

'height'
bounds

(xmin, ymin, xmax, ymax); the cloud extent if None.

None
min_height float

Cells with nothing above this height are 0.

0.0

Returns:

Type Description
Raster

Maximum height per cell (m). No pit filling is applied, and TLS under-samples the upper canopy far from the scanners.