r.dem.icp
Co-register DEM surfaces using Iterative Closest Point (point-to-plane).
Aligns a source DEM to a reference DEM with robust, multi-scale ICP.
r.dem.icp reference=name source=name output=name [mask=name] [dof=integer] [levels=integer] [stride=integer] [max_iterations=integer] [trim=float] [huber=float] [tolerance=float] [distance_max=float] [slope_max=float] [init_dx=float] [init_dy=float] [init_dz=float] [init_yaw=float] [init_roll=float] [init_pitch=float] [transform_out=name] [stats_out=name] [nprocs=integer] [--overwrite] [--verbose] [--quiet] [--qq] [--ui]
Example:
r.dem.icp reference=name source=name output=name
grass.tools.Tools.r_dem_icp(reference, source, output, mask=None, dof=4, levels=3, stride=2, max_iterations=30, trim=0.80, huber=1.0, tolerance=1e-5, distance_max=10, slope_max=90, init_dx=0, init_dy=0, init_dz=0, init_yaw=0, init_roll=0, init_pitch=0, transform_out=None, stats_out=None, nprocs=0, overwrite=None, verbose=None, quiet=None, superquiet=None)
Example:
tools = Tools()
tools.r_dem_icp(reference="name", source="name", output="name")
This grass.tools API is experimental in version 8.5 and expected to be stable in version 8.6.
grass.script.run_command("r.dem.icp", reference, source, output, mask=None, dof=4, levels=3, stride=2, max_iterations=30, trim=0.80, huber=1.0, tolerance=1e-5, distance_max=10, slope_max=90, init_dx=0, init_dy=0, init_dz=0, init_yaw=0, init_roll=0, init_pitch=0, transform_out=None, stats_out=None, nprocs=0, overwrite=None, verbose=None, quiet=None, superquiet=None)
Example:
gs.run_command("r.dem.icp", reference="name", source="name", output="name")
Parameters
reference=name [required]
Reference DEM raster
source=name [required]
Source DEM raster to align
output=name [required]
Output aligned DEM raster
mask=name
Optional stable-terrain mask (non-zero=use)
dof=integer
Degrees of freedom (4: dx,dy,dz,yaw; 6: add roll,pitch - experimental)
Allowed values: 4, 6
Default: 4
levels=integer
ICP pyramid levels (coarse to fine)
Default: 3
stride=integer
Base sampling stride (cells) at finest level
Default: 2
max_iterations=integer
Max iterations per level
Default: 30
trim=float
Trimmed ICP keep fraction [0-1]
Default: 0.80
huber=float
Huber delta (m); 0 disables
Default: 1.0
tolerance=float
Convergence threshold on parameter update norm
Default: 1e-5
distance_max=float
Max point-to-plane distance (m); 0 disables
Default: 10
slope_max=float
Reject target cells with slope > (deg)
Default: 90
init_dx=float
Initial dx (m)
Default: 0
init_dy=float
Initial dy (m)
Default: 0
init_dz=float
Initial dz (m)
Default: 0
init_yaw=float
Initial yaw (deg)
Default: 0
init_roll=float
Initial roll (deg) (6-DoF only)
Default: 0
init_pitch=float
Initial pitch (deg) (6-DoF only)
Default: 0
transform_out=name
Write final transform to file
stats_out=name
Write per-iteration stats to file
nprocs=integer
Number of threads for parallel computing
0: use OpenMP default; >0: use nprocs; <0: use MAX-nprocs
Default: 0
--overwrite
Allow output files to overwrite existing files
--help
Print usage summary
--verbose
Verbose module output
--quiet
Quiet module output
--qq
Very quiet module output
--ui
Force launching GUI dialog
reference : str | np.ndarray, required
Reference DEM raster
Used as: input, raster, name
source : str | np.ndarray, required
Source DEM raster to align
Used as: input, raster, name
output : str | type(np.ndarray) | type(np.array) | type(gs.array.array), required
Output aligned DEM raster
Used as: output, raster, name
mask : str | np.ndarray, optional
Optional stable-terrain mask (non-zero=use)
Used as: input, raster, name
dof : int, optional
Degrees of freedom (4: dx,dy,dz,yaw; 6: add roll,pitch - experimental)
Allowed values: 4, 6
Default: 4
levels : int, optional
ICP pyramid levels (coarse to fine)
Default: 3
stride : int, optional
Base sampling stride (cells) at finest level
Default: 2
max_iterations : int, optional
Max iterations per level
Default: 30
trim : float, optional
Trimmed ICP keep fraction [0-1]
Default: 0.80
huber : float, optional
Huber delta (m); 0 disables
Default: 1.0
tolerance : float, optional
Convergence threshold on parameter update norm
Default: 1e-5
distance_max : float, optional
Max point-to-plane distance (m); 0 disables
Default: 10
slope_max : float, optional
Reject target cells with slope > (deg)
Default: 90
init_dx : float, optional
Initial dx (m)
Default: 0
init_dy : float, optional
Initial dy (m)
Default: 0
init_dz : float, optional
Initial dz (m)
Default: 0
init_yaw : float, optional
Initial yaw (deg)
Default: 0
init_roll : float, optional
Initial roll (deg) (6-DoF only)
Default: 0
init_pitch : float, optional
Initial pitch (deg) (6-DoF only)
Default: 0
transform_out : str, optional
Write final transform to file
Used as: output, file, name
stats_out : str, optional
Write per-iteration stats to file
Used as: output, file, name
nprocs : int, optional
Number of threads for parallel computing
0: use OpenMP default; >0: use nprocs; <0: use MAX-nprocs
Default: 0
overwrite : bool, optional
Allow output files to overwrite existing files
Default: None
verbose : bool, optional
Verbose module output
Default: None
quiet : bool, optional
Quiet module output
Default: None
superquiet : bool, optional
Very quiet module output
Default: None
Returns:
result : grass.tools.support.ToolResult | np.ndarray | tuple[np.ndarray] | None
If the tool produces text as standard output, a ToolResult object will be returned. Otherwise, None will be returned. If an array type (e.g., np.ndarray) is used for one of the raster outputs, the result will be an array and will have the shape corresponding to the computational region. If an array type is used for more than one raster output, the result will be a tuple of arrays.
Raises:
grass.tools.ToolError: When the tool ended with an error.
reference : str, required
Reference DEM raster
Used as: input, raster, name
source : str, required
Source DEM raster to align
Used as: input, raster, name
output : str, required
Output aligned DEM raster
Used as: output, raster, name
mask : str, optional
Optional stable-terrain mask (non-zero=use)
Used as: input, raster, name
dof : int, optional
Degrees of freedom (4: dx,dy,dz,yaw; 6: add roll,pitch - experimental)
Allowed values: 4, 6
Default: 4
levels : int, optional
ICP pyramid levels (coarse to fine)
Default: 3
stride : int, optional
Base sampling stride (cells) at finest level
Default: 2
max_iterations : int, optional
Max iterations per level
Default: 30
trim : float, optional
Trimmed ICP keep fraction [0-1]
Default: 0.80
huber : float, optional
Huber delta (m); 0 disables
Default: 1.0
tolerance : float, optional
Convergence threshold on parameter update norm
Default: 1e-5
distance_max : float, optional
Max point-to-plane distance (m); 0 disables
Default: 10
slope_max : float, optional
Reject target cells with slope > (deg)
Default: 90
init_dx : float, optional
Initial dx (m)
Default: 0
init_dy : float, optional
Initial dy (m)
Default: 0
init_dz : float, optional
Initial dz (m)
Default: 0
init_yaw : float, optional
Initial yaw (deg)
Default: 0
init_roll : float, optional
Initial roll (deg) (6-DoF only)
Default: 0
init_pitch : float, optional
Initial pitch (deg) (6-DoF only)
Default: 0
transform_out : str, optional
Write final transform to file
Used as: output, file, name
stats_out : str, optional
Write per-iteration stats to file
Used as: output, file, name
nprocs : int, optional
Number of threads for parallel computing
0: use OpenMP default; >0: use nprocs; <0: use MAX-nprocs
Default: 0
overwrite : bool, optional
Allow output files to overwrite existing files
Default: None
verbose : bool, optional
Verbose module output
Default: None
quiet : bool, optional
Quiet module output
Default: None
superquiet : bool, optional
Very quiet module output
Default: None
DESCRIPTION
r.dem.icp performs constrained-rigid (4-DoF) co-registration of two DEM rasters, with an experimental full 6-DoF mode, aligning a source DEM to a reference DEM with an Iterative Closest Point (ICP) solver. Key properties of the implementation:
- Point-to-plane ICP with projective correspondences (the target DEM is sampled at the transformed (x, y) location).
- Multiscale, coarse-to-fine alignment via an adjustable sampling stride.
- Trimmed ICP (keep the best residual fraction) with Huber robust weighting.
- OpenMP parallelization of the main loops.
- DEM-specific handling: surface normals from DEM gradients, an optional slope limit, and an optional stable-terrain mask.
NOTES
- Initialization: If you already know an approximate horizontal shift or
yaw (for example from metadata or phase correlation), pass it via the
init_dx, init_dy, init_dz, and init_yaw options. A good
init_dz is often the median of
source - referenceover stable terrain. In the experimental 6-DoF mode, init_roll and init_pitch (degrees) additionally seed the roll and pitch angles; they are ignored withdof=4. - Speed knobs: Increase stride and reduce levels for quick tests, and relax max_iterations.
- Robustness: Use a conservative trim (
0.6-0.9). Where there is a lot of real change (landslides, forest canopy), lower trim and/or huber. - Constraints: 4-DoF (
dof=4) is the supported mode and usually suffices (e.g., airborne photogrammetry vs LiDAR). The four solved parameters are the three translations plus yaw (planimetric rotation about the vertical axis), which absorbs residual georeferencing rotation; roll and pitch are deliberately excluded. 6-DoF (dof=6) is experimental: rigid roll/pitch rotation is ill-conditioned for height-field DEMs and its resample is approximate, so leave it off unless you specifically need to model tilt. The residual that typically remains after 4-DoF is a sub-pixel horizontal shift and vertical offset; remove it by running r.dem.nk (Nuth & Kaeaeb) after ICP. - Validation: After alignment, inspect the residual DoD and the stats file; residual bias should be near zero on stable terrain.
EXAMPLES
The commands below use the example scene built in the r.dem toolset manual, which is derived from the North Carolina sample dataset. Build it there first.
Align the misregistered surface with four degrees of freedom, which solves three translations and yaw:
g.region raster=elev_lid792_1m
r.dem.icp source=dsm_offset reference=elev_lid792_1m \
mask=stable_terrain output=dsm_icp dof=4 \
transform_out=icp_transform.txt stats_out=icp_stats.csv
The reported transform is the one that maps the source onto the reference, so its signs are opposite to those of r.dem.nk. Against an applied offset of 0.4596 m east, 0.4596 m north, and 1.32 m up it returns:
tx=-0.4590844708
ty=-0.4608043693
tz=-1.3201388046
yaw=0.0000935114

