Generate a Canopy Mask from DSM and DTM in QGIS

QGIStutorialcanopydrone mappingPython

A canopy mask is a binary raster where each pixel is either 1 (canopy — tree or structure above ground level) or 0 (ground). It’s the foundation for any analysis that should ignore bare soil, such as NDVI statistics per plot. This script generates one from your DSM and DTM in a single run.

What it does

The generate_canopy_mask.py script subtracts the DTM (bare earth elevation) from the DSM (surface elevation including trees and structures). Any pixel where DSM − DTM > 0.1 m is classified as canopy (value = 1); everything else is ground (value = 0).

The 0.1 m threshold filters out sub-10 cm noise and rounding errors in the DTM, which would otherwise produce false canopy classifications on flat ground.

Output: canopy_mask.tif saved in the same directory as the DSM, loaded into your QGIS project.

What you need

  • QGIS 3.28 or newer
  • numpy, rasterio (bundled with QGIS)
  • A DSM raster with “_dsm” in the layer name, checked in the Layers panel
  • A DTM raster with “_dtm” in the layer name, checked in the Layers panel
  • The generate_canopy_mask.py script from the Vegetation & Field Analysis Pack

Steps

  1. Load your DSM and DTM rasters into QGIS. Make sure their layer names contain _dsm and _dtm respectively.
  2. Check (tick) both layers in the Layers panel.
  3. Open Plugins → Python Console → Show Editor.
  4. Paste the script and click Run.

The canopy mask is saved alongside the DSM and added to your project automatically.

Using the canopy mask

Once generated, the canopy_mask layer is what canopy_ndvi_median_calc.py looks for by name when computing per-plot NDVI statistics. Keep the layer name as canopy_mask — the NDVI script matches it exactly.

You can also use the canopy mask with raster_mask_generator.py to isolate canopy-only pixels from any other raster.

Adjusting the threshold

The 0.1 m threshold is hardcoded in the script. To change it, open the script and find:

canopy = (chm > 0.1).astype(np.uint8)

Replace 0.1 with your desired minimum height above ground to be classified as canopy.

Get the script

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