Unlike its namesake, this Python 3 library does not (yet) seek to conquer Eternia but to turn meshes into skeletons.
Heads-up: skeletor 1.0.0
introduced some breaking changes and major reorganizations.
Please see the changelog
for details.
pip3 install skeletor
For the dev version:
pip3 install git+https://github.com/navis-org/skeletor@master
Automatically installed with pip
:
networkx
numpy
pandas
scipy
scikit-learn
trimesh
tqdm
python-igraph
ncollpyde
Optional because not strictly required for the core functions but highly recommended:
- pyglet is required by trimesh to preview meshes/skeletons in 3D:
pip3 install pyglet
- fastremap for sizeable speed-ups with some methods:
pip3 install fastremap
Please see the documentation for details.
The change log can be found here.
For the impatient a quick example:
>>> import skeletor as sk
>>> mesh = sk.example_mesh()
>>> # To load and use your own mesh instead of the example mesh:
>>> # import trimesh as tm
>>> # mesh = tm.Trimesh(vertices, faces) # or...
>>> # mesh = tm.load_mesh('mesh.obj')
>>> fixed = sk.pre.fix_mesh(mesh, remove_disconnected=5, inplace=False)
>>> skel = sk.skeletonize.by_wavefront(fixed, waves=1, step_size=1)
>>> skel
<Skeleton(vertices=(1258, 3), edges=(1194, 2), method=wavefront)>
All skeletonization methods return a Skeleton
object. These are just
convenient objects to represent and inspect the results.
>>> # location of vertices (nodes)
>>> skel.vertices
array([[16744, 36720, 26407],
...,
[22076, 23217, 24472]])
>>> # child -> parent edges
>>> skel.edges
array([[ 64, 31],
...,
[1257, 1252]])
>>> # Mapping for mesh to skeleton vertex indices
>>> skel.mesh_map
array([ 157, 158, 1062, ..., 525, 474, 547])
>>> # SWC table
>>> skel.swc.head()
node_id parent_id x y z radius
0 0 -1 16744.005859 36720.058594 26407.902344 0.000000
1 1 -1 5602.751953 22266.756510 15799.991211 7.542587
2 2 -1 16442.666667 14999.978516 10887.916016 5.333333
>>> # Save SWC file
>>> skel.save_swc('skeleton.swc')
If you installed pyglet
(see above) you can also use trimesh
's plotting
capabilities to inspect the results:
>>> skel.show(mesh=True)
Benchmarks
were run on a 2018 MacBook Pro (2.2 GHz Core i7, 32Gb memory) with optional
fastremap
dependency installed. Note some of these functions (e.g.
contraction and TEASAR/vertex cluster skeletonization) can vary a lot in
speed based on parameterization.
Pull requests are always welcome!
Mesh contraction and the edge collapse approach are based on this paper:
[1] Au OK, Tai CL, Chu HK, Cohen-Or D, Lee TY. Skeleton extraction by mesh contraction. ACM Transactions on Graphics (TOG). 2008 Aug 1;27(3):44.
The abstract and the paper can be found here.
Also see this YouTube video.
Some of the code in skeletor was modified from the Py_BL_MeshSkeletonization addon for Blender 3D created by #0K Srinivasan Ramachandran and published under GPL3.
The mesh TEASAR approach was adapted from the implementation in meshparty by Sven Dorkenwald, Casey Schneider-Mizell and Forrest Collman.