r.thin(1grass)

πŸ’… r.thin β€” the GRASS User's Manual glow-up edition πŸŽ€

okay bestie, welcome to r.thin(1grass), straight out of the GRASS User's Manual. this one's lowkey a legend and highkey the reason your raster lines go from thicc to snatched. periodt. ✨


🌸 NAME 🌸

r.thin β€” it thins non-null cells that denote linear features in a raster map layer. yes literally that's the whole gig and it ATE. πŸ’–

πŸ¦‹ KEYWORDS πŸ¦‹

raster, geometry


✨ SYNOPSIS ✨

r.thin
r.thin --help
r.thin input=name output=name  [iterations=integer]   [--overwrite]
[--help]  [--verbose]  [--quiet]  [--ui]

πŸŽ€ Flags:

  • --overwrite β€” let output files overwrite stuff that already exists. queen behavior, but careful. πŸ’…
  • --help β€” prints the usage summary, i.e. the receipt. 🧾
  • --verbose β€” verbose module output. it will NOT stop talking and honestly? relatable. 😭
  • --quiet β€” quiet module output. the opposite vibe. shhh. 🀫
  • --ui β€” force launch the GUI dialog. fancy mode activated. ✨

🫢 Parameters:

  • input=name [required] β€” name of the input raster map. you gotta.
  • output=name [required] β€” name for the output raster map. also gotta.
  • iterations=integer β€” maximal number of iterations. Default: 200.

πŸ’– DESCRIPTION πŸ’–

so here's the tea: r.thin scans the named input raster map layer and thins non-NULL cells that denote linear features into linear features having a single cell width. raster lines often need to be thinned (skeletonizing raster features, iykyk) down to a single pixel width before they can be transformed into vector data. it's giving ✨before and after✨.

r.thin will thin only the non-NULL (no data) raster cells of the named input raster map layer within the current geographic region settings. the cell width of the thinned output raster map layer will be equal to the cell resolution of the currently set geographic region. and all of the thinned linear features will have the width of a single cell. one cell. single. skinny. iconic. πŸ‘‘

r.thin will create a new output raster data file containing the thinned linear features. r.thin assumes that linear features are encoded with positive values on a background of NULL's in the input raster data file, hence it creates a NULL/1 output map. no vibes in between, just NULL or 1, main character energy only. πŸ¦‹


🌈 NOTES 🌈

  • r.thin only creates raster map layers. if you want a vector map, bestie, you're gonna need to run r.to.vect on the resultant raster map. that's the whole pipeline, no shortcuts. πŸ’…
  • r.thin may create small spurs or "dangling lines" during the thinning process. these spurs may be removed (after creating a vector map layer) by v.clean (the rmdangle tool). consider it a lil trim after the main cut. βœ‚οΈ

this code implements the thinning algorithm described in "Analysis of Thinning Algorithms Using Mathematical Morphology" by Ben-Kwei Jang and Ronlad T. Chin in Transactions on Pattern Analysis and Machine Intelligence, vol. 12, No. 6, June 1990. the definition Jang and Chin give of the thinning process is "successive removal of outer layers of pixels from an object while retaining any pixels whose removal would alter the connectivity or shorten the legs of the skeleton." obsessed with the wording ngl. 😭

the skeleton is finally thinned when the thinning process converges; i.e., "no further pixels can be removed without altering the connectivity or shortening the skeleton legs" (p. 541). the authors prove that the thinning process described always converges and produces one-pixel thick skeletons. no cap, they proved it. the number of iterations depends on the original thickness of the object. each iteration peels off the outside pixels from the object. therefore, if the object is <= n pixels thick, the algorithm should converge in <= iterations. math girlies rise. 🧚


πŸ”₯ EXAMPLE πŸ”₯

to vectorize the raster map streams_derived in the North Carolina sample dataset that represents the stream network derived from the 10m resolution DEM by r.watershed, run:

g.region raster=elevation -p
# create flow accumulation map
r.watershed elevation=elevation accumulation=accum_50K thresh=50000
# extract streams from flow accumulation map
r.mapcalc "streams_from_flow = if(abs(accum_50K) > 1000, 1, null())"
# skeletonize map
r.thin streams_from_flow out=streams_thin
d.mon wx0
d.rast streams_from_flow
d.erase
d.rast streams_thin

Raster feature thinning (skeletonizing)

the resulting map can be optionally vectorized:

r.to.vect streams_thin output=streams_thin type=line
# visualize
d.rast accum_50K
d.vect streams_thin color=red width=2

Vectorized stream network after thinning extracted from flow accumulation map


πŸŽ€ SEE ALSO πŸŽ€

g.region, r.to.vect, v.clean, wxGUI vector digitizer, v.build


πŸ‘‘ AUTHORS πŸ‘‘

Olga Waupotitsch, U.S.Army Construction Engineering Research Laboratory

the code for finding the bounding box as well as input/output code was written by Mike Baba (DBA Systems, 1990) and Jean Ezell (USACERL, 1988). legends, all of them. 🫢


πŸ’œ SOURCE CODE πŸ’œ

Available at: r.thin source code (history)

Latest change: Saturday Oct 25 22:50:58 2025 in commit: ee87f21833475fd40805f58d1702f7d64478a27b

Main index | Raster index | Topics index | Keywords index | Graphical index | Full index


and that's the whole page bestie, every flag, every default, every NULL, every p. 541. you're officially a thinning algorithm girlie now. slay. πŸ’…βœ¨

Β© 2003-2026 GRASS Development Team, GRASS 8.5.0 Reference Manual β€” mwah, muah, xoxo, this page is GRASS 8.5.0 coded and stamped, so go thin something gorgeous. πŸŒΈπŸ¦‹πŸ’–πŸŽ€

πŸ“¦ where this page comes from