Ejemplo n.º 1
0
def SplitDisconectedParts(polydata):
    """
    """
    conn = vtkPolyDataConnectivityFilter()
    conn.SetInputData(polydata)
    conn.SetExtractionModeToAllRegions()
    conn.Update()

    nregions = conn.GetNumberOfExtractedRegions()

    conn.SetExtractionModeToSpecifiedRegions()
    conn.Update()

    polydata_collection = []

    # Update progress value in GUI
    progress = nregions -1
    if progress:
        UpdateProgress = vu.ShowProgress(progress)

    for region in range(nregions):
        conn.InitializeSpecifiedRegionList()
        conn.AddSpecifiedRegion(region)
        conn.Update()

        p = vtkPolyData()
        p.DeepCopy(conn.GetOutput())

        polydata_collection.append(p)
        if progress:
            UpdateProgress(region, _("Splitting disconnected regions..."))

    return polydata_collection
Ejemplo n.º 2
0
def SelectLargestPart(polydata):
    """
    """
    UpdateProgress = vu.ShowProgress(1)
    conn = vtkPolyDataConnectivityFilter()
    conn.SetInputData(polydata)
    conn.SetExtractionModeToLargestRegion()
    conn.AddObserver("ProgressEvent", lambda obj, evt:
                  UpdateProgress(conn, "Getting largest part..."))
    conn.Update()

    result = vtkPolyData()
    result.DeepCopy(conn.GetOutput())
    return result
Ejemplo n.º 3
0
def dcm2memmap(files, slice_size, orientation, resolution_percentage):
    """
    From a list of dicom files it creates memmap file in the temp folder and
    returns it and its related filename.
    """
    if len(files) > 1:
        message = _("Generating multiplanar visualization...")
        update_progress = vtk_utils.ShowProgress(
            len(files) - 1, dialog_type="ProgressDialog"
        )

    first_slice = read_dcm_slice_as_np2(files[0], resolution_percentage)
    slice_size = first_slice.shape[::-1]

    temp_file = tempfile.mktemp()

    if orientation == "SAGITTAL":
        shape = slice_size[0], slice_size[1], len(files)
    elif orientation == "CORONAL":
        shape = slice_size[1], len(files), slice_size[0]
    else:
        shape = len(files), slice_size[1], slice_size[0]

    matrix = numpy.memmap(temp_file, mode="w+", dtype="int16", shape=shape)
    for n, f in enumerate(files):
        im_array = read_dcm_slice_as_np2(f, resolution_percentage)[::-1]

        if orientation == "CORONAL":
            matrix[:, shape[1] - n - 1, :] = im_array
        elif orientation == "SAGITTAL":
            # TODO: Verify if it's necessary to add the slices swapped only in
            # sagittal rmi or only in # Rasiane's case or is necessary in all
            # sagittal cases.
            matrix[:, :, n] = im_array
        else:
            matrix[n] = im_array
        if len(files) > 1:
            update_progress(n, message)

    matrix.flush()
    scalar_range = matrix.min(), matrix.max()

    return matrix, scalar_range, temp_file
Ejemplo n.º 4
0
    def ApplyConvolution(self, imagedata, update_progress = None):
        number_filters = len(self.config['convolutionFilters'])
        if number_filters:
            if not(update_progress):
                update_progress = vtk_utils.ShowProgress(number_filters)
            for filter in self.config['convolutionFilters']:
                convolve = vtk.vtkImageConvolve()
                convolve.SetInputData(imagedata)
                convolve.SetKernel5x5([i/60.0 for i in Kernels[filter]])
                #  convolve.ReleaseDataFlagOn()

                convolve_ref = weakref.ref(convolve)
                
                convolve_ref().AddObserver("ProgressEvent", lambda obj,evt:
                                     update_progress(convolve_ref(), "Rendering..."))
                convolve.Update()
                del imagedata
                imagedata = convolve.GetOutput()
                del convolve
                #convolve.GetOutput().ReleaseDataFlagOn()
        return imagedata
