Use threshold for the CT Segment and translate the labelmap to polydata

Hi, I’m using threshold for a CT’s bone surface, and using vtkDiscreteMarchingCubes to get the first polydata,but the data is too large,when I use vtkQuadricDecimation to reduce the number of cells, but there will have some holes and non manifold edges.
I have no idea how to solve the problem.
① should I smooth the CT before the threshold?
② how to reduce the number of cells without the holes or non manifold edges appear?
③ Is there parameters that I should set when using the vtkDiscreteMarchingCubes?

If you all that you ever need is segmenting with a threshold value then probably the best is to go with a contour filter, such as vtkFlyingEdges3D (not the discrete version).

Thresholding of noisy data always generates a very large, complex mesh that inevitably contains some oddly-shaped cells or other mesh errors. To reduce complexity and size of the mesh you can smooth and/or resample the image before the contour filter. You can use smooth polydata filter or windowed sinc filter to make the mesh a bit smoother and quadric decimation or ACVD universal remeshing to further reduce the mesh complexity.

The main limitation of this workflow would be that it assumes that segmentation can be accomplished by simple thresholding, which practically never happens in real clinical workflows. If you segment the image (e.g., using some AI models and maybe some manual/semi-automatic editing) then the output of the segmentation is a binary labelmap, which has completely different issues and different methods to deal with them.

Hi, I use windowed sinc filter to reduce the number of polydata, but there will come out holes and non manifold edges.
now in my flow, I prefer to use the binary labelmap for each segmentation. Can you give me some suggestions for the flow of generate polydata by labelmap?

I tried to use vtkDiscreteMarchingCubes by set the generatevalues(1,1,1), then the polydata can be boolean by cgal function.thank you for the suggestion((not the discrete version)).Today I will try the no discrete version.

Windowed sinc does not changes the topology of the mesh (change the number of points or introduce holes or non-manifold edges). If you find holes or non-manifold edges in the smoothing filter output then those were already present in the input.

Yes, I think it is a better approach than trying to segment an image using thresholding with a contour filter such as vtkFlyingEdges3D.

This is a complex topic, you can find discussions of it on this forum. Source code of 3D Slicer’s implementation is available here.

Boolean operations on meshes are very difficult to implement correctly. I would recommend to perform all Booelan operations in the binary labelmap representation, where it is a trivial operation.

Unlike VTK, CGAL is not free software. Make sure you are aware of licensing restrictions/costs before considering using it.

The non-discrete version is only better if you go from grayscale image to mesh. If you go through a binary labelmap representation then you can use the discrete versions of the contour filters.

Thank you. I will try your suggestion.

Boolean operations on meshes are very difficult to implement correctly. I would recommend to perform all Booelan operations in the binary labelmap representation, where it is a trivial operation

if just boolean the polydata from the CT genaration, the mask boolean is much better and fast. But when import other stls, will it be better to translate polydata to mask and use mask boolean, then trans the result mask to polydata?
I have two considerations: ① By transform the polydata to mask, there will be some accuracy loss, like a very thin plan polydata, when transformed to mask, may not occupy one voxel. ②When transform the result mask to polydata, there will be more accuracy loss.

To represent small details, sharp edges, thin walls, and reproduce sizes very accurately, you indeed need to use a sufficiently high resolution binary labelmap image. If the object is large then indeed the memory and computation requirements may limit what is the finest resolution you can use. If this resolution is not sufficient then combining surface meshes can be a better solution.

If you need to combine surface meshes using Boolean operations, you can try to use vtkbool library, which is free. It may be a bit less robust, but if you send meshes to the developer that causes trouble then usually he can help.

Thank you for your suggests. I will try to find some roboost open algorithm.
I think try to change the spacing of the volume(when change the polydata to mask) is not a good way to solve this problem, it will use more than 100G memory if I try to change the the spacing to (0.1,0.1,0.1).

At 0.1mm spacing, 100GB would mean a cube of 46 x 46 x 46 cm, which would be highly unusual in clinical applications. How would you 3D-print such a huge object? A more common size would be 15 x 15 x 15 cm, a labelmap at this size at 0.1mm spacing would require about 3.1GB memory. Even if you need additional memory space for processing and visualization, a computer with just 32GB memory could comortably handle such data sets.

If you needed 0.01mm precision then binary labelmap representation of a 15cm cube would require about 3TB. In this case you would definitely need to perform Boolean operations on meshes. However, such precision is not commonly needed for clinical applications, where the acceptable error is typically around 0.1 to 1.0mm.

So, overall, Boolean operations on meshes would be very useful, but most often avoidable when implementing clinical applications.

Hi, Andras, you said a labelmap at this size at 0.1mm spacing would require about 3.1GB memory, I want to know how to define such a data? Is it created by VTK? I tried using vtk_bit to make vtk Imagedata, but it cames out some errors.