Felzenszwalb-Huttenlocher (FH) graph-based image segmentation
Source:R/fh_segmenter.R
fh_segmenter.RdSegments a multi-band image using the **Felzenszwalb-Huttenlocher** graph-based
region merging algorithm (often used as an efficient OBIA-style "superpixel"
generator). Each pixel is a node in a grid graph; edges connect neighboring
pixels (4- or 8-neighborhood) with weights given by spectral distance.
Regions are merged in increasing edge-weight order subject to an adaptive
internal-difference criterion controlled by k, with an optional cleanup
pass that enforces a minimum region size.
Usage
fh_segmenter(
x,
k = 1,
min_size = 50,
eight = TRUE,
scale_bands = TRUE,
smooth = 0,
output_file = NULL,
verbose = TRUE
)Arguments
- x
A
SpatRasterwith one or more layers (bands). Bands should be numeric and represent co-registered imagery (e.g., RGB, VNIR/SWIR).- k
Numeric scalar. Scale/threshold parameter controlling region merging. Larger
kgenerally yields fewer, larger segments.- min_size
Integer scalar. Minimum allowed segment size (in pixels). Segments smaller than this are merged during a cleanup pass.
- eight
Logical. If
TRUE, use 8-neighborhood connectivity; ifFALSE, use 4-neighborhood connectivity.- scale_bands
Logical. If
TRUE(recommended), each band is z-score scaled using its mean and standard deviation computed withna.rm=TRUE.- smooth
Integer scalar. If
> 0, applies a mean (box) filter of sizesmooth x smoothto each band before segmentation. Use small odd values (e.g., 3 or 5). Set to0to disable smoothing.- output_file
Optional character string. If provided, the resulting segmentation raster is written to this file via
terra::writeRaster().- verbose
Do progress messages? (default: TRUE)
Value
A single-layer SpatRaster with integer segment IDs
in the layer "segment_id". Invalid pixels are NA.
Details
This wrapper accepts a SpatRaster and returns a single-layer
label raster with integer segment IDs. It optionally applies a mean (box) filter
prior to segmentation and z-score scales each band to stabilize the distance
threshold across bands and sensors.
**Algorithm behavior**
kcontrols the tendency to merge: larger values typically produce larger segments.min_sizeenforces a minimum mapping unit by merging small regions to the most similar neighbor in a post-processing step.eighttoggles 8-neighborhood (Queen) vs 4-neighborhood (Rook) connectivity; 8-neighborhood usually yields more "diagonal-safe" objects.scale_bandsapplies per-band z-score scaling usingna.rm=TRUE.
**NA handling**
Pixels with NA in any band are treated as invalid by the underlying C++
implementation and returned as NA in the output label raster.
If your scene contains large NA areas, consider masking/cropping/filling
prior to segmentation to avoid creating many invalid edge cases.
**Performance notes** The heavy lifting is implemented in Rcpp/C++ and is designed for large rasters. For very large scenes, prefer tiling.
See also
boundaries,as.polygonsfor visualization and vectorization of segments.
Examples
if (FALSE) { # \dontrun{
library(terra)
r <- rast("image.tif")
seg <- fh_segmenter(
r,
k = 0.5,
min_size = 20,
eight = TRUE,
scale_bands = TRUE,
smooth = 3
)
# Overlay boundaries on RGB
rgb <- stretch(r[[1:3]])
bnd <- boundaries(seg, directions = 8)
plotRGB(rgb, r=1, g=2, b=3, stretch="lin")
plot(bnd, add=TRUE, col="yellow", lwd=0.8)
} # }