Ejemplo n.º 5
0
def JoinSeedsParts(polydata, point_id_list):
    """
    The function require vtkPolyData and point id
    from vtkPolyData.
    """
    conn = vtkPolyDataConnectivityFilter()
    conn.SetInputData(polydata)
    conn.SetExtractionModeToPointSeededRegions()
    UpdateProgress = vu.ShowProgress(1 + len(point_id_list))
    pos = 1
    for seed in point_id_list:
        conn.AddSeed(seed)
        UpdateProgress(pos, _("Analysing selected regions..."))
        pos += 1

    conn.AddObserver("ProgressEvent", lambda obj, evt:
                  UpdateProgress(conn, "Getting selected parts"))
    conn.Update()

    result = vtkPolyData()
    result.DeepCopy(conn.GetOutput())
    return result
Ejemplo n.º 6
0
    def LoadVolume(self):
        proj = prj.Project()
        #image = imagedata_utils.to_vtk(n_array, spacing, slice_number, orientation)

        if not self.loaded_image:
            self.LoadImage()
            self.loaded_image = 1

        image = self.image

        number_filters = len(self.config['convolutionFilters'])

        if (prj.Project().original_orientation == const.AXIAL):
            flip_image = True
        else:
            flip_image = False

        #if (flip_image):
        update_progress = vtk_utils.ShowProgress(2 + number_filters)
        # Flip original vtkImageData
        flip = vtk.vtkImageFlip()
        flip.SetInputData(image)
        flip.SetFilteredAxis(1)
        flip.FlipAboutOriginOn()
        #  flip.ReleaseDataFlagOn()

        flip_ref = weakref.ref(flip)
        flip_ref().AddObserver(
            "ProgressEvent",
            lambda obj, evt: update_progress(flip_ref(), "Rendering..."))
        flip.Update()
        image = flip.GetOutput()

        scale = image.GetScalarRange()
        self.scale = scale

        cast = vtk.vtkImageShiftScale()
        cast.SetInputData(image)
        cast.SetShift(abs(scale[0]))
        cast.SetOutputScalarTypeToUnsignedShort()
        #  cast.ReleaseDataFlagOn()
        cast_ref = weakref.ref(cast)
        cast_ref().AddObserver(
            "ProgressEvent",
            lambda obj, evt: update_progress(cast_ref(), "Rendering..."))
        cast.Update()
        image2 = cast

        self.imagedata = image2
        if self.config['advancedCLUT']:
            self.Create16bColorTable(scale)
            self.CreateOpacityTable(scale)
        else:
            self.Create8bColorTable(scale)
            self.Create8bOpacityTable(scale)

        image2 = self.ApplyConvolution(image2.GetOutput(), update_progress)
        self.final_imagedata = image2

        # Changed the vtkVolumeRayCast to vtkFixedPointVolumeRayCastMapper
        # because it's faster and the image is better
        # TODO: To test if it's true.
        if const.TYPE_RAYCASTING_MAPPER:
            volume_mapper = vtk.vtkVolumeRayCastMapper()
            #volume_mapper.AutoAdjustSampleDistancesOff()
            #volume_mapper.SetInput(image2)
            #volume_mapper.SetVolumeRayCastFunction(composite_function)
            #volume_mapper.SetGradientEstimator(gradientEstimator)
            volume_mapper.IntermixIntersectingGeometryOn()
            self.volume_mapper = volume_mapper
        else:

            if int(ses.Session().rendering) == 0:
                volume_mapper = vtk.vtkFixedPointVolumeRayCastMapper()
                #volume_mapper.AutoAdjustSampleDistancesOff()
                self.volume_mapper = volume_mapper
                volume_mapper.IntermixIntersectingGeometryOn()
            else:
                volume_mapper = vtk.vtkGPUVolumeRayCastMapper()
                volume_mapper.UseJitteringOn()
                self.volume_mapper = volume_mapper

        self.SetTypeRaycasting()
        volume_mapper.SetInputData(image2)

        # TODO: Look to this
        #volume_mapper_hw = vtk.vtkVolumeTextureMapper3D()
        #volume_mapper_hw.SetInput(image2)

        #Cut Plane
        #CutPlane(image2, volume_mapper)

        #self.color_transfer = color_transfer

        volume_properties = vtk.vtkVolumeProperty()
        #volume_properties.IndependentComponentsOn()
        volume_properties.SetInterpolationTypeToLinear()
        volume_properties.SetColor(self.color_transfer)

        try:
            volume_properties.SetScalarOpacity(self.opacity_transfer_func)
        except NameError:
            pass

        if not self.volume_mapper.IsA("vtkGPUVolumeRayCastMapper"):
            # Using these lines to improve the raycasting quality. These values
            # seems related to the distance from ray from raycasting.
            # TODO: Need to see values that improve the quality and don't decrease
            # the performance. 2.0 seems to be a good value to pix_diag
            pix_diag = 2.0
            volume_mapper.SetImageSampleDistance(0.25)
            volume_mapper.SetSampleDistance(pix_diag / 5.0)
            volume_properties.SetScalarOpacityUnitDistance(pix_diag)

        self.volume_properties = volume_properties

        self.SetShading()

        volume = vtk.vtkVolume()
        volume.SetMapper(volume_mapper)
        volume.SetProperty(volume_properties)
        self.volume = volume

        colour = self.GetBackgroundColour()

        self.exist = 1

        if self.plane:
            self.plane.SetVolumeMapper(volume_mapper)

        Publisher.sendMessage('Load volume into viewer',
                              volume=volume,
                              colour=colour,
                              ww=self.ww,
                              wl=self.wl)

        del flip
        del cast
