def threshold(operator, step_pct, input_image): import itk from tomviz import itkutils import itkExtras import itkTypes otsu_filter = \ itk.OtsuMultipleThresholdsImageFilter.New(Input=input_image) otsu_filter.SetNumberOfThresholds(1) operator.progress.message = "Otsu threshold" progress = operator.progress.value itkutils.observe_filter_progress(operator, otsu_filter, progress, progress + next(step_pct)) try: otsu_filter.Update() except RuntimeError: return # Cast threshold output to an integral type if needed. input_image_type = type(input_image) voxel_type = itkExtras.template(input_image_type)[1][0] if voxel_type is itkTypes.F or voxel_type is itkTypes.D: operator.progress.message = "Casting output to integral type" # Unsigned char supports 256 labels, or 255 threshold levels. # This should be sufficient for all but the most unusual use # cases. dimension = input_image_type.GetImageDimension() py_buffer_type = itk.Image[itk.UC, dimension] caster = itk.CastImageFilter[input_image_type, py_buffer_type].New() caster.SetInput(thresholded) progress = operator.progress.value itkutils.observe_filter_progress(operator, caster, progress, progress + next(step_pct)) try: caster.Update() except RuntimeError: return thresholded = caster.GetOutput() thresholded = otsu_filter.GetOutput() return thresholded
def get_python_voxel_type(dataset): """Return the Python type that can represent the voxel type in the dataset. The dataset can be either a VTK dataset or an ITK image. """ # Try treating dataset as a VTK data set first. try: # Set up map between VTK data type and Python type global _vtk_to_python_types if _vtk_to_python_types is None: import vtk _vtk_to_python_types = { vtk.VTK_UNSIGNED_CHAR: int, vtk.VTK_CHAR: int, vtk.VTK_UNSIGNED_SHORT: int, vtk.VTK_SHORT: int, vtk.VTK_UNSIGNED_INT: int, vtk.VTK_INT: int, vtk.VTK_UNSIGNED_LONG: int, vtk.VTK_LONG: int, vtk.VTK_FLOAT: float, vtk.VTK_DOUBLE: float } pd = dataset.GetPointData() scalars = pd.GetScalars() return _vtk_to_python_types[scalars.GetDataType()] except AttributeError as attribute_error: pass # If the above fails, treat dataset as an ITK image. try: # Set up map between ITK ctype and Python type. global _itkctype_to_python_types if _itkctype_to_python_types is None: import itkTypes _itkctype_to_python_types = { itkTypes.F: float, itkTypes.D: float, itkTypes.LD: float, itkTypes.UC: int, itkTypes.US: int, itkTypes.UI: int, itkTypes.UL: int, itkTypes.SC: int, itkTypes.SS: int, itkTypes.SI: int, itkTypes.SL: int, itkTypes.B: int } import itkExtras # Incantation for obtaining voxel type in ITK image ctype = itkExtras.template(type(dataset))[1][0] return _itkctype_to_python_types[ctype] except AttributeError as attribute_error: print("Could not get Python voxel type for dataset %s" % type(dataset)) print(attribute_error)
def transform_scalars(self, dataset, number_of_thresholds=1, enable_valley_emphasis=False): """This filter performs semi-automatic multithresholding of a data set. Voxels are automatically classified into a chosen number of classes such that inter-class variance of the voxel values is minimized. The output is a label map with one label per voxel class. """ # Initial progress self.progress.value = 0 self.progress.maximum = 100 # Approximate percentage of work completed after each step in the # transform STEP_PCT = [10, 20, 70, 90, 100] try: import itk import itkExtras import itkTypes from vtkmodules.vtkCommonDataModel import vtkImageData from tomviz import itkutils from tomviz import utils except Exception as exc: print("Could not import necessary module(s)") raise exc # Return values returnValues = None # Add a try/except around the ITK portion. ITK exceptions are # passed up to the Python layer, so we can at least report what # went wrong with the script, e.g,, unsupported image type. try: self.progress.value = STEP_PCT[0] self.progress.message = "Converting data to ITK image" # Get the ITK image itk_image = itkutils.convert_vtk_to_itk_image(dataset) itk_input_image_type = type(itk_image) # OtsuMultipleThresholdsImageFilter's wrapping requires that the # input and output image types be the same. itk_threshold_image_type = itk_input_image_type # Otsu multiple threshold filter otsu_filter = itk.OtsuMultipleThresholdsImageFilter[ itk_input_image_type, itk_threshold_image_type].New() otsu_filter.SetNumberOfThresholds(number_of_thresholds) otsu_filter.SetValleyEmphasis(enable_valley_emphasis) otsu_filter.SetInput(itk_image) itkutils.observe_filter_progress(self, otsu_filter, STEP_PCT[1], STEP_PCT[2]) try: otsu_filter.Update() except RuntimeError: return print("Otsu threshold(s): %s" % (otsu_filter.GetThresholds(),)) itk_image_data = otsu_filter.GetOutput() # Cast threshold output to an integral type if needed. py_buffer_type = itk_threshold_image_type voxel_type = itkExtras.template(itk_threshold_image_type)[1][0] if voxel_type is itkTypes.F or voxel_type is itkTypes.D: self.progress.message = "Casting output to integral type" # Unsigned char supports 256 labels, or 255 threshold levels. # This should be sufficient for all but the most unusual use # cases. py_buffer_type = itk.Image.UC3 caster = itk.CastImageFilter[itk_threshold_image_type, py_buffer_type].New() caster.SetInput(itk_image_data) itkutils.observe_filter_progress(self, caster, STEP_PCT[2], STEP_PCT[3]) try: caster.Update() except RuntimeError: return itk_image_data = caster.GetOutput() self.progress.value = STEP_PCT[3] self.progress.message = "Saving results" label_buffer = itk.PyBuffer[py_buffer_type] \ .GetArrayFromImage(itk_image_data) label_map_dataset = vtkImageData() label_map_dataset.CopyStructure(dataset) utils.set_array(label_map_dataset, label_buffer, isFortran=False) self.progress.value = STEP_PCT[4] # Set up dictionary to return operator results returnValues = {} returnValues["label_map"] = label_map_dataset except Exception as exc: print("Problem encountered while running %s" % self.__class__.__name__) raise exc return returnValues
def transform_scalars(self, dataset, number_of_thresholds=1, enable_valley_emphasis=False): """This filter performs semi-automatic multithresholding of a data set. Voxels are automatically classified into a chosen number of classes such that inter-class variance of the voxel values is minimized. The output is a label map with one label per voxel class. """ # Initial progress self.progress.value = 0 self.progress.maximum = 100 # Approximate percentage of work completed after each step in the # transform STEP_PCT = [10, 20, 70, 90, 100] try: import itk import itkExtras import itkTypes import vtk from tomviz import itkutils from tomviz import utils except Exception as exc: print("Could not import necessary module(s)") raise exc # Return values returnValues = None # Add a try/except around the ITK portion. ITK exceptions are # passed up to the Python layer, so we can at least report what # went wrong with the script, e.g,, unsupported image type. try: self.progress.value = STEP_PCT[0] self.progress.message = "Converting data to ITK image" # Get the ITK image itk_image = itkutils.convert_vtk_to_itk_image(dataset) itk_input_image_type = type(itk_image) # OtsuMultipleThresholdsImageFilter's wrapping requires that the # input and output image types be the same. itk_threshold_image_type = itk_input_image_type # Otsu multiple threshold filter otsu_filter = itk.OtsuMultipleThresholdsImageFilter[ itk_input_image_type, itk_threshold_image_type].New() otsu_filter.SetNumberOfThresholds(number_of_thresholds) otsu_filter.SetValleyEmphasis(enable_valley_emphasis) otsu_filter.SetInput(itk_image) itkutils.observe_filter_progress(self, otsu_filter, STEP_PCT[1], STEP_PCT[2]) try: otsu_filter.Update() except RuntimeError: return print("Otsu threshold(s): %s" % (otsu_filter.GetThresholds(),)) itk_image_data = otsu_filter.GetOutput() # Cast threshold output to an integral type if needed. py_buffer_type = itk_threshold_image_type voxel_type = itkExtras.template(itk_threshold_image_type)[1][0] if voxel_type is itkTypes.F or voxel_type is itkTypes.D: self.progress.message = "Casting output to integral type" # Unsigned char supports 256 labels, or 255 threshold levels. # This should be sufficient for all but the most unusual use # cases. py_buffer_type = itk.Image.UC3 caster = itk.CastImageFilter[itk_threshold_image_type, py_buffer_type].New() caster.SetInput(itk_image_data) itkutils.observe_filter_progress(self, caster, STEP_PCT[2], STEP_PCT[3]) try: caster.Update() except RuntimeError: return itk_image_data = caster.GetOutput() self.progress.value = STEP_PCT[3] self.progress.message = "Saving results" label_buffer = itk.PyBuffer[py_buffer_type] \ .GetArrayFromImage(itk_image_data) label_map_dataset = vtk.vtkImageData() label_map_dataset.CopyStructure(dataset) utils.set_array(label_map_dataset, label_buffer) self.progress.value = STEP_PCT[4] # Set up dictionary to return operator results returnValues = {} returnValues["label_map"] = label_map_dataset except Exception as exc: print("Problem encountered while running %s" % self.__class__.__name__) raise exc return returnValues