Running SMRF on Photogrammetric Point Clouds

TL;DR: Photogrammetric clouds are dense, single-surface and noisy, with no return numbers. Thin them to a few points per square metre with filters.voxelcenternearestneighbor, remove statistical outliers, then run filters.smrf with returns unrestricted (there are only “first” returns), a small cell (0.25–0.5 m), a tight threshold (0.15–0.3 m) and a window matched to the largest object. Treat classified “ground” under vegetation as unreliable: dense matching sees only the canopy.

# Context and Motivation

This guide is part of SMRF Ground Classification. Drone surveys increasingly produce point clouds from overlapping photographs rather than lasers. Structure-from-motion and dense image matching yield hundreds of points per square metre with colour, and SMRF can classify them — but three differences from LiDAR change how. There are no multiple returns: every point is the visible surface, so under trees there is no ground at all, only canopy. Density is very high and uneven, which makes SMRF slow and its grid choices different. And noise has a different character: matching errors produce fuzzy surfaces and occasional floating blobs rather than isolated low returns.

Handled correctly, SMRF produces good bare-earth models of open sites — quarries, construction sites, agricultural fields, stockpiles. Handled naively, it produces a DTM that follows the tree canopy.

No returns beneath the canopy Two side-by-side profiles of a tree over ground. LiDAR: pulses penetrate the canopy and produce last returns on the ground beneath, so SMRF can find ground there. Photogrammetry: points exist only on the visible top of the canopy; the ground beneath has no points, so any ground surface there is interpolated across the gap. LiDAR photogrammetry last returns reach the ground no points: ground must be interpolated

# Prerequisites and Assumptions

  • A photogrammetric point cloud in LAS/LAZ with a projected CRS, typically from software such as OpenDroneMap, Metashape or Pix4D.
  • PDAL 2.x.
  • Ground control used in the photogrammetric solution, so absolute heights are meaningful.
  • An open or mostly open site; closed canopy cannot be classified meaningfully from images.

# Step-by-Step Implementation

# Step 1 — Thin to a manageable density

Voxel thinning at 0.1–0.2 m keeps plenty of points for a 0.25–0.5 m DTM while cutting run time by an order of magnitude.

# Step 2 — Remove matching noise

filters.outlier (statistical) removes floating blobs; a range filter on Z removes gross errors above and below the site.

# Step 3 — Set return fields

Photogrammetric exports often leave ReturnNumber and NumberOfReturns at 0. SMRF by default considers “last,only” returns; set both fields to 1 with filters.assign so every point counts as an only return.

# Step 4 — Run SMRF with fine settings

Small cell, tight threshold, window matched to the largest object on site (a stockpile, a building, a machine).

# Step 5 — Mask vegetation from ground

Use colour (a vegetation index from RGB) or height to identify canopy areas and exclude them from ground, reporting them as interpolated in the DTM.

# Complete Working Example

json
{
  "pipeline": [
    { "type": "readers.las", "filename": "drone/quarry_2026_08.laz" },
    { "type": "filters.voxelcenternearestneighbor", "cell": 0.15 },
    { "type": "filters.outlier", "method": "statistical", "mean_k": 16, "multiplier": 2.2 },
    { "type": "filters.range", "limits": "Classification![7:7]" },
    { "type": "filters.assign", "value": [
        "ReturnNumber = 1", "NumberOfReturns = 1", "Classification = 1" ] },
    { "type": "filters.smrf", "cell": 0.4, "slope": 0.3, "window": 20,
      "threshold": 0.2, "scalar": 1.2 },
    { "type": "writers.las", "filename": "out/quarry_ground.laz", "minor_version": 4,
      "dataformat_id": 7, "forward": "all", "tag": "classified" },
    { "type": "filters.range", "inputs": ["classified"], "limits": "Classification[2:2]" },
    { "type": "writers.gdal", "filename": "out/quarry_dtm_025.tif", "resolution": 0.25,
      "radius": 0.35, "output_type": "idw", "window_size": 8, "data_type": "float32" }
  ]
}

A vegetation mask from RGB, excluding green points from ground after the fact:

python
"""Remove likely vegetation from photogrammetric ground using an RGB index."""
import json

import numpy as np
import pdal

