Extract Tree Heights from DSM and DTM in QGIS

QGIStutorialtree heightdrone mappingplantationPython

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

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.

Downstream use

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

  • Run plot_tree_attributes_histograms.py to compare height distributions by tree_type
  • Export the GeoJSON for analysis in Python or R
  • Classify by height using classify_layer.py

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.