Extract Tree Heights from DSM and DTM in QGIS

QGIStutorialtree heightdrone mappingaerial surveyplantationcoconutprecision agriculturePython
Extract Tree Heights from DSM and DTM in QGIS

After annotating individual trees or plot polygons in QGIS, the most common next step is to get a height for each one. This script extracts that directly from DSM and DTM rasters without needing to process the original point cloud.

What it does

The tree_heights_from_dsm_dtm.py script adds a height field (DSM − DTM in metres) to every feature in the active vector layer.

The sampling approach depends on geometry type:

  • Point features — samples the exact DSM and DTM raster values at the point’s location
  • Polygon features — takes the maximum DSM value minus the minimum DTM value within the polygon’s bounding box (approximates the tallest point inside the polygon)

If the vector layer and rasters are in different CRS, the script reprojects the vector automatically before sampling.

Output: {input_name}_with_height.geojson saved alongside the original, with a new height field, loaded into the QGIS project.

What you need

  • QGIS 3.28 or newer
  • numpy, rasterio (bundled with QGIS)
  • Active point or polygon layer (tree annotations or plot polygons)
  • DSM raster with “_dsm” in the layer name, checked in the Layers panel
  • DTM raster with “_dtm” in the layer name, checked in the Layers panel
  • The tree_heights_from_dsm_dtm.py script from the Vegetation & Field Analysis Pack

Here’s what the two required rasters look like on a real coconut plantation survey, as coloured hillshade. DSM — surface elevation, includes canopy:

DSM hillshade coloured by elevation, showing individual coconut palm canopies as raised bumps against the surrounding ground

DTM — bare ground elevation, canopy stripped out. height is the difference between these two at each tree:

DTM hillshade of the same site — bare ground elevation with canopy stripped out

Steps

  1. Load your DSM and DTM rasters into QGIS. Layer names must contain _dsm and _dtm.
  2. Load your tree point or polygon layer and click it to make it the active layer.
  3. Check (tick) the DSM and DTM rasters in the Layers panel.
  4. Open Plugins → Python Console → Show Editor.
  5. Paste the script and click Run.

The output file is saved alongside the source vector file and added to the QGIS project.

Accuracy notes

  • Point layers — height accuracy depends on the DSM/DTM spatial resolution. At 5 cm/pixel a single point is sampled; at 20 cm/pixel nearby objects can affect the reading.
  • Polygon layers — the script uses max DSM − min DTM within the bounding box. For precise crown height measurement, use point features at the estimated tree top location.

Here’s the result on a real coconut plantation survey — height grouped into percentile classes and styled, one step in a complete per-tree health workflow that also covers canopy NDVI:

Coconut palms coloured by height class — Short, Medium, Tall, Very Tall — with legend overlaid

Downstream use

Once you have height values on each feature, you can:

Get the script

tree_heights_from_dsm_dtm.py is part of the Vegetation & Field Analysis Pack — six vegetation analysis scripts for QGIS at $40 USD.