0

I have a set of 3D ROI label stacks stored as TIFF files, where each ROI represents a single cell. I want to generate surface meshes(I use trimesh) suitable for downstream shape analysis.

I tried marching cubes:

from skimage import measure import trimesh import numpy as np mask = labels == lab_id # binary mask for one ROI verts, faces, normals, values = measure.marching_cubes(mask.astype(np.float32), level=0.5) mesh = trimesh.Trimesh(vertices=verts, faces=faces) 

but Some meshes have missing surfaces, holes, or multiple disconnected “blobs. and Poisson surface reconstruction (Open3D) which didn't correctly capture the shapes.

I also tried

import trimesh coords = np.argwhere(mask) # N x 3 points pc = trimesh.points.PointCloud(coords) mesh = pc.convex_hull 

But Convex hull loses all concavities, making every cell look roughly the same.

What is the recommended way to generate a nice and smooth closed-contour mesh from a 3D ROI stack, preserving concavities and avoiding blobs or missing surfaces?

Are there specific parameters in either of the methods I tried that help produce more reliable meshes?

1
  • Are you saying that the mesh this finds is not a correct representation of the mask, or are you saying that the mask variable contains voids / cavities that you want to fill? An example of the incorrect input / output would help me quite a bit. Commented Nov 14 at 21:14

1 Answer 1

0

To triangulate a point cloud you can use Poisson surface reconstruction. It produces a smooth, watertight, closed-surface mesh that preserves concavities.

import numpy as np import open3d as o3d import trimesh # coords = np.argwhere(mask) # this is from your question: N x 3 point cloud # --- 1. Convert to Open3D point cloud --- pcd = o3d.geometry.PointCloud() pcd.points = o3d.utility.Vector3dVector(coords.astype(np.float32)) # --- 2. Estimate normals (required for Poisson) --- pcd.estimate_normals( search_param=o3d.geometry.KDTreeSearchParamHybrid( radius=4.0, # adjust based on cell size max_nn=60 ) ) pcd.orient_normals_consistent_tangent_plane(20) # --- 3. Poisson triangulation --- mesh, _ = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson( pcd, depth=8 # depth 7–10 is typical; higher = more detail, slower ) # --- 4. Convert to trimesh --- tri = trimesh.Trimesh( vertices=np.asarray(mesh.vertices), faces=np.asarray(mesh.triangles) ) 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.