Skip to content

Commit

Permalink
Add remove small parts filter
Browse files Browse the repository at this point in the history
  • Loading branch information
Shaokun-X committed May 2, 2021
1 parent 56668e8 commit eb8beb8
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ After all the image processing is finished, the volume is converted to a VTK ima
Then the following VTK pipeline is executed:
* [Extract a surface mesh](https://vtk.org/doc/nightly/html/classvtkContourFilter.html) from the VTK image
* Apply the [clean mesh filter](https://vtk.org/doc/nightly/html/classvtkCleanPolyData.html)
* [Remove small parts](https://vtk.org/doc/nightly/html/classvtkPolyDataConnectivityFilter.html) which connect to little other parts
* Apply the [smooth mesh filter](https://vtk.org/doc/nightly/html/classvtkSmoothPolyDataFilter.html)
* Apply the [reduce mesh filter](https://vtk.org/doc/nightly/html/classvtkQuadricDecimation.html)
* [Write out an STL file](https://vtk.org/doc/nightly/html/classvtkSTLWriter.html)
Expand Down
13 changes: 11 additions & 2 deletions dicom2stl.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,16 +326,25 @@ def elapsedTime(start_time):
mesh = vtkutils.extractSurface(vtkimg, isovalue)
vtkimg = None
gc.collect()

if args.debug:
print("Cleaning mesh")
mesh2 = vtkutils.cleanMesh(mesh, connectivityFilter)
mesh = None
gc.collect()

if args.debug:
print("Smoothing mesh", args.smooth, "iterations")
mesh3 = vtkutils.smoothMesh(mesh2, args.smooth)
print(f"Cleaning small parts ratio{args.small}")
mesh_cleaned_parts = vtkutils.removeSmallObjects(mesh2, args.small)
mesh2 = None
gc.collect()

if args.debug:
print("Smoothing mesh", args.smooth, "iterations")
mesh3 = vtkutils.smoothMesh(mesh_cleaned_parts, args.smooth)
mesh_cleaned_parts = None
gc.collect()

if args.debug:
print("Simplifying mesh")
mesh4 = vtkutils.reduceMesh(mesh3, args.reduce)
Expand Down
4 changes: 4 additions & 0 deletions parseargs.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ def parseargs():
type=float, default=.9,
help='Mesh reduction factor (default=.9)')

mesh_group.add_argument('--clean-small', '-x', action='store', dest='small',
type=float, default=.05,
help='Clean small parts factor (default=.05)')

# Filtering options
filter_group = parser.add_argument_group('Filtering options')
filter_group.add_argument('--enable', action='append', dest='filters',
Expand Down
48 changes: 48 additions & 0 deletions utils/vtkutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,54 @@ def reduceMesh(mymesh, reductionFactor):
traceback.print_exception(
exc_type, exc_value, exc_traceback, limit=2, file=sys.stdout)
return None


# from https://github.com/AOT-AG/DicomToMesh/blob/master/lib/src/meshRoutines.cpp#L109
# MIT License
def removeSmallObjects(mesh, ratio):
"""
Remove small parts which are not of interest
@param ratio A floating-point value between 0.0 and 1.0, the higher the stronger effect
"""

# do nothing if ratio is 0
if ratio == 0:
return mesh

try:
t = time.perf_counter()
conn_filter = vtk.vtkPolyDataConnectivityFilter()
conn_filter.SetInputData(mesh)
conn_filter.SetExtractionModeToAllRegions()
conn_filter.Update()

# remove objects consisting of less than ratio vertexes of the biggest object
region_sizes = conn_filter.GetRegionSizes()

# find object with most vertices
max_size = 0
for i in range(conn_filter.GetNumberOfExtractedRegions()):
if region_sizes.GetValue(i) > max_size:
max_size = region_sizes.GetValue(i)

# append regions of sizes over the threshold
conn_filter.SetExtractionModeToSpecifiedRegions()
for i in range(conn_filter.GetNumberOfExtractedRegions()):
if region_sizes.GetValue(i) > max_size * ratio:
conn_filter.AddSpecifiedRegion(i)

conn_filter.Update()
processed_mesh = conn_filter.GetOutput()
print("Small parts cleaned")
print(" ", processed_mesh.GetNumberOfPolys(), "polygons")
elapsedTime(t)
return processed_mesh

except BaseException:
print("Remove small objects failed")
exc_type, exc_value, exc_traceback = sys.exc_info()
traceback.print_exception(
exc_type, exc_value, exc_traceback, limit=2, file=sys.stdout)


#
Expand Down

0 comments on commit eb8beb8

Please sign in to comment.