pythonvtkrasterize3d-printingimage-slicer

How to label inner/outer of contour when slice/rasterize 3D objects to image stack?


For 3D printing, we slice the digital objects into image stacks in order to stack them layer by layer using a 3D printer. And when the slice is done, how to label the inner/outer to set the solid parts?

  1. The STL model:

enter image description here

  1. The Slices:

enter image description here

  1. Sample of one image stack (sliced):

enter image description here

but the need is to keep or label the inner/outer of contours, say the inner is black so the 3D printer will print it and skip the white outer. The goal is filled inner of contours as the following image:

enter image description here

Try 1

import pyvista as pv

mesh = pv.read('./haus.stl')
slices = mesh.slice_along_axis(n=20, axis='z', progress_bar=True) 

# show single slice with camera setting
slices[15].plot(cpos=[0, 1, 1], line_width=5, parallel_projection=True,)

# save slices (outcome is as step.3 image stack)
for i in range(20):
    p = pv.Plotter(off_screen=True)
    p.add_mesh(slices[i])
    p.camera_position = 'zy'
    p.enable_parallel_projection()
    im_name = "im_slice_" + str(i) + ".jpg"
    p.screenshot(im_name)


# Try voxelize (as ans from https://stackoverflow.com/questions/75300529)
voxels = pv.voxelize(mesh, density=mesh.length / 100)

# Try pv.Plane() (not test yet)
plane=pv.Plane()
plane.compute_implicit_distance(mesh, inplace=True)
np.sign(plane.point_data['implicit_distance'])
#i_resolution=?, j_resolution=?


# Try vtk (not test yet)
# https://stackoverflow.com/questions/68191368

voxelize model: enter image description here

voxelize sliced: enter image description here

but voxelize sliced doesn't seem very suitable. A very fine mesh needs to be built to restore the boundaries.

Try 2 VTK example

show STL:

enter image description here

Just add STL reader and Mapper:

filename = './haus.stl'
    
reader = vtkSTLReader()
reader.SetFileName(filename)
reader.Update()

stlMapper = vtk.vtkPolyDataMapper()
stlMapper.SetInputConnection(reader.GetOutputPort())
polydata = stlMapper
print("Get GetOrigin", polydata.GetCenter()) 
sphereSource = reader

slice result:

enter image description here

Try 2 is almost done with the job, but can not figure out the SetExtent/SetOrigin effect. The output image all fit to the contours' dimensions so each output image WXH is not identical.

Try 3 3D Silcer example

Only change some code as following:

inputModelFile = "./data/haus.stl"
outputDir = "./outputs/"
...
for i in range(80,140, 10):
  imageio.imwrite(f"{outputDir}/image_{i:03}.jpg", 255 - outputLabelmapVolumeArray[i]) # Inverting Colors

enter image description here

The result seems acceptable, but need future to revise some code to match the resolution, position, spacing, etc. So, is there a more lean and more efficient way to automate similar work?


Solution

  • You may want to try out the combination of vtkFeatureEdges, vtkStripper and vtkTriangleFilter, eg:

    from vedo import *
    msh = Mesh('https://vedo.embl.es/examples/data/cow.vtk')
    slices = []
    for z in np.arange(-.50, .50, .15):
        line = msh.clone().cut_with_plane(origin=(0,0,z), normal='z')
        cap = line.cap(True)
        slices.append(cap)
    show(slices, msh.alpha(0.1), axes=1)
    

    enter image description here

    In case you want to create a set of images or a tiff stack (instead of a polygonal mesh), you can do it with:

    from vedo import *
    
    surf = Mesh("https://vedo.embl.es/examples/data/cow.vtk")
    surf.compute_normals()
    
    # write a tiff stack
    vol = surf.binarize(spacing=(0.02, 0.02, 0.02))
    vol.alpha([0,0.6]).c('blue5')
    vol.write("image.tif")
    
    # write a numpy array and/or a set of png files
    arr = vol.tonumpy()
    pic = Picture(arr[:,:,55])
    pic.write("slice55.png")
    
    show(vol, pic, N=2, sharecam=False, axes=1)
    

    enter image description here

    Finally you can inspect the tiff file from command line:

    vedo --slicer3d image.tif
    

    enter image description here