Ejemplo n.º 7
0
def dcm2memmap(files, slice_size, orientation, resolution_percentage):
    """
    From a list of dicom files it creates memmap file in the temp folder and
    returns it and its related filename.
    """
    message = _("Generating multiplanar visualization...")
    update_progress = vtk_utils.ShowProgress(len(files) - 1,
                                             dialog_type="ProgressDialog")

    temp_file = tempfile.mktemp()

    if orientation == 'SAGITTAL':
        if resolution_percentage == 1.0:
            shape = slice_size[0], slice_size[1], len(files)
        else:
            shape = math.ceil(slice_size[0]*resolution_percentage),\
                    math.ceil(slice_size[1]*resolution_percentage), len(files)

    elif orientation == 'CORONAL':
        if resolution_percentage == 1.0:
            shape = slice_size[1], len(files), slice_size[0]
        else:
            shape = math.ceil(slice_size[1]*resolution_percentage), len(files),\
                                        math.ceil(slice_size[0]*resolution_percentage)
    else:
        if resolution_percentage == 1.0:
            shape = len(files), slice_size[1], slice_size[0]
        else:
            shape = len(files), math.ceil(slice_size[1]*resolution_percentage),\
                                        math.ceil(slice_size[0]*resolution_percentage)

    matrix = numpy.memmap(temp_file, mode='w+', dtype='int16', shape=shape)
    dcm_reader = vtkgdcm.vtkGDCMImageReader()
    cont = 0
    max_scalar = None
    min_scalar = None

    for n, f in enumerate(files):
        dcm_reader.SetFileName(f)
        dcm_reader.Update()
        image = dcm_reader.GetOutput()

        if resolution_percentage != 1.0:
            image_resized = ResampleImage2D(image, px=None, py=None,\
                                resolution_percentage = resolution_percentage, update_progress = None)

            image = image_resized

        min_aux, max_aux = image.GetScalarRange()
        if min_scalar is None or min_aux < min_scalar:
            min_scalar = min_aux

        if max_scalar is None or max_aux > max_scalar:
            max_scalar = max_aux

        array = numpy_support.vtk_to_numpy(image.GetPointData().GetScalars())
        if orientation == 'CORONAL':
            array.shape = matrix.shape[0], matrix.shape[2]
            matrix[:, n, :] = array
        elif orientation == 'SAGITTAL':
            array.shape = matrix.shape[0], matrix.shape[1]
            # TODO: Verify if it's necessary to add the slices swapped only in
            # sagittal rmi or only in # Rasiane's case or is necessary in all
            # sagittal cases.
            matrix[:, :, n] = array
        else:
            array.shape = matrix.shape[1], matrix.shape[2]
            matrix[n] = array
        update_progress(cont, message)
        cont += 1

    matrix.flush()
    scalar_range = min_scalar, max_scalar

    return matrix, scalar_range, temp_file
