diff --git a/invesalius/data/surface.py b/invesalius/data/surface.py index dc4aac7..5f3f363 100644 --- a/invesalius/data/surface.py +++ b/invesalius/data/surface.py @@ -377,7 +377,7 @@ class SurfaceManager(): """ matrix, filename_img, mask, spacing = pubsub_evt.data min_value, max_value = mask.threshold_range - fill_holes = True + fill_holes = False #if len(surface_data) == 5: #imagedata, colour, [min_value, max_value], \ @@ -394,7 +394,7 @@ class SurfaceManager(): mode = 'CONTOUR' # 'GRAYSCALE' quality=_('Optimal *') - keep_largest = True + keep_largest = False surface_name = "" colour = mask.colour @@ -415,19 +415,19 @@ class SurfaceManager(): #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 + 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 + # pipeline_size += 1 #if keep_largest: - #pipeline_size += 1 - + # pipeline_size += 1 + ## Update progress value in GUI - #UpdateProgress = vu.ShowProgress(pipeline_size) - #UpdateProgress(0, _("Generating 3D surface...")) + UpdateProgress = vu.ShowProgress(pipeline_size) + UpdateProgress(0, _("Generating 3D surface...")) #filename_img = tempfile.mktemp() @@ -452,7 +452,6 @@ class SurfaceManager(): piece_size = 20 n_pieces = int(round(matrix.shape[0] / piece_size + 0.5, 0)) - print "n_pieces", n_pieces, matrix.shape q_in = multiprocessing.Queue() q_out = multiprocessing.Queue() @@ -463,8 +462,7 @@ class SurfaceManager(): matrix.shape, matrix.dtype, spacing, mode, min_value, max_value, decimate_reduction, smooth_relaxation_factor, - smooth_iterations, language, fill_holes, keep_largest, - flip_image, q_in, q_out) + smooth_iterations, language, flip_image, q_in, q_out) p.append(sp) sp.start() @@ -478,6 +476,18 @@ class SurfaceManager(): 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() t = n_pieces while t: @@ -490,13 +500,18 @@ class SurfaceManager(): t -= 1 polydata = polydata_append.GetOutput() - clean = vtk.vtkCleanPolyData() + clean.AddObserver("ProgressEvent", lambda obj,evt: + UpdateProgress(obj, _("Generating 3D surface..."))) clean.SetInput(polydata) clean.PointMergingOn() + clean.Update() polydata = clean.GetOutput() + smoother = vtk.vtkWindowedSincPolyDataFilter() + smoother.AddObserver("ProgressEvent", lambda obj,evt: + UpdateProgress(obj, _("Generating 3D surface..."))) smoother.SetInput(polydata) smoother.SetNumberOfIterations(smooth_iterations) smoother.SetFeatureAngle(120) @@ -508,29 +523,48 @@ class SurfaceManager(): smoother.Update() polydata = smoother.GetOutput() + if keep_largest: + conn = vtk.vtkPolyDataConnectivityFilter() + conn.SetInput(polydata) + conn.SetExtractionModeToLargestRegion() + conn.AddObserver("ProgressEvent", lambda obj,evt: + UpdateProgress(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 fill_holes: + filled_polydata = vtk.vtkFillHolesFilter() + filled_polydata.SetInput(polydata) + filled_polydata.SetHoleSize(300) + #filled_polydata.AddObserver("ProgressEvent", lambda obj,evt: + # UpdateProgress(obj, _("Generating 3D surface..."))) + polydata = filled_polydata.GetOutput() normals = vtk.vtkPolyDataNormals() + normals.AddObserver("ProgressEvent", lambda obj,evt: + UpdateProgress(obj, _("Generating 3D surface..."))) normals.SetInput(polydata) normals.SetFeatureAngle(80) normals.AutoOrientNormalsOn() + normals.Update() polydata = normals.GetOutput() - #decimation = vtk.vtkDecimatePro() - #decimation.SetInput(polydata) - #decimation.SetTargetReduction(0.3) - #decimation.PreserveTopologyOn() - #decimation.SplittingOff() - #decimation.BoundaryVertexDeletionOff() - #polydata = decimation.GetOutput() # Improve performance stripper = vtk.vtkStripper() + stripper.AddObserver("ProgressEvent", lambda obj,evt: + UpdateProgress(obj, _("Generating 3D surface..."))) stripper.SetInput(polydata) stripper.PassThroughCellIdsOn() stripper.PassThroughPointIdsOn() + stripper.Update() + polydata = stripper.GetOutput() # Map polygonal data (vtkPolyData) to graphics primitives. mapper = vtk.vtkPolyDataMapper() - mapper.SetInput(stripper.GetOutput()) + mapper.SetInput(polydata) mapper.ScalarVisibilityOff() mapper.ImmediateModeRenderingOn() # improve performance @@ -601,15 +635,16 @@ class SurfaceManager(): # Save actor for future management tasks self.actors_dict[surface.index] = actor - - ps.Publisher().sendMessage('Update status text in GUI', - _("Ready")) - ps.Publisher().sendMessage('Update surface info in GUI', (surface.index, surface.name, surface.colour, surface.volume, surface.transparency)) + UpdateProgress(0, _("Ready")) + UpdateProgress(0, _("Ready")) + ps.Publisher().sendMessage('Update status text in GUI', + _("Ready")) + ps.Publisher().sendMessage('End busy cursor') diff --git a/invesalius/data/surface_process.py b/invesalius/data/surface_process.py index d645993..8d28aab 100644 --- a/invesalius/data/surface_process.py +++ b/invesalius/data/surface_process.py @@ -13,8 +13,7 @@ class SurfaceProcess(multiprocessing.Process): def __init__(self, pipe, filename, shape, dtype, spacing, mode, min_value, max_value, decimate_reduction, smooth_relaxation_factor, - smooth_iterations, language, fill_holes, keep_largest, - flip_image, q_in, q_out): + smooth_iterations, language, flip_image, q_in, q_out): multiprocessing.Process.__init__(self) self.pipe = pipe @@ -27,8 +26,6 @@ class SurfaceProcess(multiprocessing.Process): self.smooth_relaxation_factor = smooth_relaxation_factor self.smooth_iterations = smooth_iterations self.language = language - self.fill_holes = fill_holes - self.keep_largest = keep_largest self.flip_image = flip_image self.q_in = q_in self.q_out = q_out @@ -40,7 +37,6 @@ class SurfaceProcess(multiprocessing.Process): shape=self.shape) while 1: roi = self.q_in.get() - print roi if roi is None: break self.CreateSurface(roi) @@ -60,77 +56,52 @@ class SurfaceProcess(multiprocessing.Process): flip.Update() # Create vtkPolyData from vtkImageData #print "Generating Polydata" - #if self.mode == "CONTOUR": + if self.mode == "CONTOUR": #print "Contour" - #contour = vtk.vtkContourFilter() - #contour.SetInput(image) - #contour.SetValue(0, self.min_value) # initial threshold - #contour.SetValue(1, self.max_value) # final threshold - #contour.ComputeScalarsOn() - #contour.ComputeGradientsOn() - #contour.ComputeNormalsOn() - #polydata = contour.GetOutput() - #else: #mode == "GRAYSCALE": - mcubes = vtk.vtkMarchingCubes() - mcubes.SetInput(flip.GetOutput()) - mcubes.SetValue(0, self.min_value) - mcubes.SetValue(1, self.max_value) - mcubes.ComputeScalarsOff() - mcubes.ComputeGradientsOff() - mcubes.ComputeNormalsOff() - polydata = mcubes.GetOutput() + contour = vtk.vtkContourFilter() + contour.SetInput(flip.GetOutput()) + contour.SetValue(0, self.min_value) # initial threshold + contour.SetValue(1, self.max_value) # final threshold + contour.ComputeScalarsOn() + contour.ComputeGradientsOn() + contour.ComputeNormalsOn() + contour.AddObserver("ProgressEvent", lambda obj,evt: + self.SendProgress(obj, _("Generating 3D surface..."))) + polydata = contour.GetOutput() + else: #mode == "GRAYSCALE": + mcubes = vtk.vtkMarchingCubes() + mcubes.SetInput(flip.GetOutput()) + mcubes.SetValue(0, self.min_value) + mcubes.SetValue(1, self.max_value) + mcubes.ComputeScalarsOff() + mcubes.ComputeGradientsOff() + mcubes.ComputeNormalsOff() + mcubes.AddObserver("ProgressEvent", lambda obj,evt: + self.SendProgress(obj, _("Generating 3D surface..."))) + polydata = mcubes.GetOutput() triangle = vtk.vtkTriangleFilter() triangle.SetInput(polydata) + triangle.AddObserver("ProgressEvent", lambda obj,evt: + self.SendProgress(obj, _("Generating 3D surface..."))) triangle.Update() polydata = triangle.GetOutput() - bounds = polydata.GetBounds() - origin = ((bounds[1] + bounds[0]) / 2.0, (bounds[3] + bounds[2])/2.0, - (bounds[5] + bounds[4]) / 2.0) - - print "Bounds is", bounds - print "origin is", origin - - #print "Decimating" - decimation = vtk.vtkDecimatePro() - decimation.SetInput(polydata) - decimation.SetTargetReduction(0.3) - #decimation.PreserveTopologyOn() - decimation.SplittingOff() - decimation.BoundaryVertexDeletionOff() - polydata = decimation.GetOutput() - - #decimation = vtk.vtkQuadricClustering() - #decimation.SetInput(polydata) - #decimation.AutoAdjustNumberOfDivisionsOff() - #decimation.SetDivisionOrigin(0, 0, 0) - #decimation.SetDivisionSpacing(self.spacing) - #decimation.SetFeaturePointsAngle(80) - #decimation.UseFeaturePointsOn() - #decimation.UseFeatureEdgesOn() - #ecimation.CopyCellDataOn() + if self.decimate_reduction: + + #print "Decimating" + decimation = vtk.vtkDecimatePro() + decimation.SetInput(polydata) + decimation.SetTargetReduction(0.3) + decimation.AddObserver("ProgressEvent", lambda obj,evt: + self.SendProgress(obj, _("Generating 3D surface..."))) + #decimation.PreserveTopologyOn() + decimation.SplittingOff() + decimation.BoundaryVertexDeletionOff() + polydata = decimation.GetOutput() + + self.pipe.send(None) - #print "Division", decimation.GetNumberOfDivisions() - - #polydata = decimation.GetOutput() - - #if self.smooth_iterations and self.smooth_relaxation_factor: - #print "Smoothing" - #smoother = vtk.vtkWindowedSincPolyDataFilter() - #smoother.SetInput(polydata) - #smoother.SetNumberOfIterations(self.smooth_iterations) - #smoother.SetFeatureAngle(120) - #smoother.SetNumberOfIterations(30) - #smoother.BoundarySmoothingOn() - #smoother.SetPassBand(0.01) - #smoother.FeatureEdgeSmoothingOn() - #smoother.NonManifoldSmoothingOn() - #smoother.NormalizeCoordinatesOn() - #smoother.Update() - #polydata = smoother.GetOutput() - - print "Saving" filename = tempfile.mktemp(suffix='_%s.vtp' % (self.pid)) writer = vtk.vtkXMLPolyDataWriter() writer.SetInput(polydata) diff --git a/invesalius/data/vtk_utils.py b/invesalius/data/vtk_utils.py index c57393f..c01e7df 100644 --- a/invesalius/data/vtk_utils.py +++ b/invesalius/data/vtk_utils.py @@ -74,7 +74,6 @@ def ShowProgress(number_of_filters = 1, # final progress status value progress[0] = progress[0] + ratio*difference - # Tell GUI to update progress status value if (dialog_type == "GaugeProgress"): ps.Publisher().sendMessage('Update status in GUI', -- libgit2 0.21.2