navis-org / skeletor

Extraction of 3D skeletons from meshes.
https://navis-org.github.io/skeletor/
GNU General Public License v3.0
209 stars 26 forks source link

Plotting issues #41

Open koenterheegde0507 opened 6 months ago

koenterheegde0507 commented 6 months ago

Hi,

I'm having some issues with plotting the skeleton. I'm using python 3.9.7 and I've managed to get the skeleton from one of my own .STL files.

`mesh = tm.load_mesh(file_path) plotter = pv.Plotter() plotter.add_mesh(mesh) plotter.show()

fixed = sk.pre.fix_mesh(mesh, remove_disconnected=5, inplace=False)

skel = sk.skeletonize.by_wavefront(mesh, waves=1, step_size=1)

skel.show(mesh=True)`

This is the original mesh:

image

This is the result of the skeletonization:

image

I'm currently having the issues that under a lot of camera angles, the skeleton and mesh are not showing at all. I have to randomly turn the camera and hope they appear. The mesh is also not showing for 99%. I do get this warning from python: UserWarning: Could not set COM MTA mode. Unexpected behavior may occur. warnings.warn("Could not set COM MTA mode. Unexpected behavior may occur.") Is this related to my problem and is there a way to solve it?

schlegelp commented 6 months ago

Hi! Glad your skeleton seems to have turned out OK. Under the hood, skeletor is using trimesh for the visualization. It's a really thin wrapper: check out the .show() method - it boils down to 3 maybe 4 lines of code.

I can't quite tell from your example whether you are using pyvista or the built-in trimesh plotting - the code/screenshots seems to suggest a combination of both?

I don't think I can help you with pyvista unfortunately. For trimesh: I'm happy to investigate but not sure when I'll get to it. In the meantime you could consider opening an issue in trimesh. If you do, probably best to write a minimal code example independent of skeletor.

koenterheegde0507 commented 6 months ago

Thanks for the super quick reply! I'm currently plotting the original mesh in pyvista and then use your code to plot the skeleton and the mesh (but that doesn't work for me completely). I eventually want to click on the points of which the skeleton is made. Maybe instead of using skel.show(mesh=True) I could just save the skeleton and extract the points from it and then plot it in pyvista. This made me wonder if it's only possible to get the points in .swc format or also other formats like .txt?

schlegelp commented 6 months ago

In the end SWC files are just CSVs with a space as delimiter.

You can always get the points and save them yourself:

>>> import skeletor as sk
>>> mesh = sk.example_mesh()
>>> 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)>

>>> # Get the points as (N, 3) numpy array 
>>> skel.vertices
array([[ 3458.71940104, 21792.08268229, 15101.31347656],
       [ 3521.65361328, 21865.68359375, 15115.18046875],
       [ 3636.05541992, 21930.08447266, 15149.98095703],
       ...,
       [22080.08691406, 23342.10595703, 24558.125     ],
       [22037.41959635, 23518.77571615, 24649.29264323],
       [22076.88671875, 23217.7046875 , 24472.12304688]])
>>> # Get the corresponding (M, 2) edges 
>>> skel.edges
array([[   1,    0],
       [   2,    1],
       [   3,    5],
       ...,
       [1100, 1102],
       [1101, 1100],
       [1102, 1097]])
>>> # Get the SWC table as pandas DataFrame 
>>> skel.swc.head()
   node_id  parent_id            x             y             z     radius
0        0         -1  3458.719401  21792.082682  15101.313477  59.041832
1        1          0  3521.653613  21865.683594  15115.180469  89.220330
2        2          1  3636.055420  21930.084473  15149.980957  82.838492
3        3          5  3481.386393  20677.398437  16057.328125  82.052557
4        4          2  3726.056763  21988.085449  15177.981689  81.357745

Using the .swc DataFrame you can export the points to all the formats pandas supports.

koenterheegde0507 commented 6 months ago

Pfff, so stupid to forget this haha, thanks! I have managed to obtain the coordinates from the dataframe and plot them inside the mesh: image This does however look a bit different from the earlier picture i have shown, why would that be the case? Does skel.show() automatically interpolate between the points? I'm mainly worrying about the gaps at each bifurcation...

schlegelp commented 6 months ago

skel.show plots the edges, i.e. the lines between points. You need to use skel.vertices and skel.edges to generate a 3D line plot in pyvista.

koenterheegde0507 commented 6 months ago

skel.edges return the index of the vertices of the skeleton? So [ 64, 31] would mean an edge between vertex with index 64 and 31 in the skel.vertices array right?

schlegelp commented 6 months ago

Correct