Ejemplo n.º 8
0
def bitmap2memmap(files, slice_size, orientation, spacing,
                  resolution_percentage):
    """
    From a list of dicom files it creates memmap file in the temp folder and
    returns it and its related filename.
    """
    message = _("Generating multiplanar visualization...")
    update_progress = vtk_utils.ShowProgress(len(files) - 1,
                                             dialog_type="ProgressDialog")

    temp_file = tempfile.mktemp()

    if orientation == 'SAGITTAL':
        if resolution_percentage == 1.0:
            shape = slice_size[1], slice_size[0], len(files)
        else:
            shape = math.ceil(slice_size[1]*resolution_percentage),\
                    math.ceil(slice_size[0]*resolution_percentage), len(files)

    elif orientation == 'CORONAL':
        if resolution_percentage == 1.0:
            shape = slice_size[1], len(files), slice_size[0]
        else:
            shape = math.ceil(slice_size[1]*resolution_percentage), len(files),\
                                        math.ceil(slice_size[0]*resolution_percentage)
    else:
        if resolution_percentage == 1.0:
            shape = len(files), slice_size[1], slice_size[0]
        else:
            shape = len(files), math.ceil(slice_size[1]*resolution_percentage),\
                                        math.ceil(slice_size[0]*resolution_percentage)

    if resolution_percentage == 1.0:
        matrix = numpy.memmap(temp_file, mode='w+', dtype='int16', shape=shape)

    cont = 0
    max_scalar = None
    min_scalar = None

    xy_shape = None
    first_resample_entry = False

    for n, f in enumerate(files):
        image_as_array = bitmap_reader.ReadBitmap(f)

        image = converters.to_vtk(image_as_array, spacing=spacing,\
                                    slice_number=1, orientation=orientation.upper())

        if resolution_percentage != 1.0:


            image_resized = ResampleImage2D(image, px=None, py=None,\
                                resolution_percentage = resolution_percentage, update_progress = None)

            yx_shape = image_resized.GetDimensions(
            )[1], image_resized.GetDimensions()[0]

            if not (first_resample_entry):
                shape = shape[0], yx_shape[0], yx_shape[1]
                matrix = numpy.memmap(temp_file,
                                      mode='w+',
                                      dtype='int16',
                                      shape=shape)
                first_resample_entry = True

            image = image_resized

        min_aux, max_aux = image.GetScalarRange()
        if min_scalar is None or min_aux < min_scalar:
            min_scalar = min_aux

        if max_scalar is None or max_aux > max_scalar:
            max_scalar = max_aux

        array = numpy_support.vtk_to_numpy(image.GetPointData().GetScalars())

        if array.dtype == 'uint16':
            array = array - 32768 / 2

        array = array.astype("int16")

        if orientation == 'CORONAL':
            array.shape = matrix.shape[0], matrix.shape[2]
            matrix[:, n, :] = array[:, ::-1]
        elif orientation == 'SAGITTAL':
            array.shape = matrix.shape[0], matrix.shape[1]
            # TODO: Verify if it's necessary to add the slices swapped only in
            # sagittal rmi or only in # Rasiane's case or is necessary in all
            # sagittal cases.
            matrix[:, :, n] = array[:, ::-1]
        else:
            array.shape = matrix.shape[1], matrix.shape[2]
            matrix[n] = array

        update_progress(cont, message)
        cont += 1

    matrix.flush()
    scalar_range = min_scalar, max_scalar

    return matrix, scalar_range, temp_file
