medial_axis_points — 3D medial op

• Data kinds: voxel → points

• Call: import fullseye as fs; fs.ledger.medial_axis_points(vol, min_radius=0.0) (to call the implementation directly, import medial; medial.medial_axis_points(vol, min_radius=0.0); from the registry, ops3d.get("medial_axis_points"))

• Return value through the ledger: fullseye.ledger.medial_axis_points(...) returns only the declared out type points (the underlying function also returns auxiliary values). When you need what was dropped, use fullseye.ledger.medial_axis_points.raw(...) or call medial.medial_axis_points directly.

• Underlying return: (points, radii)

Usage

Turn the medial voxels into a point set with their local radius (= that point's EDT value). Returns (points, radius).

Returns the medial points, distributed as surfaces in thick parts and as lines in thin parts, as (M,3) coordinates (z,y,x) together with each one's local radius (M,). The point with the largest radius points to the "innermost" part of the shape = its centre.

Args:

vol: binary voxels (bool / 0-1 3D).

min_radius: exclude points with radius at or below this value (noise suppression).

Returns:

points (float64, (M,3)): medial voxel coordinates (z, y, x).

radius (float64, (M,)): EDT value of each point (= local inscribed radius).

Procedure: returns np.argwhere of the ridge_mask obtained from distance_ridge(vol, min_radius) (array indices; rows deterministic in z-major lexicographic order) and the edt values at those positions. Coordinates are voxel indices and spacing is not applied (if physical coordinates are needed, the caller computes points * (sz, sy, sx), and likewise multiplies the radius by the isotropic spacing).

Arguments and validation: vol is 3-D (non-zero = foreground). Not 3-D, empty, or NaN/Inf gives ValueError; min_radius < 0 is also ValueError. radius holds only the points with > min_radius (boundary voxels have EDT of 1 or less, so min_radius=1 drops almost all outer-shell noise).

Edge behaviour: if there is no foreground, or all points are at or below min_radius, points is (0, 3) and radius is (0,), both empty arrays (no error).

Where to use: radius distribution for medial_match, bridge to point-cloud ops (smallest_sphere3 / fit_line3 etc.), and np.argmax(radius) gives the centre of the largest inscribed sphere.

References (sample data, literature)

• Sample-data catalog (download URLs / licences) — 2-D uses skimage.data (BSD/public domain) plus synthetic images; 3-D lists download URLs for real data sources (Stanford, PDS, …).

• Operator provenance and references — the sources of the research/methods this op family came from.

Runnable examples (verified samples that actually call this op)

• medial_topology — py -3.11 examples_3d/medial_topology.py

Ops the type connects to (they accept points as input)

points_to_voxel · gaussians_to_voxel · estimate_point_normals · to_points · match_points_ncc · match_pca · moment_axes · icp_point2point_3d

Same category (medial)

distance_ridge · skeletonize_vol · topology_signature · medial_match · skeleton_junctions3d · skeleton_endpoints3d · skeleton_prune3d · skeleton_branches3d


*Provenance: medial.py — 3D operator registry. This per-op note is generated by tools/opdocs.py md (do not hand-edit).*

© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.