def fill_holes(self, hole_size=10.0): print('filling holes') filling_filter = vtk.vtkFillHolesFilter() filling_filter.SetInputConnection(self.mesh.GetOutputPort()) filling_filter.SetHoleSize(hole_size) filling_filter.Update() self.mesh = filling_filter
def FillHoles(self, hole_size, inplace=True): """ Fill holes in a vtkInterface.PolyData or vtk.vtkPolyData object. Holes are identified by locating boundary edges, linking them together into loops, and then triangulating the resulting loops. Note that you can specify an approximate limit to the size of the hole that can be filled. Parameters ---------- hole_size : float Specifies the maximum hole size to fill. This is represented as a radius to the bounding circumsphere containing the hole. Note that this is an approximate area; the actual area cannot be computed without first triangulating the hole. inplace : bool, optional Updates mesh in-place while returning nothing. Returns ------- mesh : vtkInterface.PolyData Mesh with holes filled. None when inplace=True """ fill = vtk.vtkFillHolesFilter() fill.SetHoleSize(hole_size) fill.SetInputData(self) fill.Update() if inplace: self.OverwriteMesh(fill.GetOutput()) else: return PolyData(fill.GetOutput())
def make_mesh_watertight(self, hole_size=None, filename=None, write=True): """This method reads a ply mesh from an external file and converts it into a watertight mesh """ self.to_ply(filename="temp.ply") logger.info(f"Making the mesh read from {filename} watertight") reader = vtk.vtkPLYReader() if filename is None: filename = Path.cwd() / "output/temp.ply" reader.SetFileName(str(filename)) reader.Update() polydata = reader.GetOutput() fill = vtk.vtkFillHolesFilter() fill.SetInputData(polydata) hole_size = hole_size if hole_size else config.stl_from_point_cloud.watertight_mesh.hole_size if config.stl_from_point_cloud.watertight_mesh.hole_size else 1.0 fill.SetHoleSize(hole_size) fill.Update() self.vtk_filled = fill.GetOutput() if write: writer = vtk.vtkPLYWriter() writer.SetInputData(self.vtk_filled) writer.SetFileName(f"temp-watertight.ply") writer.Write() self.stl_mesh = o3d.io.read_triangle_mesh("temp-watertight.ply") print(self.stl_mesh) # Path.unlink(Path("temp-watertight.ply")) # Path.unlink(filename) return fill.GetOutput()
def fillholes(polydata,size): filler = vtk.vtkFillHolesFilter() filler.SetInputData(polydata) filler.SetHoleSize(size) filler.Update() return filler.GetOutput()
def fillholes(surface, holesize=1000): """Fill holes in surface. Use holesize to specify the max 'radius' of the holes to be filled.""" filler = vtk.vtkFillHolesFilter() filler.SetInput(surface) filler.SetHoleSize(holesize) filler.Update() return filler.GetOutput()
def FillSurfaceHole(polydata): """ Fill holes in the given polydata. """ # Filter used to detect and fill holes. Only fill print "Filling polydata" filled_polydata = vtk.vtkFillHolesFilter() filled_polydata.SetInputData(polydata) filled_polydata.SetHoleSize(500) return filled_polydata.GetOutput()
def refineBreastPolyData(self, polyData, holeSize): holeFiller = vtk.vtkFillHolesFilter() holeFiller.SetInputData(polyData) holeFiller.SetHoleSize(holeSize) holeFiller.Update() normalFilter = vtk.vtkPolyDataNormals() normalFilter.SetInputConnection(holeFiller.GetOutputPort()) normalFilter.ComputePointNormalsOn() normalFilter.SplittingOff() normalFilter.Update() return normalFilter.GetOutput()
def fillHoles(actor, size=None, legend=None): # not tested properly fh = vtk.vtkFillHolesFilter() if not size: mb = maxBoundSize(actor) size = mb / 20 fh.SetHoleSize(size) poly = polydata(actor) setInput(fh, poly) fh.Update() fpoly = fh.GetOutput() factor = makeActor(fpoly, legend=legend) factor.SetProperty(actor.GetProperty()) return factor
def fillHoles(inputModel, outputModel, maximumHoleSize=1000.0): """Fills up a hole in a open mesh. """ fill = vtk.vtkFillHolesFilter() fill.SetInputData(inputModel.GetPolyData()) fill.SetHoleSize(maximumHoleSize) # Need to auto-orient normals, otherwise holes could appear to be unfilled when # only front-facing elements are chosen to be visible. normals = vtk.vtkPolyDataNormals() normals.SetInputConnection(fill.GetOutputPort()) normals.SetAutoOrientNormals(True) normals.Update() outputModel.SetAndObservePolyData(normals.GetOutput())
def wrapOpImp(self): fill = vtk.vtkFillHolesFilter(); fill.SetInputData(self.data); fill.Update() """ consistenNormal = vtk.vtkPolyDataNormals(); consistenNormal.ConsistencyOn(); consistenNormal.SplittingOff(); consistenNormal.SetInputConnection(fill.GetOutputPort()); consistenNormal.Update(); output = consistenNormal.GetOutput(); output.GetPointData().SetNormals(self.data.GetPointData().GetNormals()); """ output = fill.GetOutput(); return output;
def fill_hole(poly, size=10000000.): """ Fill holes in VTK PolyData Args: poly: VTK PolyData to fill size: max size of the hole to fill Returns: poly: filled VTK PolyData """ filler = vtk.vtkFillHolesFilter() filler.SetInputData(poly) filler.SetHoleSize(size) filler.Update() return filler.GetOutput()
def _build_vtkcontours(self): # fill holes filledHoles = vtk.vtkFillHolesFilter() filledHoles.SetInputData(self._mesh.vtk_obj) filledHoles.SetHoleSize(1000) filledHoles.Update() filledHolesOutput = filledHoles.GetOutput() # first generate normals self._normals = vtk.vtkPolyDataNormals() self._normals.SetInputData(filledHolesOutput) self._normals.Update() cut_meshes = dict() for d in self._axes: """ :TODO: parallelise """ # the configure the cutter self._cutter = vtk.vtkCutter() self._cutter.SetInputConnection(self._normals.GetOutputPort()) self._cutter.SetCutFunction(self.__getattribute__('%s_plane' % d)) # determine the number of z-contours to generate from the bounds d_max = math.floor(self.__getattribute__('%smax' % d.upper())) d_count = int(2 * d_max + 1) # generate the cuts on the mesh self._cutter.GenerateValues(d_count, -d_max, d_max) # pass through vtk.vtkStripper to ensure we have triangel strips self._stripper = vtk.vtkStripper() self._stripper.SetInputConnection(self._cutter.GetOutputPort()) self._stripper.Update() # the actual cuts colour = self._mesh.colour args = self._mesh.vtk_args cut_meshes[d] = VTKMesh(colour, args) stripper_output = self._stripper.GetOutput() cut_meshes[d].vtk_obj.SetPoints(stripper_output.GetPoints()) cut_meshes[d].vtk_obj.SetPolys(stripper_output.GetLines()) return cut_meshes
#fill_holes.SetInputConnection(subdivide.GetOutputPort()) #fill_holes.SetHoleSize(1000.0); #fill_holes.Update() triangle = vtk.vtkTriangleFilter() triangle.SetInputConnection(subdivide.GetOutputPort()) triangle.PassLinesOff() triangle.PassVertsOff() triangle.Update() if (vmtk_avail): #creates round outlet region caps capper = vtkvmtk.vtkvmtkSmoothCapPolyData() capper.SetInputConnection(triangle.GetOutputPort()) capper.SetConstraintFactor(1.0) capper.SetNumberOfRings(8) else: capper = vtk.vtkFillHolesFilter() capper.SetInputConnection(triangle.GetOutputPort()) capper.SetHoleSize(1000.0) cleaner = vtk.vtkCleanPolyData() cleaner.SetInputConnection(capper.GetOutputPort()) cleaner.Update() n_cells = cleaner.GetOutput().GetNumberOfCells() print("surface cells", n_cells) # Setup the colors array colors = vtk.vtkIntArray() colors.SetNumberOfComponents(1) colors.SetNumberOfValues(n_cells) colors.SetName("RegionId")
cellId = i - 1 + yRes * (j - 1) if (cellId != 48 and cellId != 12 and cellId != 13 and cellId != 23 and cellId != 60 and cellId != 83 and cellId != 72 and cellId != 76 and cellId != 77 and cellId != 78 and cellId != 87): polys.InsertNextCell(4) polys.InsertCellPoint(i - 1 + ((j - 1) * yPtsRes)) polys.InsertCellPoint(i + ((j - 1) * yPtsRes)) polys.InsertCellPoint(i + (j * yPtsRes)) polys.InsertCellPoint(i - 1 + (j * yPtsRes)) pass i += 1 j += 1 # Fill the holes fill = vtk.vtkFillHolesFilter() fill.SetInputData(pd) fill.SetHoleSize(20.0) # Mapping and actor map = vtk.vtkPolyDataMapper() # map SetInput pd map.SetInputConnection(fill.GetOutputPort()) actor = vtk.vtkActor() actor.SetMapper(map) actor.GetProperty().SetColor(1, 0, 0) # Add the actors to the renderer, set the background and size # ren1.AddActor(actor)
def join_process_surface(filenames, algorithm, smooth_iterations, smooth_relaxation_factor, decimate_reduction, keep_largest, fill_holes, options, msg_queue): def send_message(msg): try: msg_queue.put_nowait(msg) except queue.Full as e: print(e) send_message('Joining surfaces ...') polydata_append = vtk.vtkAppendPolyData() for f in filenames: reader = vtk.vtkXMLPolyDataReader() reader.SetFileName(f) reader.Update() polydata = reader.GetOutput() polydata_append.AddInputData(polydata) del reader del polydata polydata_append.Update() # polydata_append.GetOutput().ReleaseDataFlagOn() polydata = polydata_append.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del polydata_append send_message('Cleaning surface ...') clean = vtk.vtkCleanPolyData() # clean.ReleaseDataFlagOn() # clean.GetOutput().ReleaseDataFlagOn() clean_ref = weakref.ref(clean) # clean_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(clean_ref(), _("Creating 3D surface..."))) clean.SetInputData(polydata) clean.PointMergingOn() clean.Update() del polydata polydata = clean.GetOutput() # polydata.SetSource(None) del clean if algorithm == 'ca_smoothing': send_message('Calculating normals ...') normals = vtk.vtkPolyDataNormals() normals_ref = weakref.ref(normals) # normals_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(normals_ref(), _("Creating 3D surface..."))) normals.SetInputData(polydata) # normals.ReleaseDataFlagOn() #normals.SetFeatureAngle(80) #normals.AutoOrientNormalsOn() normals.ComputeCellNormalsOn() # normals.GetOutput().ReleaseDataFlagOn() normals.Update() del polydata polydata = normals.GetOutput() # polydata.SetSource(None) del normals clean = vtk.vtkCleanPolyData() # clean.ReleaseDataFlagOn() # clean.GetOutput().ReleaseDataFlagOn() clean_ref = weakref.ref(clean) # clean_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(clean_ref(), _("Creating 3D surface..."))) clean.SetInputData(polydata) clean.PointMergingOn() clean.Update() del polydata polydata = clean.GetOutput() # polydata.SetSource(None) del clean # try: # polydata.BuildLinks() # except TypeError: # polydata.BuildLinks(0) # polydata = ca_smoothing.ca_smoothing(polydata, options['angle'], # options['max distance'], # options['min weight'], # options['steps']) send_message('Context Aware smoothing ...') mesh = cy_mesh.Mesh(polydata) cy_mesh.ca_smoothing(mesh, options['angle'], options['max distance'], options['min weight'], options['steps']) # polydata = mesh.to_vtk() # polydata.SetSource(None) # polydata.DebugOn() else: #smoother = vtk.vtkWindowedSincPolyDataFilter() send_message('Smoothing ...') smoother = vtk.vtkSmoothPolyDataFilter() smoother_ref = weakref.ref(smoother) # smoother_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(smoother_ref(), _("Creating 3D surface..."))) smoother.SetInputData(polydata) smoother.SetNumberOfIterations(smooth_iterations) smoother.SetRelaxationFactor(smooth_relaxation_factor) smoother.SetFeatureAngle(80) #smoother.SetEdgeAngle(90.0) #smoother.SetPassBand(0.1) smoother.BoundarySmoothingOn() smoother.FeatureEdgeSmoothingOn() #smoother.NormalizeCoordinatesOn() #smoother.NonManifoldSmoothingOn() # smoother.ReleaseDataFlagOn() # smoother.GetOutput().ReleaseDataFlagOn() smoother.Update() del polydata polydata = smoother.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del smoother if decimate_reduction: print("Decimating", decimate_reduction) send_message('Decimating ...') decimation = vtk.vtkQuadricDecimation() # decimation.ReleaseDataFlagOn() decimation.SetInputData(polydata) decimation.SetTargetReduction(decimate_reduction) decimation_ref = weakref.ref(decimation) # decimation_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(decimation_ref(), _("Creating 3D surface..."))) #decimation.PreserveTopologyOn() #decimation.SplittingOff() #decimation.BoundaryVertexDeletionOff() # decimation.GetOutput().ReleaseDataFlagOn() decimation.Update() del polydata polydata = decimation.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del decimation #to_measure.Register(None) # to_measure.SetSource(None) if keep_largest: send_message('Finding the largest ...') conn = vtk.vtkPolyDataConnectivityFilter() conn.SetInputData(polydata) conn.SetExtractionModeToLargestRegion() conn_ref = weakref.ref(conn) # conn_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(conn_ref(), _("Creating 3D surface..."))) conn.Update() # conn.GetOutput().ReleaseDataFlagOn() del polydata polydata = conn.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del conn #Filter used to detect and fill holes. Only fill boundary edges holes. #TODO: Hey! This piece of code is the same from #polydata_utils.FillSurfaceHole, we need to review this. if fill_holes: send_message('Filling holes ...') filled_polydata = vtk.vtkFillHolesFilter() # filled_polydata.ReleaseDataFlagOn() filled_polydata.SetInputData(polydata) filled_polydata.SetHoleSize(300) filled_polydata_ref = weakref.ref(filled_polydata) # filled_polydata_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(filled_polydata_ref(), _("Creating 3D surface..."))) filled_polydata.Update() # filled_polydata.GetOutput().ReleaseDataFlagOn() del polydata polydata = filled_polydata.GetOutput() #polydata.Register(None) # polydata.SetSource(None) # polydata.DebugOn() del filled_polydata to_measure = polydata normals = vtk.vtkPolyDataNormals() # normals.ReleaseDataFlagOn() # normals_ref = weakref.ref(normals) # normals_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(normals_ref(), _("Creating 3D surface..."))) normals.SetInputData(polydata) # normals.SetFeatureAngle(80) # normals.SplittingOff() # normals.AutoOrientNormalsOn() # normals.GetOutput().ReleaseDataFlagOn() normals.Update() del polydata polydata = normals.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del normals # Improve performance stripper = vtk.vtkStripper() # stripper.ReleaseDataFlagOn() # stripper_ref = weakref.ref(stripper) # stripper_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(stripper_ref(), _("Creating 3D surface..."))) stripper.SetInputData(polydata) stripper.PassThroughCellIdsOn() stripper.PassThroughPointIdsOn() # stripper.GetOutput().ReleaseDataFlagOn() stripper.Update() del polydata polydata = stripper.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del stripper send_message('Calculating area and volume ...') measured_polydata = vtk.vtkMassProperties() measured_polydata.SetInputData(to_measure) measured_polydata.Update() volume = float(measured_polydata.GetVolume()) area = float(measured_polydata.GetSurfaceArea()) del measured_polydata filename = tempfile.mktemp(suffix='_full.vtp') writer = vtk.vtkXMLPolyDataWriter() writer.SetInputData(polydata) writer.SetFileName(filename) writer.Write() del writer print("MY PID", os.getpid()) return filename, {'volume': volume, 'area': area}
def AddNewActor(self, slice_, mask, surface_parameters): """ Create surface actor, save into project and send it to viewer. """ matrix = slice_.matrix filename_img = slice_.matrix_filename spacing = slice_.spacing algorithm = surface_parameters['method']['algorithm'] options = surface_parameters['method']['options'] surface_name = surface_parameters['options']['name'] quality = surface_parameters['options']['quality'] fill_holes = surface_parameters['options']['fill'] keep_largest = surface_parameters['options']['keep_largest'] mode = 'CONTOUR' # 'GRAYSCALE' min_value, max_value = mask.threshold_range colour = mask.colour[:3] try: overwrite = surface_parameters['options']['overwrite'] except KeyError: overwrite = False mask.matrix.flush() if quality in const.SURFACE_QUALITY.keys(): imagedata_resolution = const.SURFACE_QUALITY[quality][0] smooth_iterations = const.SURFACE_QUALITY[quality][1] smooth_relaxation_factor = const.SURFACE_QUALITY[quality][2] decimate_reduction = const.SURFACE_QUALITY[quality][3] #if imagedata_resolution: #imagedata = iu.ResampleImage3D(imagedata, imagedata_resolution) pipeline_size = 4 if decimate_reduction: pipeline_size += 1 if (smooth_iterations and smooth_relaxation_factor): pipeline_size += 1 if fill_holes: pipeline_size += 1 if keep_largest: pipeline_size += 1 ## Update progress value in GUI UpdateProgress = vu.ShowProgress(pipeline_size) UpdateProgress(0, _("Creating 3D surface...")) language = ses.Session().language if (prj.Project().original_orientation == const.CORONAL): flip_image = False else: flip_image = True n_processors = multiprocessing.cpu_count() pipe_in, pipe_out = multiprocessing.Pipe() o_piece = 1 piece_size = 2000 n_pieces = int(round(matrix.shape[0] / piece_size + 0.5, 0)) q_in = multiprocessing.Queue() q_out = multiprocessing.Queue() p = [] for i in range(n_processors): sp = surface_process.SurfaceProcess( pipe_in, filename_img, matrix.shape, matrix.dtype, mask.temp_file, mask.matrix.shape, mask.matrix.dtype, spacing, mode, min_value, max_value, decimate_reduction, smooth_relaxation_factor, smooth_iterations, language, flip_image, q_in, q_out, algorithm != 'Default', algorithm, imagedata_resolution) p.append(sp) sp.start() for i in range(n_pieces): init = i * piece_size end = init + piece_size + o_piece roi = slice(init, end) q_in.put(roi) print("new_piece", roi) for i in p: q_in.put(None) none_count = 1 while 1: msg = pipe_out.recv() if (msg is None): none_count += 1 else: UpdateProgress(msg[0] / (n_pieces * pipeline_size), msg[1]) if none_count > n_pieces: break polydata_append = vtk.vtkAppendPolyData() # polydata_append.ReleaseDataFlagOn() t = n_pieces while t: filename_polydata = q_out.get() reader = vtk.vtkXMLPolyDataReader() reader.SetFileName(filename_polydata) # reader.ReleaseDataFlagOn() reader.Update() # reader.GetOutput().ReleaseDataFlagOn() polydata = reader.GetOutput() # polydata.SetSource(None) polydata_append.AddInputData(polydata) del reader del polydata t -= 1 polydata_append.Update() # polydata_append.GetOutput().ReleaseDataFlagOn() polydata = polydata_append.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del polydata_append if algorithm == 'ca_smoothing': normals = vtk.vtkPolyDataNormals() normals_ref = weakref.ref(normals) normals_ref().AddObserver( "ProgressEvent", lambda obj, evt: UpdateProgress( normals_ref(), _("Creating 3D surface..."))) normals.SetInputData(polydata) # normals.ReleaseDataFlagOn() #normals.SetFeatureAngle(80) #normals.AutoOrientNormalsOn() normals.ComputeCellNormalsOn() # normals.GetOutput().ReleaseDataFlagOn() normals.Update() del polydata polydata = normals.GetOutput() # polydata.SetSource(None) del normals clean = vtk.vtkCleanPolyData() # clean.ReleaseDataFlagOn() # clean.GetOutput().ReleaseDataFlagOn() clean_ref = weakref.ref(clean) clean_ref().AddObserver( "ProgressEvent", lambda obj, evt: UpdateProgress( clean_ref(), _("Creating 3D surface..."))) clean.SetInputData(polydata) clean.PointMergingOn() clean.Update() del polydata polydata = clean.GetOutput() # polydata.SetSource(None) del clean # try: # polydata.BuildLinks() # except TypeError: # polydata.BuildLinks(0) # polydata = ca_smoothing.ca_smoothing(polydata, options['angle'], # options['max distance'], # options['min weight'], # options['steps']) mesh = cy_mesh.Mesh(polydata) cy_mesh.ca_smoothing(mesh, options['angle'], options['max distance'], options['min weight'], options['steps']) # polydata = mesh.to_vtk() # polydata.SetSource(None) # polydata.DebugOn() else: #smoother = vtk.vtkWindowedSincPolyDataFilter() smoother = vtk.vtkSmoothPolyDataFilter() smoother_ref = weakref.ref(smoother) smoother_ref().AddObserver( "ProgressEvent", lambda obj, evt: UpdateProgress( smoother_ref(), _("Creating 3D surface..."))) smoother.SetInputData(polydata) smoother.SetNumberOfIterations(smooth_iterations) smoother.SetRelaxationFactor(smooth_relaxation_factor) smoother.SetFeatureAngle(80) #smoother.SetEdgeAngle(90.0) #smoother.SetPassBand(0.1) smoother.BoundarySmoothingOn() smoother.FeatureEdgeSmoothingOn() #smoother.NormalizeCoordinatesOn() #smoother.NonManifoldSmoothingOn() # smoother.ReleaseDataFlagOn() # smoother.GetOutput().ReleaseDataFlagOn() smoother.Update() del polydata polydata = smoother.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del smoother if decimate_reduction: print("Decimating", decimate_reduction) decimation = vtk.vtkQuadricDecimation() # decimation.ReleaseDataFlagOn() decimation.SetInputData(polydata) decimation.SetTargetReduction(decimate_reduction) decimation_ref = weakref.ref(decimation) decimation_ref().AddObserver( "ProgressEvent", lambda obj, evt: UpdateProgress( decimation_ref(), _("Creating 3D surface..."))) #decimation.PreserveTopologyOn() #decimation.SplittingOff() #decimation.BoundaryVertexDeletionOff() # decimation.GetOutput().ReleaseDataFlagOn() decimation.Update() del polydata polydata = decimation.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del decimation #to_measure.Register(None) # to_measure.SetSource(None) if keep_largest: conn = vtk.vtkPolyDataConnectivityFilter() conn.SetInputData(polydata) conn.SetExtractionModeToLargestRegion() conn_ref = weakref.ref(conn) conn_ref().AddObserver( "ProgressEvent", lambda obj, evt: UpdateProgress( conn_ref(), _("Creating 3D surface..."))) conn.Update() # conn.GetOutput().ReleaseDataFlagOn() del polydata polydata = conn.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del conn #Filter used to detect and fill holes. Only fill boundary edges holes. #TODO: Hey! This piece of code is the same from #polydata_utils.FillSurfaceHole, we need to review this. if fill_holes: filled_polydata = vtk.vtkFillHolesFilter() # filled_polydata.ReleaseDataFlagOn() filled_polydata.SetInputData(polydata) filled_polydata.SetHoleSize(300) filled_polydata_ref = weakref.ref(filled_polydata) filled_polydata_ref().AddObserver( "ProgressEvent", lambda obj, evt: UpdateProgress( filled_polydata_ref(), _("Creating 3D surface..."))) filled_polydata.Update() # filled_polydata.GetOutput().ReleaseDataFlagOn() del polydata polydata = filled_polydata.GetOutput() #polydata.Register(None) # polydata.SetSource(None) # polydata.DebugOn() del filled_polydata to_measure = polydata # If InVesalius is running without GUI if wx.GetApp() is None: proj = prj.Project() #Create Surface instance if overwrite: surface = Surface(index=self.last_surface_index) proj.ChangeSurface(surface) else: surface = Surface(name=surface_name) index = proj.AddSurface(surface) surface.index = index self.last_surface_index = index surface.colour = colour surface.polydata = polydata # With GUI else: normals = vtk.vtkPolyDataNormals() # normals.ReleaseDataFlagOn() normals_ref = weakref.ref(normals) normals_ref().AddObserver( "ProgressEvent", lambda obj, evt: UpdateProgress( normals_ref(), _("Creating 3D surface..."))) normals.SetInputData(polydata) normals.SetFeatureAngle(80) normals.AutoOrientNormalsOn() # normals.GetOutput().ReleaseDataFlagOn() normals.Update() del polydata polydata = normals.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del normals # Improve performance stripper = vtk.vtkStripper() # stripper.ReleaseDataFlagOn() stripper_ref = weakref.ref(stripper) stripper_ref().AddObserver( "ProgressEvent", lambda obj, evt: UpdateProgress( stripper_ref(), _("Creating 3D surface..."))) stripper.SetInputData(polydata) stripper.PassThroughCellIdsOn() stripper.PassThroughPointIdsOn() # stripper.GetOutput().ReleaseDataFlagOn() stripper.Update() del polydata polydata = stripper.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del stripper # Map polygonal data (vtkPolyData) to graphics primitives. mapper = vtk.vtkPolyDataMapper() mapper.SetInputData(polydata) mapper.ScalarVisibilityOff() # mapper.ReleaseDataFlagOn() mapper.ImmediateModeRenderingOn() # improve performance # Represent an object (geometry & properties) in the rendered scene actor = vtk.vtkActor() actor.SetMapper(mapper) del mapper #Create Surface instance if overwrite: surface = Surface(index=self.last_surface_index) else: surface = Surface(name=surface_name) surface.colour = colour surface.polydata = polydata del polydata # Set actor colour and transparency actor.GetProperty().SetColor(colour) actor.GetProperty().SetOpacity(1 - surface.transparency) prop = actor.GetProperty() interpolation = int(ses.Session().surface_interpolation) prop.SetInterpolation(interpolation) proj = prj.Project() if overwrite: proj.ChangeSurface(surface) else: index = proj.AddSurface(surface) surface.index = index self.last_surface_index = index session = ses.Session() session.ChangeProject() measured_polydata = vtk.vtkMassProperties() # measured_polydata.ReleaseDataFlagOn() measured_polydata.SetInputData(to_measure) volume = float(measured_polydata.GetVolume()) area = float(measured_polydata.GetSurfaceArea()) surface.volume = volume surface.area = area self.last_surface_index = surface.index del measured_polydata del to_measure Publisher.sendMessage('Load surface actor into viewer', actor=actor) # Send actor by pubsub to viewer's render if overwrite and self.actors_dict.keys(): old_actor = self.actors_dict[self.last_surface_index] Publisher.sendMessage('Remove surface actor from viewer', actor=old_actor) # Save actor for future management tasks self.actors_dict[surface.index] = actor Publisher.sendMessage('Update surface info in GUI', surface=surface) #When you finalize the progress. The bar is cleaned. UpdateProgress = vu.ShowProgress(1) UpdateProgress(0, _("Ready")) Publisher.sendMessage('Update status text in GUI', label=_("Ready")) Publisher.sendMessage('End busy cursor') del actor
def AddNewActor(self, pubsub_evt): """ Create surface actor, save into project and send it to viewer. """ slice_, mask, surface_parameters = pubsub_evt.data matrix = slice_.matrix filename_img = slice_.matrix_filename spacing = slice_.spacing algorithm = surface_parameters['method']['algorithm'] options = surface_parameters['method']['options'] surface_name = surface_parameters['options']['name'] quality = surface_parameters['options']['quality'] fill_holes = surface_parameters['options']['fill'] keep_largest = surface_parameters['options']['keep_largest'] mode = 'CONTOUR' # 'GRAYSCALE' min_value, max_value = mask.threshold_range colour = mask.colour try: overwrite = surface_parameters['options']['overwrite'] except KeyError: overwrite = False mask.matrix.flush() if quality in const.SURFACE_QUALITY.keys(): imagedata_resolution = const.SURFACE_QUALITY[quality][0] smooth_iterations = const.SURFACE_QUALITY[quality][1] smooth_relaxation_factor = const.SURFACE_QUALITY[quality][2] decimate_reduction = const.SURFACE_QUALITY[quality][3] #if imagedata_resolution: #imagedata = iu.ResampleImage3D(imagedata, imagedata_resolution) pipeline_size = 4 if decimate_reduction: pipeline_size += 1 if (smooth_iterations and smooth_relaxation_factor): pipeline_size += 1 if fill_holes: pipeline_size += 1 if keep_largest: pipeline_size += 1 ## Update progress value in GUI UpdateProgress = vu.ShowProgress(pipeline_size) UpdateProgress(0, _("Creating 3D surface...")) language = ses.Session().language if (prj.Project().original_orientation == const.CORONAL): flip_image = False else: flip_image = True n_processors = multiprocessing.cpu_count() pipe_in, pipe_out = multiprocessing.Pipe() o_piece = 1 piece_size = 2000 n_pieces = int(round(matrix.shape[0] / piece_size + 0.5, 0)) q_in = multiprocessing.Queue() q_out = multiprocessing.Queue() p = [] for i in xrange(n_processors): sp = surface_process.SurfaceProcess(pipe_in, filename_img, matrix.shape, matrix.dtype, mask.temp_file, mask.matrix.shape, mask.matrix.dtype, spacing, mode, min_value, max_value, decimate_reduction, smooth_relaxation_factor, smooth_iterations, language, flip_image, q_in, q_out, algorithm != 'Default', algorithm, imagedata_resolution) p.append(sp) sp.start() for i in xrange(n_pieces): init = i * piece_size end = init + piece_size + o_piece roi = slice(init, end) q_in.put(roi) print "new_piece", roi for i in p: q_in.put(None) none_count = 1 while 1: msg = pipe_out.recv() if(msg is None): none_count += 1 else: UpdateProgress(msg[0]/(n_pieces * pipeline_size), msg[1]) if none_count > n_pieces: break polydata_append = vtk.vtkAppendPolyData() polydata_append.ReleaseDataFlagOn() t = n_pieces while t: filename_polydata = q_out.get() reader = vtk.vtkXMLPolyDataReader() reader.SetFileName(filename_polydata) reader.ReleaseDataFlagOn() reader.Update() reader.GetOutput().ReleaseDataFlagOn() polydata = reader.GetOutput() polydata.SetSource(None) polydata_append.AddInput(polydata) del reader del polydata t -= 1 polydata_append.Update() polydata_append.GetOutput().ReleaseDataFlagOn() polydata = polydata_append.GetOutput() #polydata.Register(None) polydata.SetSource(None) del polydata_append if algorithm == 'ca_smoothing': normals = vtk.vtkPolyDataNormals() normals_ref = weakref.ref(normals) normals_ref().AddObserver("ProgressEvent", lambda obj,evt: UpdateProgress(normals_ref(), _("Creating 3D surface..."))) normals.SetInput(polydata) normals.ReleaseDataFlagOn() #normals.SetFeatureAngle(80) #normals.AutoOrientNormalsOn() normals.ComputeCellNormalsOn() normals.GetOutput().ReleaseDataFlagOn() normals.Update() del polydata polydata = normals.GetOutput() polydata.SetSource(None) del normals clean = vtk.vtkCleanPolyData() clean.ReleaseDataFlagOn() clean.GetOutput().ReleaseDataFlagOn() clean_ref = weakref.ref(clean) clean_ref().AddObserver("ProgressEvent", lambda obj,evt: UpdateProgress(clean_ref(), _("Creating 3D surface..."))) clean.SetInput(polydata) clean.PointMergingOn() clean.Update() del polydata polydata = clean.GetOutput() polydata.SetSource(None) del clean try: polydata.BuildLinks() except TypeError: polydata.BuildLinks(0) polydata = ca_smoothing.ca_smoothing(polydata, options['angle'], options['max distance'], options['min weight'], options['steps']) polydata.SetSource(None) polydata.DebugOn() else: #smoother = vtk.vtkWindowedSincPolyDataFilter() smoother = vtk.vtkSmoothPolyDataFilter() smoother_ref = weakref.ref(smoother) smoother_ref().AddObserver("ProgressEvent", lambda obj,evt: UpdateProgress(smoother_ref(), _("Creating 3D surface..."))) smoother.SetInput(polydata) smoother.SetNumberOfIterations(smooth_iterations) smoother.SetRelaxationFactor(smooth_relaxation_factor) smoother.SetFeatureAngle(80) #smoother.SetEdgeAngle(90.0) #smoother.SetPassBand(0.1) smoother.BoundarySmoothingOn() smoother.FeatureEdgeSmoothingOn() #smoother.NormalizeCoordinatesOn() #smoother.NonManifoldSmoothingOn() smoother.ReleaseDataFlagOn() smoother.GetOutput().ReleaseDataFlagOn() smoother.Update() del polydata polydata = smoother.GetOutput() #polydata.Register(None) polydata.SetSource(None) del smoother if decimate_reduction: print "Decimating", decimate_reduction decimation = vtk.vtkQuadricDecimation() decimation.ReleaseDataFlagOn() decimation.SetInput(polydata) decimation.SetTargetReduction(decimate_reduction) decimation_ref = weakref.ref(decimation) decimation_ref().AddObserver("ProgressEvent", lambda obj,evt: UpdateProgress(decimation_ref(), _("Creating 3D surface..."))) #decimation.PreserveTopologyOn() #decimation.SplittingOff() #decimation.BoundaryVertexDeletionOff() decimation.GetOutput().ReleaseDataFlagOn() decimation.Update() del polydata polydata = decimation.GetOutput() #polydata.Register(None) polydata.SetSource(None) del decimation to_measure = polydata #to_measure.Register(None) to_measure.SetSource(None) if keep_largest: conn = vtk.vtkPolyDataConnectivityFilter() conn.SetInput(polydata) conn.SetExtractionModeToLargestRegion() conn_ref = weakref.ref(conn) conn_ref().AddObserver("ProgressEvent", lambda obj,evt: UpdateProgress(conn_ref(), _("Creating 3D surface..."))) conn.Update() conn.GetOutput().ReleaseDataFlagOn() del polydata polydata = conn.GetOutput() #polydata.Register(None) polydata.SetSource(None) del conn #Filter used to detect and fill holes. Only fill boundary edges holes. #TODO: Hey! This piece of code is the same from #polydata_utils.FillSurfaceHole, we need to review this. if fill_holes: filled_polydata = vtk.vtkFillHolesFilter() filled_polydata.ReleaseDataFlagOn() filled_polydata.SetInput(polydata) filled_polydata.SetHoleSize(300) filled_polydata_ref = weakref.ref(filled_polydata) filled_polydata_ref().AddObserver("ProgressEvent", lambda obj,evt: UpdateProgress(filled_polydata_ref(), _("Creating 3D surface..."))) filled_polydata.Update() filled_polydata.GetOutput().ReleaseDataFlagOn() del polydata polydata = filled_polydata.GetOutput() #polydata.Register(None) polydata.SetSource(None) polydata.DebugOn() del filled_polydata normals = vtk.vtkPolyDataNormals() normals.ReleaseDataFlagOn() normals_ref = weakref.ref(normals) normals_ref().AddObserver("ProgressEvent", lambda obj,evt: UpdateProgress(normals_ref(), _("Creating 3D surface..."))) normals.SetInput(polydata) normals.SetFeatureAngle(80) normals.AutoOrientNormalsOn() normals.GetOutput().ReleaseDataFlagOn() normals.Update() del polydata polydata = normals.GetOutput() #polydata.Register(None) polydata.SetSource(None) del normals # Improve performance stripper = vtk.vtkStripper() stripper.ReleaseDataFlagOn() stripper_ref = weakref.ref(stripper) stripper_ref().AddObserver("ProgressEvent", lambda obj,evt: UpdateProgress(stripper_ref(), _("Creating 3D surface..."))) stripper.SetInput(polydata) stripper.PassThroughCellIdsOn() stripper.PassThroughPointIdsOn() stripper.GetOutput().ReleaseDataFlagOn() stripper.Update() del polydata polydata = stripper.GetOutput() #polydata.Register(None) polydata.SetSource(None) del stripper # Map polygonal data (vtkPolyData) to graphics primitives. mapper = vtk.vtkPolyDataMapper() mapper.SetInput(polydata) mapper.ScalarVisibilityOff() mapper.ReleaseDataFlagOn() mapper.ImmediateModeRenderingOn() # improve performance # Represent an object (geometry & properties) in the rendered scene actor = vtk.vtkActor() actor.SetMapper(mapper) del mapper #Create Surface instance if overwrite: surface = Surface(index = self.last_surface_index) else: surface = Surface(name=surface_name) surface.colour = colour surface.polydata = polydata del polydata # Set actor colour and transparency actor.GetProperty().SetColor(colour) actor.GetProperty().SetOpacity(1-surface.transparency) prop = actor.GetProperty() interpolation = int(ses.Session().surface_interpolation) prop.SetInterpolation(interpolation) proj = prj.Project() if overwrite: proj.ChangeSurface(surface) else: index = proj.AddSurface(surface) surface.index = index self.last_surface_index = index session = ses.Session() session.ChangeProject() # The following lines have to be here, otherwise all volumes disappear measured_polydata = vtk.vtkMassProperties() measured_polydata.ReleaseDataFlagOn() measured_polydata.SetInput(to_measure) volume = float(measured_polydata.GetVolume()) surface.volume = volume self.last_surface_index = surface.index del measured_polydata del to_measure Publisher.sendMessage('Load surface actor into viewer', actor) # Send actor by pubsub to viewer's render if overwrite and self.actors_dict.keys(): old_actor = self.actors_dict[self.last_surface_index] Publisher.sendMessage('Remove surface actor from viewer', old_actor) # Save actor for future management tasks self.actors_dict[surface.index] = actor Publisher.sendMessage('Update surface info in GUI', (surface.index, surface.name, surface.colour, surface.volume, surface.transparency)) #When you finalize the progress. The bar is cleaned. UpdateProgress = vu.ShowProgress(1) UpdateProgress(0, _("Ready")) Publisher.sendMessage('Update status text in GUI', _("Ready")) Publisher.sendMessage('End busy cursor') del actor
def fillCaps(self): # read the .obj and center it # polydata = Helpers.centerPolyData(Helpers.getObjData(modelFn)) # TODO: centering seems to glitch the tetgen somewhy polydata = Helpers.getObjData(modelFn) size = Helpers.getBounds(polydata) print "Model sizes:" + str(size) fillHolesFilter = vtk.vtkFillHolesFilter() fillHolesFilter.SetInputData(polydata) fillHolesFilter.SetHoleSize( 1000.0 ) # TODO: hole size: compute using model size (some factor of it) normals = vtk.vtkPolyDataNormals() normals.SetInputConnection(fillHolesFilter.GetOutputPort()) normals.ConsistencyOn() normals.SplittingOff() normals.Update() normals.GetOutput().GetPointData().SetNormals( polydata.GetPointData().GetNormals()) numOriginalCells = polydata.GetNumberOfCells() numNewCells = normals.GetOutput().GetNumberOfCells() it = normals.GetOutput().NewCellIterator() numCells = 0 it.InitTraversal() # Iterate over the original cells while (not it.IsDoneWithTraversal()) and numCells < numOriginalCells: it.GoToNextCell() numCells += 1 holePolyData = vtk.vtkPolyData() holePolyData.Allocate(normals.GetOutput(), numNewCells - numOriginalCells) holePolyData.SetPoints(normals.GetOutput().GetPoints()) cell = vtk.vtkGenericCell() # The remaining cells are the new ones from the hole filler while not it.IsDoneWithTraversal(): it.GetCell(cell) holePolyData.InsertNextCell(it.GetCellType(), cell.GetPointIds()) it.GoToNextCell() connectivity = vtk.vtkConnectivityFilter() connectivity.SetInputData(holePolyData) connectivity.SetExtractionModeToAllRegions() connectivity.ColorRegionsOn() connectivity.Update() capRegions = connectivity.GetOutput() outPD = vtk.vtkPolyData() outPD.Allocate(normals.GetOutput(), numNewCells) outPD.SetPoints(capRegions.GetPoints()) numOfCaps = connectivity.GetNumberOfExtractedRegions() print "Found " + str(numOfCaps) + " holes." # create the cap polydatas capPDs = [] for i in range(0, numOfCaps): capPD = vtk.vtkPolyData() capPD.Allocate(normals.GetOutput(), numNewCells) capPD.SetPoints(capRegions.GetPoints()) capPDs.append(capPD) capScalars = capRegions.GetCellData().GetScalars() cell = vtk.vtkGenericCell() it = capRegions.NewCellIterator() i = 0 while not it.IsDoneWithTraversal(): it.GetCell(cell) # outPD.InsertNextCell(it.GetCellType(), cell.GetPointIds()) capIdx = capScalars.GetValue(i) capPDs[capIdx].InsertNextCell(it.GetCellType(), cell.GetPointIds()) it.GoToNextCell() i = i + 1 sortedCaps = [] for i in range(0, len(capPDs)): capPD = capPDs[i] cleanFilter = vtk.vtkCleanPolyData() cleanFilter.SetInputData(capPD) cleanFilter.Update() cleanedPD = cleanFilter.GetOutput() area = Helpers.getArea(cleanedPD) radius = math.sqrt(area / math.pi) sortedCaps.append([cleanedPD, area, radius]) capPDs[i] = cleanedPD sortedCaps = sorted(sortedCaps, key=lambda x: x[1], reverse=True) [lastPd, area, radius] = sortedCaps[len(capPDs) - 1] print "Recommended edge size: " + str(radius / 2) scalarsName = "ModelFaceID" Helpers.appendScalars(polydata, 1, scalarsName) # 1 for the walls appendFilter = vtk.vtkAppendPolyData() appendFilter.AddInputData(outPD) appendFilter.AddInputData(polydata) scalarIdx = 2 for [capPD, area, radius] in sortedCaps: # if radius < 0.1: # Helpers.appendScalars(capPD, 1, scalarsName) # append the face ID idx # else: # Helpers.appendScalars(capPD, scalarIdx, scalarsName) # append the face ID idx Helpers.appendScalars(capPD, scalarIdx, scalarsName) # append the face ID idx appendFilter.AddInputData(capPD) print "Cap radius: " + str(radius) scalarIdx += 1 appendFilter.Update() cleanFilter = vtk.vtkCleanPolyData() cleanFilter.SetInputConnection(appendFilter.GetOutputPort()) cleanFilter.Update() joinedPD = cleanFilter.GetOutput() # joinedPD.GetCellData().SetScalars(scalars) # Write as VTP Helpers.writeVTP(meshFn, joinedPD) return [ polydata, [[capPD, radius] for [capPD, area, radius] in sortedCaps] ]
def applyFilters(self, state): surface = None surface = state.inputModelNode.GetPolyDataConnection() if state.decimation: triangle = vtk.vtkTriangleFilter() triangle.SetInputConnection(surface) decimation = vtk.vtkDecimatePro() decimation.SetTargetReduction(state.reduction) decimation.SetBoundaryVertexDeletion(state.boundaryDeletion) decimation.PreserveTopologyOn() decimation.SetInputConnection(triangle.GetOutputPort()) surface = decimation.GetOutputPort() if state.smoothing: if state.smoothingMethod == "Laplace": smoothing = vtk.vtkSmoothPolyDataFilter() smoothing.SetBoundarySmoothing(state.boundarySmoothing) smoothing.SetNumberOfIterations(state.laplaceIterations) smoothing.SetRelaxationFactor(state.laplaceRelaxation) smoothing.SetInputConnection(surface) surface = smoothing.GetOutputPort() elif state.smoothingMethod == "Taubin": smoothing = vtk.vtkWindowedSincPolyDataFilter() smoothing.SetBoundarySmoothing(state.boundarySmoothing) smoothing.SetNumberOfIterations(state.taubinIterations) smoothing.SetPassBand(state.taubinPassBand) smoothing.SetInputConnection(surface) surface = smoothing.GetOutputPort() if state.normals: normals = vtk.vtkPolyDataNormals() normals.SetAutoOrientNormals(state.autoOrientNormals) normals.SetFlipNormals(state.flipNormals) normals.SetSplitting(state.splitting) normals.SetFeatureAngle(state.featureAngle) normals.ConsistencyOn() normals.SetInputConnection(surface) surface = normals.GetOutputPort() if state.mirror: mirrorTransformMatrix = vtk.vtkMatrix4x4() mirrorTransformMatrix.SetElement(0, 0, -1 if state.mirrorX else 1) mirrorTransformMatrix.SetElement(1, 1, -1 if state.mirrorY else 1) mirrorTransformMatrix.SetElement(2, 2, -1 if state.mirrorZ else 1) mirrorTransform = vtk.vtkTransform() mirrorTransform.SetMatrix(mirrorTransformMatrix) transformFilter = vtk.vtkTransformPolyDataFilter() transformFilter.SetInputConnection(surface) transformFilter.SetTransform(mirrorTransform) surface = transformFilter.GetOutputPort() if mirrorTransformMatrix.Determinant() < 0: reverse = vtk.vtkReverseSense() reverse.SetInputConnection(surface) surface = reverse.GetOutputPort() if state.cleaner: cleaner = vtk.vtkCleanPolyData() cleaner.SetInputConnection(surface) surface = cleaner.GetOutputPort() if state.fillHoles: fillHoles = vtk.vtkFillHolesFilter() fillHoles.SetHoleSize(state.fillHolesSize) fillHoles.SetInputConnection(surface) # Need to auto-orient normals, otherwise holes # could appear to be unfilled when only front-facing elements # are chosen to be visible. normals = vtk.vtkPolyDataNormals() normals.AutoOrientNormalsOn() normals.ConsistencyOn() normals.SetInputConnection(fillHoles.GetOutputPort()) surface = normals.GetOutputPort() if state.connectivity: connectivity = vtk.vtkPolyDataConnectivityFilter() connectivity.SetExtractionModeToLargestRegion() connectivity.SetInputConnection(surface) surface = connectivity.GetOutputPort() state.outputModelNode.SetPolyDataConnection(surface) return True
def mergeBreastAndBoundary(self, breastPolyData, wallPolyData): # 先移除最外圍的點 避免與胸部data重疊 _, edgeIds = self.extractBoundaryPoints(wallPolyData) rippedWallPolyData = self.deletePoint(wallPolyData, edgeIds) rippedWallEdge, _ = self.extractBoundaryPoints(rippedWallPolyData) wallStrips = vtk.vtkStripper() wallStrips.SetInputData(rippedWallEdge) wallStrips.Update() edge1 = wallStrips.GetOutput() breastEdge, _ = self.extractBoundaryPoints(breastPolyData) boundaryStrips = vtk.vtkStripper() boundaryStrips.SetInputData(breastEdge) boundaryStrips.Update() edge2 = boundaryStrips.GetOutput() stitcer = PolyDataStitcher() stitchPolyData = stitcer.stitch(edge1, edge2) #self.createNewModelNode(stitchPolyData, "Stitch") #先將胸壁與縫合面合併 appendFilter = vtk.vtkAppendPolyData() appendFilter.AddInputData(rippedWallPolyData) appendFilter.AddInputData(stitchPolyData) appendFilter.Update() normalFilter = vtk.vtkPolyDataNormals() normalFilter.SetInputConnection(appendFilter.GetOutputPort()) normalFilter.Update() cleanFilter = vtk.vtkCleanPolyData() cleanFilter.SetInputConnection(normalFilter.GetOutputPort()) cleanFilter.ConvertLinesToPointsOn() cleanFilter.ConvertPolysToLinesOn() cleanFilter.ConvertStripsToPolysOn() cleanFilter.Update() holeFilter = vtk.vtkFillHolesFilter() holeFilter.SetInputConnection(cleanFilter.GetOutputPort()) holeFilter.Update() #self.createNewModelNode(holeFilter.GetOutput(), "Stitch_Combine") #再次合併胸壁和胸部 appendFilter = vtk.vtkAppendPolyData() appendFilter.AddInputData(breastPolyData) appendFilter.AddInputData(holeFilter.GetOutput()) appendFilter.Update() cleanFilter = vtk.vtkCleanPolyData() cleanFilter.SetInputConnection(appendFilter.GetOutputPort()) cleanFilter.ConvertLinesToPointsOn() cleanFilter.ConvertPolysToLinesOn() cleanFilter.ConvertStripsToPolysOn() cleanFilter.Update() connectFilter = vtk.vtkPolyDataConnectivityFilter() connectFilter.SetInputConnection(cleanFilter.GetOutputPort()) connectFilter.SetExtractionModeToLargestRegion() connectFilter.Update() holeFilter = vtk.vtkFillHolesFilter() holeFilter.SetInputConnection(connectFilter.GetOutputPort()) holeFilter.Update() cleanFilter = vtk.vtkCleanPolyData() cleanFilter.SetInputConnection(holeFilter.GetOutputPort()) cleanFilter.ConvertLinesToPointsOn() cleanFilter.ConvertPolysToLinesOn() cleanFilter.ConvertStripsToPolysOn() cleanFilter.Update() normalFilter = vtk.vtkPolyDataNormals() normalFilter.SetInputConnection(cleanFilter.GetOutputPort()) normalFilter.Update() return normalFilter.GetOutput()
folder = os.path.basename(os.path.dirname(file)) if folder == "train": out_folder = os.path.join(out_path, sub_folders[0]) elif folder == "val": out_folder = os.path.join(out_path, sub_folders[1]) elif folder == "test": out_folder = os.path.join(out_path, sub_folders[2]) new_name = '_'.join(os.path.basename(file).split('_')[0:2]) + '.vtk' reader = vtk.vtkPolyDataReader() reader.SetFileName(file) reader.ReadAllScalarsOn() reader.Update() filler = vtk.vtkFillHolesFilter() filler.SetInputData(reader.GetOutput()) filler.SetHoleSize(1000) filler.Update() filt = vtk.vtkConnectivityFilter() filt.SetInputData(filler.GetOutput()) filt.SetExtractionModeToLargestRegion() filt.Update() TriangleFilter = vtk.vtkTriangleFilter() TriangleFilter.SetInputData(filt.GetOutput()) TriangleFilter.Update() cleanPolyData = vtk.vtkCleanPolyData() cleanPolyData.ToleranceIsAbsoluteOn()
def CreateSurface(self): _ = i18n.InstallLanguage(self.language) reader = vtk.vtkXMLImageDataReader() reader.SetFileName(self.filename) reader.Update() image = reader.GetOutput() if (self.flip_image): # Flip original vtkImageData flip = vtk.vtkImageFlip() flip.SetInput(reader.GetOutput()) flip.SetFilteredAxis(1) flip.FlipAboutOriginOn() image = flip.GetOutput() # Create vtkPolyData from vtkImageData if self.mode == "CONTOUR": contour = vtk.vtkContourFilter() contour.SetInput(image) contour.SetValue(0, self.min_value) # initial threshold contour.SetValue(1, self.max_value) # final threshold contour.GetOutput().ReleaseDataFlagOn() contour.AddObserver("ProgressEvent", lambda obj,evt: self.SendProgress(obj, _("Generating 3D surface..."))) polydata = contour.GetOutput() else: #mode == "GRAYSCALE": mcubes = vtk.vtkMarchingCubes() mcubes.SetInput(image) mcubes.SetValue(0, 255) mcubes.ComputeScalarsOn() mcubes.ComputeGradientsOn() mcubes.ComputeNormalsOn() mcubes.ThresholdBetween(self.min_value, self.max_value) mcubes.GetOutput().ReleaseDataFlagOn() mcubes.AddObserver("ProgressEvent", lambda obj,evt: self.SendProgress(obj, _("Generating 3D surface..."))) polydata = mcubes.GetOutput() if self.decimate_reduction: decimation = vtk.vtkQuadricDecimation() decimation.SetInput(polydata) decimation.SetTargetReduction(self.decimate_reduction) decimation.GetOutput().ReleaseDataFlagOn() decimation.AddObserver("ProgressEvent", lambda obj,evt: self.SendProgress(obj, _("Generating 3D surface..."))) polydata = decimation.GetOutput() if self.smooth_iterations and self.smooth_relaxation_factor: smoother = vtk.vtkSmoothPolyDataFilter() smoother.SetInput(polydata) smoother.SetNumberOfIterations(self.smooth_iterations) smoother.SetFeatureAngle(80) smoother.SetRelaxationFactor(self.smooth_relaxation_factor) smoother.FeatureEdgeSmoothingOn() smoother.BoundarySmoothingOn() smoother.GetOutput().ReleaseDataFlagOn() smoother.AddObserver("ProgressEvent", lambda obj,evt: self.SendProgress(obj, _("Generating 3D surface..."))) polydata = smoother.GetOutput() if self.keep_largest: conn = vtk.vtkPolyDataConnectivityFilter() conn.SetInput(polydata) conn.SetExtractionModeToLargestRegion() conn.AddObserver("ProgressEvent", lambda obj,evt: self.SendProgress(obj, _("Generating 3D surface..."))) polydata = conn.GetOutput() # Filter used to detect and fill holes. Only fill boundary edges holes. #TODO: Hey! This piece of code is the same from # polydata_utils.FillSurfaceHole, we need to review this. if self.fill_holes: filled_polydata = vtk.vtkFillHolesFilter() filled_polydata.SetInput(polydata) filled_polydata.SetHoleSize(300) filled_polydata.AddObserver("ProgressEvent", lambda obj,evt: self.SendProgress(obj, _("Generating 3D surface..."))) polydata = filled_polydata.GetOutput() filename = tempfile.mktemp() writer = vtk.vtkXMLPolyDataWriter() writer.SetInput(polydata) writer.SetFileName(filename) writer.Write() self.pipe.send(None) self.pipe.send(filename)
def join_process_surface(filenames, algorithm, smooth_iterations, smooth_relaxation_factor, decimate_reduction, keep_largest, fill_holes, options, msg_queue): def send_message(msg): try: msg_queue.put_nowait(msg) except queue.Full as e: print(e) log_path = tempfile.mktemp('vtkoutput.txt') fow = vtk.vtkFileOutputWindow() fow.SetFileName(log_path) ow = vtk.vtkOutputWindow() ow.SetInstance(fow) send_message('Joining surfaces ...') polydata_append = vtk.vtkAppendPolyData() for f in filenames: reader = vtk.vtkXMLPolyDataReader() reader.SetFileName(f) reader.Update() polydata = reader.GetOutput() polydata_append.AddInputData(polydata) del reader del polydata polydata_append.Update() # polydata_append.GetOutput().ReleaseDataFlagOn() polydata = polydata_append.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del polydata_append send_message('Cleaning surface ...') clean = vtk.vtkCleanPolyData() # clean.ReleaseDataFlagOn() # clean.GetOutput().ReleaseDataFlagOn() clean_ref = weakref.ref(clean) # clean_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(clean_ref(), _("Creating 3D surface..."))) clean.SetInputData(polydata) clean.PointMergingOn() clean.Update() del polydata polydata = clean.GetOutput() # polydata.SetSource(None) del clean if algorithm == 'ca_smoothing': send_message('Calculating normals ...') normals = vtk.vtkPolyDataNormals() normals_ref = weakref.ref(normals) # normals_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(normals_ref(), _("Creating 3D surface..."))) normals.SetInputData(polydata) # normals.ReleaseDataFlagOn() #normals.SetFeatureAngle(80) #normals.AutoOrientNormalsOn() normals.ComputeCellNormalsOn() # normals.GetOutput().ReleaseDataFlagOn() normals.Update() del polydata polydata = normals.GetOutput() # polydata.SetSource(None) del normals clean = vtk.vtkCleanPolyData() # clean.ReleaseDataFlagOn() # clean.GetOutput().ReleaseDataFlagOn() clean_ref = weakref.ref(clean) # clean_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(clean_ref(), _("Creating 3D surface..."))) clean.SetInputData(polydata) clean.PointMergingOn() clean.Update() del polydata polydata = clean.GetOutput() # polydata.SetSource(None) del clean # try: # polydata.BuildLinks() # except TypeError: # polydata.BuildLinks(0) # polydata = ca_smoothing.ca_smoothing(polydata, options['angle'], # options['max distance'], # options['min weight'], # options['steps']) send_message('Context Aware smoothing ...') mesh = cy_mesh.Mesh(polydata) cy_mesh.ca_smoothing(mesh, options['angle'], options['max distance'], options['min weight'], options['steps']) # polydata = mesh.to_vtk() # polydata.SetSource(None) # polydata.DebugOn() # else: # #smoother = vtk.vtkWindowedSincPolyDataFilter() # send_message('Smoothing ...') # smoother = vtk.vtkSmoothPolyDataFilter() # smoother_ref = weakref.ref(smoother) # # smoother_ref().AddObserver("ProgressEvent", lambda obj,evt: # # UpdateProgress(smoother_ref(), _("Creating 3D surface..."))) # smoother.SetInputData(polydata) # smoother.SetNumberOfIterations(smooth_iterations) # smoother.SetRelaxationFactor(smooth_relaxation_factor) # smoother.SetFeatureAngle(80) # #smoother.SetEdgeAngle(90.0) # #smoother.SetPassBand(0.1) # smoother.BoundarySmoothingOn() # smoother.FeatureEdgeSmoothingOn() # #smoother.NormalizeCoordinatesOn() # #smoother.NonManifoldSmoothingOn() # # smoother.ReleaseDataFlagOn() # # smoother.GetOutput().ReleaseDataFlagOn() # smoother.Update() # del polydata # polydata = smoother.GetOutput() # #polydata.Register(None) # # polydata.SetSource(None) # del smoother if not decimate_reduction: print("Decimating", decimate_reduction) send_message('Decimating ...') decimation = vtk.vtkQuadricDecimation() # decimation.ReleaseDataFlagOn() decimation.SetInputData(polydata) decimation.SetTargetReduction(decimate_reduction) decimation_ref = weakref.ref(decimation) # decimation_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(decimation_ref(), _("Creating 3D surface..."))) #decimation.PreserveTopologyOn() #decimation.SplittingOff() #decimation.BoundaryVertexDeletionOff() # decimation.GetOutput().ReleaseDataFlagOn() decimation.Update() del polydata polydata = decimation.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del decimation #to_measure.Register(None) # to_measure.SetSource(None) if keep_largest: send_message('Finding the largest ...') conn = vtk.vtkPolyDataConnectivityFilter() conn.SetInputData(polydata) conn.SetExtractionModeToLargestRegion() conn_ref = weakref.ref(conn) # conn_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(conn_ref(), _("Creating 3D surface..."))) conn.Update() # conn.GetOutput().ReleaseDataFlagOn() del polydata polydata = conn.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del conn #Filter used to detect and fill holes. Only fill boundary edges holes. #TODO: Hey! This piece of code is the same from #polydata_utils.FillSurfaceHole, we need to review this. if fill_holes: send_message('Filling holes ...') filled_polydata = vtk.vtkFillHolesFilter() # filled_polydata.ReleaseDataFlagOn() filled_polydata.SetInputData(polydata) filled_polydata.SetHoleSize(300) filled_polydata_ref = weakref.ref(filled_polydata) # filled_polydata_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(filled_polydata_ref(), _("Creating 3D surface..."))) filled_polydata.Update() # filled_polydata.GetOutput().ReleaseDataFlagOn() del polydata polydata = filled_polydata.GetOutput() #polydata.Register(None) # polydata.SetSource(None) # polydata.DebugOn() del filled_polydata to_measure = polydata normals = vtk.vtkPolyDataNormals() # normals.ReleaseDataFlagOn() # normals_ref = weakref.ref(normals) # normals_ref().AddObserver("ProgressEvent", lambda obj,evt: # UpdateProgress(normals_ref(), _("Creating 3D surface..."))) normals.SetInputData(polydata) normals.SetFeatureAngle(80) normals.SplittingOn() normals.AutoOrientNormalsOn() normals.NonManifoldTraversalOn() normals.ComputeCellNormalsOn() # normals.GetOutput().ReleaseDataFlagOn() normals.Update() del polydata polydata = normals.GetOutput() #polydata.Register(None) # polydata.SetSource(None) del normals # # Improve performance # stripper = vtk.vtkStripper() # # stripper.ReleaseDataFlagOn() # # stripper_ref = weakref.ref(stripper) # # stripper_ref().AddObserver("ProgressEvent", lambda obj,evt: # # UpdateProgress(stripper_ref(), _("Creating 3D surface..."))) # stripper.SetInputData(polydata) # stripper.PassThroughCellIdsOn() # stripper.PassThroughPointIdsOn() # # stripper.GetOutput().ReleaseDataFlagOn() # stripper.Update() # del polydata # polydata = stripper.GetOutput() # #polydata.Register(None) # # polydata.SetSource(None) # del stripper send_message('Calculating area and volume ...') measured_polydata = vtk.vtkMassProperties() measured_polydata.SetInputData(to_measure) measured_polydata.Update() volume = float(measured_polydata.GetVolume()) area = float(measured_polydata.GetSurfaceArea()) del measured_polydata filename = tempfile.mktemp(suffix='_full.vtp') writer = vtk.vtkXMLPolyDataWriter() writer.SetInputData(polydata) writer.SetFileName(filename) writer.Write() del writer print("MY PID", os.getpid()) return filename, {'volume': volume, 'area': area}
def applyFilters(self, state): surface = None surface = state.inputModelNode.GetPolyDataConnection() if state.decimation: triangle = vtk.vtkTriangleFilter() triangle.SetInputConnection(surface) decimation = vtk.vtkDecimatePro() decimation.SetTargetReduction(state.reduction) decimation.SetBoundaryVertexDeletion(state.boundaryDeletion) decimation.PreserveTopologyOn() decimation.SetInputConnection(triangle.GetOutputPort()) surface = decimation.GetOutputPort() if state.smoothing: if state.smoothingMethod == "Laplace": smoothing = vtk.vtkSmoothPolyDataFilter() smoothing.SetBoundarySmoothing(state.boundarySmoothing) smoothing.SetNumberOfIterations(state.laplaceIterations) smoothing.SetRelaxationFactor(state.laplaceRelaxation) smoothing.SetInputConnection(surface) surface = smoothing.GetOutputPort() elif state.smoothingMethod == "Taubin": smoothing = vtk.vtkWindowedSincPolyDataFilter() smoothing.SetBoundarySmoothing(state.boundarySmoothing) smoothing.SetNumberOfIterations(state.taubinIterations) smoothing.SetPassBand(state.taubinPassBand) smoothing.SetInputConnection(surface) surface = smoothing.GetOutputPort() if state.normals: normals = vtk.vtkPolyDataNormals() normals.SetAutoOrientNormals(state.autoOrientNormals) normals.SetFlipNormals(state.flipNormals) normals.SetSplitting(state.splitting) normals.SetFeatureAngle(state.featureAngle) normals.ConsistencyOn() normals.SetInputConnection(surface) surface = normals.GetOutputPort() if state.mirror: mirrorTransformMatrix = vtk.vtkMatrix4x4() mirrorTransformMatrix.SetElement(0, 0, -1 if state.mirrorX else 1) mirrorTransformMatrix.SetElement(1, 1, -1 if state.mirrorY else 1) mirrorTransformMatrix.SetElement(2, 2, -1 if state.mirrorZ else 1) mirrorTransform = vtk.vtkTransform() mirrorTransform.SetMatrix(mirrorTransformMatrix) transformFilter = vtk.vtkTransformPolyDataFilter() transformFilter.SetInputConnection(surface) transformFilter.SetTransform(mirrorTransform) surface = transformFilter.GetOutputPort() if mirrorTransformMatrix.Determinant()<0: reverse = vtk.vtkReverseSense() reverse.SetInputConnection(surface) surface = reverse.GetOutputPort() if state.cleaner: cleaner = vtk.vtkCleanPolyData() cleaner.SetInputConnection(surface) surface = cleaner.GetOutputPort() if state.fillHoles: fillHoles = vtk.vtkFillHolesFilter() fillHoles.SetHoleSize(state.fillHolesSize) fillHoles.SetInputConnection(surface) # Need to auto-orient normals, otherwise holes # could appear to be unfilled when only front-facing elements # are chosen to be visible. normals = vtk.vtkPolyDataNormals() normals.AutoOrientNormalsOn() normals.ConsistencyOn() normals.SetInputConnection(fillHoles.GetOutputPort()) surface = normals.GetOutputPort() if state.connectivity: connectivity = vtk.vtkPolyDataConnectivityFilter() connectivity.SetExtractionModeToLargestRegion() connectivity.SetInputConnection(surface) surface = connectivity.GetOutputPort() state.outputModelNode.SetPolyDataConnection(surface) return True
reader.SetFileName(file_name) reader.Update() model = reader.GetOutput() clean_filter = vtk.vtkCleanPolyData() clean_filter.SetPointMerging(True) clean_filter.SetInputData(model) clean_filter.Update() model = clean_filter.GetOutput() model.BuildLinks() create_node_coord_hash(model) #find_holes(model) fill_hole_filter = vtk.vtkFillHolesFilter() fill_hole_filter.SetInputData(model) fill_hole_filter.SetHoleSize(float(1e10)) fill_hole_filter.Update() model = fill_hole_filter.GetOutput() normals = vtk.vtkPolyDataNormals() normals.SetInputData(model) normals.ConsistencyOn() normals.SplittingOn() normals.Update() model = normals.GetOutput() clean_filter = vtk.vtkCleanPolyData() clean_filter.SetPointMerging(True) clean_filter.SetInputData(model)