Binary Image Thinning Algorithms
Overview
Thinning (skeletonization) algorithms for binary raster images. Provides seven algorithms behind a single dispatching function: Zhang-Suen (Zhang and Suen 1984) doi:10.1145/357994.358023, Guo-Hall (Guo and Hall 1989) doi:10.1145/62065.62074, a 2-D adaptation of Lee (Lee, Kashyap, and Chu 1994) doi:10.1006/cgip.1994.1042, K3M (Saeed, Tabedzki, Rybnik, and Adamski 2010) doi:10.2478/v10006-010-0024-4, the parallel form commonly attributed to Hilditch (1969, in 'Machine Intelligence 4'), OPTA / SPTA (Naccache and Shinghal 1984), and Holt and colleagues (1987) doi:10.1145/12527.12531. Also provides the medial axis transform (Blum 1967) and a distance transform implementation following Felzenszwalb and Huttenlocher (2012) doi:10.4086/toc.2012.v008a019. The thin() API selects the algorithm by name, defaulting to Zhang-Suen. Complements the morphology in the 'EBImage' package, which does not provide a thinning operator.
Correctness fixes from the figureextract ecosystem review (2026-07-03).
All are boundary conditions the published algorithms assume away; see the
new vignette("correctness-properties") for the guarantees they restore.
thin()now skeletonises shapes that touch the matrix border correctly. The kernels inspect an 8-neighbourhood and so never deleted pixels in the outermost row or column, leaving edge-touching shapes two to three pixels thick;thin()now pads the image with a one-pixel background margin and crops it back, so a shape thins identically whether or not it touches the frame. Applies to all seven methods (#F012).thin(method = "opta")now keeps two-pixel-wide strokes connected. The SPTA kernel evaluated all four contour directions against the pre-cycle snapshot and deleted them in one batch, so both sides of a 2px stroke were removed together and the skeleton fragmented (a 2×9 bar collapsed to its four corner pixels). Deletion is now sequential per direction, as Naccache & Shinghal's two-scan formulation requires (#F011).
Show all changes in 0.3.0Hide the rest of the changes in 0.3.0
distance_transform(metric = "manhattan" | "chessboard")now returnsInffor a fully-foreground image (no background pixel exists), matching the"euclidean"metric andEBImage::distmap(). The two-pass metrics previously seeded foreground with a finite sentinel that leaked out as a plausible-looking but meaningless finite distance (#F015).thin(),distance_transform(), andmedial_axis()now rejectNAinput with a clear error at the coercion boundary instead of silently turning it intoNA_integer_(INT_MIN) in the C++ kernels (#F016).thin(method = "hilditch")now thins junctions to the published parallel form. The look-ahead conditions 3 and 4 skip deleting a pixel only when a cardinal neighbour has crossing numberA == 1on the current image; the kernel had compared the look-ahead crossing number (computed with the centre already removed) against 1, which is strictly stronger and also spared junction neighbours whereA >= 2, leaving a redundant pixel beside the junction. Skeletons are now equal to or thinner than before, never thicker (verified against a reference implementation of the published form over random images) (#F014).- Added a connectivity-preservation property test across all seven methods and tightened the Holt straight-line test (#F013).
- Documented and pinned the isolated-2×2-block behaviour: the default
zhang_suenerases an isolated 2×2 block entirely whileguo_hallkeeps one pixel. Seevignette("choosing-a-method")for guidance on small-blob masks (#F017). - Removed
thinImage(). Usethin()(Zhang-Suen is the default method).
From NEWS.md in the release
Install
Health
- OK13 OK2026-08-04
- NOTE12 OK, 1 NOTE2026-08-01
- OK7 OK2026-05-28
Documentation
- Help pages
- 4 (1 internal)includes a package overview page
- Examples that run
- 100%3 run in a plain check
- Exported functions with examples
- 100%
- Documented parameters
- 100%
- Return-value docs
- 100%
- Help pages citing references
- 50%
Downloads
Repository
- PRs merged (all time)
- 93%
- Median days to close, 50 most recently updated closed issues
- 0
- Median days to close, 50 most recently updated closed PRs
- 0
Releases over time
Commits over time
8 development-tooling and community-health practices detected across 4 families in the upstream repository
Checks run against github.com/humanpred/thinr on 2026-10-21.
The R CMD check workflow runs on Linux, macOS and Windows, and on R-devel
GitHub Pages site last deployed 2026-08-22 · The repository has a site deploy workflow
pkgdown site last built 2026-08-22
This repository shows signs of AI coding tools.
- Claude Codefirst seen on or before 2026-05-16Seen in the repository: CLAUDE.mdNamed in .Rbuildignore: CLAUDE.mdNamed in .gitignore: .claudeCommits: at least 43 crediting it in the message
- Claude Opus 4.819 commits · Jun to Jul 2026
- Claude Opus 4.715 commits · May 2026
- Claude Fable 57 commits · Jul 2026
- Claude Opus 52 commits · Jul to Aug 2026
Dependencies
Installing thinr adds 1 package (1 with compiled code, 1.8 MB of source tarballs). Heaviest: Rcpp 1.8 MB.
Code & Tests
People & History
Pick two releases to compare their code metrics.
- 0.3.0Latest
- 0.2.02026-05-27
- RR 4.6.0 released · 2026-04-24
Package metadata
- First published
- 2026-05-27
- Total releases
- 2 / 1 yrs
- License
- LGPL-3 OSI
- Minimum R
- ≥ 4.2
- Download size
- 62 KB
Cite
Cite this package
Run in R for the authors' preferred citation:
citation("thinr")This package has no citation file, so citation() returns this entry built from DESCRIPTION.
Cite the R Observatory
For a number measured here: a download total, a coverage figure, an archival date.
From data release v2026-10-24, which the citation names so these numbers can be found later. More on citing and the projects behind them.