Ejemplo n.º 9
0
    def CreateImageData(self, filelist, zspacing, size, bits):
        message = _("Generating multiplanar visualization...")

        if not const.VTK_WARNING:
            log_path = os.path.join(const.LOG_FOLDER, 'vtkoutput.txt')
            fow = vtk.vtkFileOutputWindow()
            fow.SetFileName(log_path)
            ow = vtk.vtkOutputWindow()
            ow.SetInstance(fow)

        x, y = size
        px, py = utils.predict_memory(len(filelist), x, y, bits)
        utils.debug("Image Resized to >>> %f x %f" % (px, py))

        if (x == px) and (y == py):
            const.REDUCE_IMAGEDATA_QUALITY = 0
        else:
            const.REDUCE_IMAGEDATA_QUALITY = 1

        if not (const.REDUCE_IMAGEDATA_QUALITY):
            update_progress = vtk_utils.ShowProgress(
                1, dialog_type="ProgressDialog")

            array = vtk.vtkStringArray()
            for x in xrange(len(filelist)):
                if not self.running:
                    return False
                array.InsertValue(x, filelist[x])

            if not self.running:
                return False
            reader = vtkgdcm.vtkGDCMImageReader()
            reader.SetFileNames(array)
            reader.AddObserver(
                "ProgressEvent",
                lambda obj, evt: update_progress(reader, message))
            reader.Update()

            if not self.running:
                reader.AbortExecuteOn()
                return False
            # The zpacing is a DicomGroup property, so we need to set it
            imagedata = vtk.vtkImageData()
            imagedata.DeepCopy(reader.GetOutput())
            spacing = imagedata.GetSpacing()
            imagedata.SetSpacing(spacing[0], spacing[1], zspacing)
        else:

            update_progress = vtk_utils.ShowProgress(
                2 * len(filelist), dialog_type="ProgressDialog")

            # Reformat each slice and future append them
            appender = vtk.vtkImageAppend()
            appender.SetAppendAxis(2)  #Define Stack in Z

            # Reformat each slice
            for x in xrange(len(filelist)):
                # TODO: We need to check this automatically according
                # to each computer's architecture
                # If the resolution of the matrix is too large
                if not self.running:
                    return False
                reader = vtkgdcm.vtkGDCMImageReader()
                reader.SetFileName(filelist[x])
                reader.AddObserver(
                    "ProgressEvent",
                    lambda obj, evt: update_progress(reader, message))
                reader.Update()

                #Resample image in x,y dimension
                slice_imagedata = ResampleImage2D(reader.GetOutput(), px, py,
                                                  update_progress)
                #Stack images in Z axes
                appender.AddInput(slice_imagedata)
                #appender.AddObserver("ProgressEvent", lambda obj,evt:update_progress(appender))
                appender.Update()

            # The zpacing is a DicomGroup property, so we need to set it
            if not self.running:
                return False
            imagedata = vtk.vtkImageData()
            imagedata.DeepCopy(appender.GetOutput())
            spacing = imagedata.GetSpacing()

            imagedata.SetSpacing(spacing[0], spacing[1], zspacing)

        imagedata.AddObserver(
            "ProgressEvent",
            lambda obj, evt: update_progress(imagedata, message))
        imagedata.Update()

        return imagedata
Ejemplo n.º 10
0
    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
Ejemplo n.º 11
0
import invesalius.constants as const
import invesalius.data.vtk_utils as vu
from invesalius.utils import touch
from invesalius.pubsub import pub as Publisher

if sys.platform == 'win32':
    try:
        import win32api
        _has_win32api = True
    except ImportError:
        _has_win32api = False
else:
    _has_win32api = False

# Update progress value in GUI
UpdateProgress = vu.ShowProgress()

def ApplyDecimationFilter(polydata, reduction_factor):
    """
    Reduce number of triangles of the given vtkPolyData, based on
    reduction_factor.
    """
    # Important: vtkQuadricDecimation presented better results than
    # vtkDecimatePro
    decimation = vtkQuadricDecimation()
    decimation.SetInputData(polydata)
    decimation.SetTargetReduction(reduction_factor)
    decimation.GetOutput().ReleaseDataFlagOn()
    decimation.AddObserver("ProgressEvent", lambda obj, evt:
                  UpdateProgress(decimation, "Reducing number of triangles..."))
    return decimation.GetOutput()