p = pdal.Pipeline(json.dumps({"pipeline": ["out/quarry_ground.laz"]}))
p.execute()
a = p.arrays[0]
r, g, b = (a[c].astype(float) for c in ("Red", "Green", "Blue"))
exg = (2 * g - r - b) / np.maximum(r + g + b, 1)          # excess green, about -1 to 1
veg = exg > 0.08
changed = (a["Classification"] == 2) & veg
a["Classification"][changed] = 3                          # low vegetation, pending review
pdal.Writer.las(filename="out/quarry_ground_vegmask.laz", minor_version=4,
                dataformat_id=7, forward="all").pipeline(a).execute()
print(f"{changed.sum():,} ground points reassigned as vegetation ({changed.mean():.1%})")
Thinning buys speed cheaply Bars of SMRF run time on a drone photogrammetry site for four voxel sizes. With no thinning at about 400 points per square metre, the run takes 21 minutes. At 0.1 metre voxels, 4 minutes. At 0.15 metres, 2 minutes. At 0.3 metres, 40 seconds. DTM differences from the unthinned result stay under 2 centimetres up to 0.15 metre voxels. no thinning0.10 m voxels0.15 m voxels0.30 m voxels 21 min4 min2 min · Δ < 2 cm40 s · Δ ≈ 5 cm illustrative 12 ha site

# Key Parameter Table

Setting LiDAR typical Photogrammetry typical Reason
voxel thinning none 0.1–0.2 m Hundreds of pts/m² are unnecessary for SMRF
cell 1.0 m 0.25–0.5 m Dense data supports a finer minimum surface
threshold 0.5 m 0.15–0.3 m Matched surfaces are smoother on bare ground
window 18 m size of largest object Stockpiles and buildings set it
return fields from sensor set to 1 SMRF’s default return filter needs them
vegetation handling returns reach ground mask and interpolate No ground under canopy

# Verification

  • Checkpoints on open ground. Compare the DTM with GNSS checkpoints on hard surfaces; photogrammetric DTMs on open ground often reach a few centimetres.
  • Vegetated areas flagged. Map where the vegetation mask removed ground; the DTM there is interpolation and should be labelled so.
  • Stockpile edges. Profile across a stockpile toe; SMRF should classify the toe as ground and the pile as non-ground, not cut into the pile.

# Gotchas and Edge Cases

Zero return numbers. If ReturnNumber is 0, SMRF’s default returns: "last,only" may select nothing, and the output has no ground at all. Set the fields, or set returns explicitly.

Doming and bowling. Photogrammetric solutions without enough ground control can bend the whole surface by decimetres. No ground filter fixes that; check the block’s residuals and control distribution.

Shadows and water. Dark shadows and water surfaces match poorly and produce noise or holes. The outlier filter removes the worst; flatten water separately.

Doming is not a classification problem A flat site surface drawn as a straight line, and the photogrammetric surface bowed upward in the middle by about 0.3 metres because ground control was only placed around the edges. Checkpoints near the centre reveal the bow. Ground classification cannot remove it; the photogrammetric solution must be redone with better control. ≈ 0.3 m dome triangles: control only at the edges · dot: central checkpoint

Colour-based masks. Excess-green works on healthy vegetation in daylight. Dry grass, autumn leaves and shaded canopy need other cues — height above the SMRF surface is often more robust.

# Frequently Asked Questions

Can SMRF classify ground in drone photogrammetry point clouds?

Yes, on open ground, with adjustments: thin the cloud, remove matching noise, set return numbers to 1, and use a finer cell and tighter threshold than for LiDAR. Under vegetation there are no ground points, so the result there is interpolation.

Why does SMRF find no ground in my photogrammetric cloud?

Usually because ReturnNumber and NumberOfReturns are zero, so SMRF’s default filter for last and only returns selects nothing. Set both fields to 1 before running it, or change the returns option.

How dense should a photogrammetric cloud be for SMRF?

A few tens of points per square metre is plenty for a DTM at 0.25 to 0.5 metres. Thinning denser clouds speeds processing greatly with little effect on the result.

Is a photogrammetric DTM as accurate as a LiDAR DTM?

On open, well-textured ground with good control it can be comparable. Under vegetation it cannot, because the ground is never seen. Report the vegetated area as interpolated.