Short answer
To produce a trustworthy slope raster in QGIS, run Processing Toolbox > GDAL > Raster analysis > Slope (gdaldem slope) or Raster terrain analysis > Slope on a single-band elevation DEM that sits in a projected CRS where the horizontal cell units match the vertical units. Decide up front whether you want degrees or percent rise, set the Z factor to reconcile any unit mismatch, and validate the result against known control values before it leaves your project.
The single most common failure is running slope on a DEM in EPSG:4326, where cells are measured in degrees and elevation in metres. The tool divides metres by degrees, and the output is geometrically meaningless even though it renders without an error.
How slope is actually computed
QGIS and GDAL both estimate slope from a 3x3 moving window centred on each cell. The default GDAL method is the Horn (1981) algorithm, which is the same finite-difference approach ArcGIS uses. It computes the rate of change in elevation in the x and y directions using a distance-weighted average of the eight neighbours:
dz/dx = ((c + 2f + i) - (a + 2d + g)) / (8 * cellsize_x)
dz/dy = ((g + 2h + i) - (a + 2b + c)) / (8 * cellsize_y)
slope_rad = atan( sqrt( (dz/dx)^2 + (dz/dy)^2 ) )
where a-i are the nine elevation values in the window. The critical term is cellsize: it must be a real ground distance in the same unit as elevation. If your DEM cell is 30 m and elevation is in metres, the maths is clean. If the cell is 0.000277 degrees and elevation is metres, the gradient is inflated by roughly five orders of magnitude.
GDAL also offers -alg ZevenbergenThorne, a four-neighbour method that is slightly sharper on smooth surfaces and is often preferred for hydrological derivatives. For general terrain work, Horn is the safe default.
Degrees vs percent: not interchangeable
- Degrees range from 0 (flat) to 90 (vertical). Use them for landslide susceptibility, slope-stability screening, and most engineering thresholds.
- Percent rise is
tan(slope_degrees) x 100. A 45-degree slope is 100 percent, not 45. Percent is standard for road grades, drainage design, and agricultural suitability.
In gdaldem slope you switch with the -p flag for percent; omit it for degrees. In the QGIS GDAL dialog there is a checkbox labelled "Slope expressed as percent instead of degrees." Mislabelling a percent raster as degrees is one of the quietest errors in terrain analysis because both are plausible numbers in the 0-60 range.
The Z factor and the geographic-CRS trap
The Z factor multiplies elevation before the gradient is computed. Its only job is to reconcile vertical and horizontal units.
| Situation | Z factor |
|---|---|
| Cells and elevation both in metres | 1 |
| Cells in metres, elevation in feet | 0.3048 |
| Cells in feet, elevation in metres | 3.28084 |
| Geographic CRS (degrees), elevation in metres | ~111320 at the equator, decreasing with latitude |
The cleanest fix for a geographic DEM is to reproject it to a projected CRS before computing slope. For most regional work, pick the appropriate UTM zone:
gdalwarp -t_srs EPSG:32631 -r bilinear -tr 30 30 \
-tap srtm_geographic.tif srtm_utm31n.tif
-r bilinear is the right resampler for continuous elevation (never near, which steps the surface and creates false flat terraces). -tr 30 30 sets a square cell, and -tap aligns to a clean grid. After this, slope with Z factor 1 is correct.
If you genuinely cannot reproject (for example, a global mosaic), GDAL exposes -s ESRI:... style handling and you can supply a latitude-scaled Z factor, but reprojection is almost always cleaner.
A worked workflow
- Inspect the DEM. Open the layer properties, read the CRS and the band unit. Run
gdalinfo -stats dem.tifand confirm there is a single band, a sensible NoData value (often -9999 or -32768), and a min/max elevation range that matches your area. - Reproject if needed to a projected CRS with
gdalwarpas above. Use bilinear resampling. - Fill or flag voids. SRTM and ASTER GDEM contain voids. For visualisation you can interpolate small voids with GRASS r.fillnulls; for analysis, keep NoData honest and document it.
- Compute slope. In the Processing Toolbox search "Slope". For GDAL: input DEM, band 1, choose degrees or percent, Z factor 1, leave "compute edges" on so the outer ring is not NoData. The CLI equivalent:
gdaldem slope dem_utm31n.tif slope_deg.tif -alg Horn -compute_edges - Style the output. Apply a singleband pseudocolor ramp with class breaks that mean something for your purpose, for example 0-2, 2-5, 5-15, 15-30, 30+ degrees for a stability screen, rather than a smooth continuous ramp that hides thresholds.
- Save a named GeoTIFF with
COMPRESS=DEFLATEand internal overviews (gdaladdo) so it loads fast and travels well.
Common pitfalls and why they happen
- Slope values that top out near 89 degrees everywhere. The DEM is in a geographic CRS. The gradient is being divided by a degree-sized cell. Reproject.
- A halo of NoData one pixel wide around the edge. Edge cells lack a full 3x3 window. Add
-compute_edges(GDAL) or accept that QGIS Raster terrain analysis trims the border. - Spurious flat terraces or staircase artefacts. The DEM was resampled with nearest-neighbour, or it is an integer raster with coarse vertical quantisation. Resample with bilinear and prefer float DEMs.
- Mismatched extents when overlaying slope with another derivative. Slope and aspect must be computed from the same DEM at the same resolution and snap origin; otherwise pixels do not co-register.
Validation
- Pick a location with a known engineered grade (a highway embankment, a quarry bench) and compare the computed slope against the design value.
- Cross-check QGIS Raster terrain analysis against
gdaldem slopeon the same input; Horn-based results should agree to within rounding. - Run
gdalinfo -stats slope_deg.tifand confirm the max is below 90 for degrees, or that percent values exceed 100 only on genuinely steep terrain. - Histogram the raster. A long, smooth tail above 70 degrees usually signals noise or a unit error, not real cliffs.
Bathyl perspective
We treat a slope raster as a measurement product, not decoration. Before it informs a hazard map or a siting decision, we lock the CRS, record the algorithm and Z factor in the layer metadata, and state the DEM source and resolution so the next analyst can reproduce it exactly. Slope is only as good as the elevation surface it came from.
Related reading
- QGIS Georeferencing Scanned Maps
- Raster Cell Alignment and Snap Raster Concepts
- QGIS vs ArcGIS for Geological and Terrain Workflows
- Terrain intelligence