Products QGIS Scripts Vegetation & Field Analysis Pack
NDVI analysis map of a plantation estate showing false-colour vegetation health raster with polygon plot overlays

QGIS Script Bundle · 6 Scripts

Vegetation & Field Analysis Pack

Six Python scripts for QGIS covering the full vegetation analysis pipeline — from generating a canopy mask and computing canopy-only NDVI per plot to extracting tree heights, filtering rasters by threshold, running zonal statistics, and plotting distributions.

Standard NDVI zonal mean includes bare soil and paths within plot boundaries, giving inflated or misleading health readings. These scripts use a canopy mask to restrict analysis to actual vegetation pixels.

$40 USD One-time purchase · 6 scripts · Instant download
Buy on Gumroad

What you get

generate_canopy_mask.py
canopy_ndvi_median_calc.py
tree_heights_from_dsm_dtm.py
raster_mask_generator.py
zonal_statistics.py
plot_tree_attributes_histograms.py
README with setup and dependency notes
Free updates via Gumroad

What the pack covers

Canopy mask

Separates canopy from ground in a binary raster so downstream NDVI calculations only sample vegetation pixels — not bare soil or paths.

Canopy-only NDVI

Median NDVI per polygon computed only from canopy pixels. Standard zonal mean includes bare soil and gives misleading health readings — this does not.

Tree heights from drone data

Extracts per-feature height (DSM − DTM) without needing a separate point cloud tool. Works on both point and polygon layers with automatic CRS alignment.

Raster threshold filter

Filter any raster by value — keep high-NDVI pixels, mask low-elevation zones, isolate anomalies. Configurable threshold and comparison direction.

Zonal statistics

Aggregate any raster value per polygon in one step. Get mean NDVI per plot, max height per zone, or min elevation per field boundary — saved as a new GeoJSON attribute.

Distribution histograms

Per-species height and NDVI distribution charts — side-by-side for quick comparison. Exported as PNGs for reports or presentations.

Scripts in this pack

generate_canopy_mask.py

Canopy Mask Generator

Creates a binary raster (1 = canopy, 0 = ground) by subtracting the DTM from the DSM. Any pixel where DSM − DTM > 0.1 m is classified as canopy. Used by the NDVI script to filter out bare soil.

Input: DSM raster (name contains "_dsm") + DTM raster (name contains "_dtm") Output: canopy_mask.tif — pixel 1 = canopy, 0 = ground
canopy_ndvi_median_calc.py

Canopy-Only NDVI Median

Computes median NDVI per polygon but only from pixels where the canopy mask shows vegetation. Ignores bare soil patches within plot boundaries. Writes a new NDVI_median field on each polygon feature.

Input: Active polygon layer + canopy_mask raster + NDVI raster (name contains "ndvi") Output: {input_name}_with_ndvi.geojson with NDVI_median field
tree_heights_from_dsm_dtm.py

Tree Heights from Elevation

Adds a "height" field (DSM − DTM) to every feature in a point or polygon layer. Points sample the exact raster location; polygons use max DSM − min DTM in the bounding box. Handles CRS mismatches automatically.

Input: Active point/polygon layer + DSM (name contains "_dsm") + DTM (name contains "_dtm") Output: {input_name}_with_height.geojson with height field
raster_mask_generator.py

Raster Mask by Threshold

Creates a filtered copy of any raster where only pixels that pass a threshold test are kept; all others are set to NoData. For example: keep only NDVI > 0.4 (healthy vegetation) and mask out the rest.

Input: First checked raster layer (any single-band raster) Output: {input_name}_mask_{comparison}{threshold}.tif
zonal_statistics.py

Zonal Statistics per Polygon

Aggregates raster pixel values (mean, median, min, or max) within each polygon zone and writes the result as a new attribute column. Works with any single-band raster — NDVI, elevation, canopy height.

Input: First checked vector layer (polygon zones) + first checked raster layer Output: {raster_name}_{data_type}_{aggregation}.geojson with statistics column
plot_tree_attributes_histograms.py

Height & NDVI Histograms

Reads height and NDVI_median from a polygon layer, groups by tree_type, and plots two side-by-side histograms per group (height distribution + NDVI distribution). Saves each chart as a PNG.

Input: Active polygon layer with height, NDVI_median, and tree_type fields Output: {tree_type}_distribution.png per group

Who it's for

  • Drone surveyors processing multispectral outputs for plantation, orchard, or forestry health assessment
  • GIS analysts who need per-plot NDVI statistics that account for canopy cover rather than raw plot averages
  • Researchers or agronomists comparing height and vegetation health distributions across tree species or varieties

Requirements

QGIS 3.28 or newer — (LTR recommended)
numpy, rasterio — bundled with QGIS
matplotlib — for histograms — install via OSGeo4W Shell if needed
DSM, DTM + NDVI rasters — from drone multispectral survey output

How to use it

  1. 1

    Load your DSM, DTM, and NDVI rasters plus any vector plot layers into QGIS.

  2. 2

    Check (tick) the relevant layers in the Layers panel; set the active layer as each script expects.

  3. 3

    For NDVI median: run generate_canopy_mask.py first to create the canopy mask layer.

  4. 4

    Open Plugins → Python Console → Show Editor.

  5. 5

    Open the script — read the HOW TO USE block at the top for exact layer naming requirements.

  6. 6

    Adjust parameters at the bottom of the script (threshold, aggregation method, data type label, etc.).

  7. 7

    Click Run — outputs are added to your QGIS project automatically.

Recommended workflow order

Run generate_canopy_mask.py first — it creates the canopy_mask layer needed by canopy_ndvi_median_calc.py. The other scripts in the pack are independent of each other.

Get the Vegetation Analysis Pack

Six scripts, one download. Canopy-aware NDVI analysis and tree height extraction from your drone survey data.