Figure: Stable-terrain residual before and after r.dem.icp at dof=4.
REFERENCES
- ICP framework (point-to-point origin). Besl, P.J. and McKay, N.D. (1992). A method for registration of 3-D shapes. IEEE Transactions on Pattern Analysis and Machine Intelligence, 14(2), 239-256. doi:10.1109/34.121791
- Point-to-plane error metric (minimized here). Chen, Y. and Medioni, G. (1992). Object modelling by registration of multiple range images. Image and Vision Computing, 10(3), 145-155. doi:10.1016/0262-8856(92)90066-C
- Projective correspondences (target sampled at the transformed x, y). Blais, G. and Levine, M.D. (1995). Registering multiview range data to create 3D computer objects. IEEE Transactions on Pattern Analysis and Machine Intelligence, 17(8), 820-824. doi:10.1109/34.400574
- Efficient ICP variants (sampling, rejection, coarse-to-fine). Rusinkiewicz, S. and Levoy, M. (2001). Efficient variants of the ICP algorithm. Proceedings Third International Conference on 3-D Digital Imaging and Modeling (3DIM), 145-152. doi:10.1109/IM.2001.924423
- Linearized least-squares point-to-plane solve. Low, K.-L. (2004). Linear least-squares optimization for point-to-plane ICP surface registration. Technical Report TR04-004, Department of Computer Science, University of North Carolina at Chapel Hill. PDF
- Trimmed ICP (robust to partial overlap and change). Chetverikov, D., Stepanov, D. and Krsek, P. (2005). Robust Euclidean alignment of 3D point sets: the trimmed iterative closest point algorithm. Image and Vision Computing, 23(3), 299-309. doi:10.1016/j.imavis.2004.05.007
- Robust M-estimator weighting. Huber, P.J. (1964). Robust estimation of a location parameter. The Annals of Mathematical Statistics, 35(1), 73-101. doi:10.1214/aoms/1177703732
- Convergence analysis of point-to-plane registration. Pottmann, H., Huang, Q.-X., Yang, Y.-L. and Hu, S.-M. (2006). Geometry and convergence analysis of algorithms for registration of 3D shapes. International Journal of Computer Vision, 67(3), 277-296. doi:10.1007/s11263-006-5167-2
Related methods not implemented here: Nuth, C. and Kaeaeb, A. (2011), The Cryosphere 5:271-290 (aspect/slope vertical-bias coregistration, provided as r.dem.nk); Segal, A., Haehnel, D. and Thrun, S. (2009), Generalized-ICP, Robotics: Science and Systems.
SEE ALSO
r.dem, r.dem.coregister, r.dem.nk
AUTHORS
Corey T. White, Center for Geospatial Analytics, NC State University
SOURCE CODE
Available at: r.dem.icp source code
(history)
Latest change: Thursday Aug 20 19:32:37 2026 in commit d08d385