navis-org / skeletor

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

Strange Results On ShapeNet Mesh #25

Open FishWoWater opened 2 years ago

FishWoWater commented 2 years ago

Hi! Thanks for your nice work!

I have some question when testing your algorithm on chair meshes from ShapeNet

I experiment with vertex cluster and edge collapse but neither of them works(what I expect is to extract four legs of the chair).

#!/usr/bin/env python
# coding=utf-8

import os, os.path as osp, shutil 
import networkx as nx
import trimesh
import skeletor as sk 
import glob 
import argparse 

parser = argparse.ArgumentParser()
parser.add_argument('--method', type=int, default=0)
args = parser.parse_args()

mesh_files = glob.glob("./samples/*.obj")
for mesh_file in mesh_files:
    try:
        mesh = trimesh.load(mesh_file)
        print('mesh loaded from', mesh_file)
        # mesh.show(mesh=True)
        # cc = nx.connected_components(mesh.vertex_adjacency_graph)
        # print(len(list(cc)), "connected components")

        fixed = sk.pre.fix_mesh(mesh, remove_disconnected=0, inplace=False)
        cc = nx.connected_components(fixed.vertex_adjacency_graph)
        print(len(list(cc)), "connected components after fixing")
        # fixed.show(mesh=True)
        # fast, work well for tubular meshes(e.g. neurons)
        if args.method == 0:
            print('wavefront')
            skel = sk.skeletonize.by_wavefront(fixed, waves=1, step_size=1)
            # fast but needs mesh to be contracted
        elif args.method == 1:
            print('contraction and by vertex cluster')
            fixed = sk.pre.contract()
            skel = sk.skeletonize.by_vertex_clusters(fixed, waves=1, step_size=1)
        else:
            skel = sk.skeletonize.by_edge_collapse(fixed)

        skel.show(mesh=True)
        shutil.copy(mesh_file, osp.join("./minisamples", osp.basename(mesh_file)))
    except:
        pass

Did I miss anything important or misunderstand the algorithm? Or is it caused by the bad mesh quality(e.g. non-manifold meshes from ShapeNet)?

Here are some screenshots and the samples along with the script can be found in the attachment.

image image

Appreciate for your help! Wish you a nice day :)

schlegelp commented 2 years ago

Hi. Stuff like this comes up fairly frequently (see eg. #13).

The gist is this:

  1. Disconnected meshes will produce disconnected skeletons (like for your second chair example).
  2. Somewhat counterintuitively the skeletonization often performs badly on primitives (e.g. stuff that's effectively made from rectangles).

What you could try is subdividing your mesh (i.e. increase the number of vertices it is made of).

I would have also suggested looking into mesh contraction + vertex clustering. Looks like your script caters for that combination but not sure about this line:

fixed = sk.pre.contract()
skel = sk.skeletonize.by_vertex_clusters(fixed, waves=1, step_size=1)

That should look something like this:

>>> fixed = sk.pre.contract(fixed, epsilon=0.1)
>>> skel = sk.skeletonize.by_vertex_clusters(fixed,
...                                          sampling_dist=1  # this needs to be adjusted depending on your object
...   )