def process_image(filename, output_folder, sigma): """ Reorient image at filename, smooth with sigma, clamp and save to output_folder. :param filename: The image filename. :param output_folder: The output folder. :param sigma: Sigma for smoothing. """ basename = os.path.basename(filename) basename_wo_ext = basename[:basename.find('.nii.gz')] print(basename_wo_ext) ImageType = itk.Image[itk.SS, 3] reader = itk.ImageFileReader[ImageType].New() reader.SetFileName(filename) image = reader.GetOutput() reoriented = reorient_to_rai(image) if not basename_wo_ext.endswith('_seg'): reoriented = smooth(reoriented, sigma) reoriented = clamp(reoriented) reoriented.SetOrigin([0, 0, 0]) m = itk.GetMatrixFromArray( np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]], np.float64)) reoriented.SetDirection(m) reoriented.Update() itk.imwrite(reoriented, os.path.join(output_folder, basename_wo_ext + '.nii.gz'))
def reorient_to_rai(image): # Reorient image to RAI orientation. filter = itk.OrientImageFilter.New(image) filter.UseImageDirectionOn() filter.SetInput(image) m = itk.GetMatrixFromArray(np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]], np.float64)) filter.SetDesiredCoordinateDirection(m) filter.Update() reoriented = filter.GetOutput() return reoriented
def sitk_to_itk(sitk_image): """ Helper function to convert SimpleITK images to ITK images """ sitk_arr = sitk.GetArrayFromImage(sitk_image) itk_image = itk.GetImageFromArray(sitk_arr, is_vector=False) itk_image.SetOrigin(sitk_image.GetOrigin()) itk_image.SetSpacing(sitk_image.GetSpacing()) itk_image.SetDirection( itk.GetMatrixFromArray( np.reshape(np.array(sitk_image.GetDirection()), [3] * 2))) return itk_image
def create_backend_obj( cls, data_array: NdarrayOrTensor, channel_dim: Optional[int] = 0, affine: Optional[NdarrayOrTensor] = None, dtype: DtypeLike = np.float32, affine_lps_to_ras: bool = True, **kwargs, ): """ Create an ITK object from ``data_array``. This method assumes a 'channel-last' ``data_array``. Args: data_array: input data array. channel_dim: channel dimension of the data array. This is used to create a Vector Image if it is not ``None``. affine: affine matrix of the data array. This is used to compute `spacing`, `direction` and `origin`. dtype: output data type. affine_lps_to_ras: whether to convert the affine matrix from "LPS" to "RAS". Defaults to ``True``. Set to ``True`` to be consistent with ``NibabelWriter``, otherwise the affine matrix is assumed already in the ITK convention. kwargs: keyword arguments. Current `itk.GetImageFromArray` will read ``ttype`` from this dictionary. see also: - https://github.com/InsightSoftwareConsortium/ITK/blob/v5.2.1/Wrapping/Generators/Python/itk/support/extras.py#L389 """ data_array = super().create_backend_obj(data_array) _is_vec = channel_dim is not None if _is_vec: data_array = np.moveaxis(data_array, -1, 0) # from channel last to channel first data_array = data_array.T.astype(dtype, copy=True, order="C") itk_obj = itk.GetImageFromArray(data_array, is_vector=_is_vec, ttype=kwargs.pop("ttype", None)) d = len(itk.size(itk_obj)) if affine is None: affine = np.eye(d + 1, dtype=np.float64) _affine = convert_data_type(affine, np.ndarray)[0] if affine_lps_to_ras: _affine = orientation_ras_lps(to_affine_nd(d, _affine)) spacing = affine_to_spacing(_affine, r=d) _direction: np.ndarray = np.diag(1 / spacing) _direction = _affine[:d, :d] @ _direction itk_obj.SetSpacing(spacing.tolist()) itk_obj.SetOrigin(_affine[:d, -1].tolist()) itk_obj.SetDirection(itk.GetMatrixFromArray(_direction)) return itk_obj
def process_image(filename, output_folder, sigma): basename = os.path.basename(filename) basename_wo_ext = basename[:basename.find('.nii.gz')] print(basename_wo_ext) ImageType = itk.Image[itk.SS, 3] reader = itk.ImageFileReader[ImageType].New() reader.SetFileName(filename) image = reader.GetOutput() reoriented = reorient_to_rai(image) smoothed = smooth(reoriented, sigma) clamped = clamp(smoothed) clamped.SetOrigin([0, 0, 0]) m = itk.GetMatrixFromArray( np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]], np.float64)) clamped.SetDirection(m) clamped.Update() itk.imwrite(clamped, os.path.join(output_folder, basename_wo_ext + '.nii.gz'))
assert m1.get(0, 0) == m_np[0, 0] m_np[0, 0] = 0 assert m1.get(0, 0) != m_np[0, 0] view = itk.GetArrayViewFromVnlMatrix(m1) assert m1.get(0, 0) == view[0, 0] view[0, 0] = 0 assert m1.get(0, 0) == view[0, 0] arr = np.zeros([3, 3]) m_vnl = itk.GetVnlMatrixFromArray(arr) assert m_vnl(0, 0) == 0 m_vnl.put(0, 0, 3) assert m_vnl(0, 0) == 3 assert arr[0, 0] == 0 # ITK Matrix arr = np.zeros([3, 3], float) m_itk = itk.GetMatrixFromArray(arr) # Test snake case function m_itk = itk.matrix_from_array(arr) m_itk.SetIdentity() # Test that the numpy array has not changed,... assert arr[0, 0] == 0 # but that the ITK matrix has the correct value. assert m_itk(0, 0) == 1 arr2 = itk.GetArrayFromMatrix(m_itk) # Check that snake case function also works arr2 = itk.array_from_matrix(m_itk) # Check that the new array has the new value. assert arr2[0, 0] == 1 arr2[0, 0] = 2 # Change the array value,... assert arr2[0, 0] == 2
image_folder = '/home/gdp/data/spine_large/VerSeg_complete/VerSeg/image' output_folder = '/home/gdp/data/spine_large/VerSeg_complete/VerSeg/image_reorient' if not os.path.exists(output_folder): os.makedirs(output_folder) filenames = glob(os.path.join(image_folder, '*.nii.gz')) for filename in sorted(filenames): # filename = '/home/D/glo/Data/spine_seg_data/VerSe2020/training_data/segmentation/verse503_seg.nii.gz' basename = os.path.basename(filename) basename_wo_ext = basename[:basename.find('.nii.gz')] out_file_name = os.path.join(output_folder, basename_wo_ext + '.nii.gz') print(basename_wo_ext) # # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~reorient image = itk.imread(os.path.join(image_folder, basename_wo_ext + '.nii.gz')) reoriented = reorient_to_rai(image) m = itk.GetMatrixFromArray(np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]], np.float64)) reoriented.SetDirection(m) reoriented.Update() itk.imwrite(reoriented, out_file_name) print('done') # # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ resample # image = sitk.ReadImage(out_file_name) # resampled = resample(image, out_spacing=(1, 1, 1), is_label=True) # resampled = sitk.GetArrayFromImage(resampled) # resampled[resampled<0] = 0 # resampled = sitk.GetImageFromArray(resampled) # resampled.SetOrigin([0, 0, 0]) # resampled.SetSpacing((1, 1, 1)) # sitk.WriteImage(resampled, out_file_name) print()
def compute(self, transform_parameters): """Generates a DRR given the transform parameters. Args: transform_parameters (list of floats): rotX, rotY,rotZ, transX, transY, transZ """ # Get transform parameters rotx = transform_parameters[0] roty = transform_parameters[1] rotz = transform_parameters[2] tx = transform_parameters[3] ty = transform_parameters[4] tz = transform_parameters[5] # position movement # compute the transformation matrix and its inverse (itk always needs the inverse) Tr = rm.get_rigid_motion_mat_from_euler(rotz, 'z', rotx, 'x', roty, 'y', 0, 0, 0) self.movDirectionMatrix = itk.GetArrayFromMatrix(self.movDirection) self.movDirectionMatrix = Tr[:3,:3] self.movDirection = itk.GetMatrixFromArray(self.movDirectionMatrix) self.movDirectionMatrix01 = itk.GetArrayFromMatrix(self.movDirection) #tDRR1 = time.time() DRR = self.DRR movImageInfo = self.movImageInfo projector_info = self.projector_info PhyImageType = self.PhyImageType self.DRRorigin = itk.Point[itk.F, self.Dimension]() self.DRRorigin[0] = movImageInfo['Volume_center'][0] - projector_info['DRR_ppx'] - self.DRRspacing[0]*(self.DRRsize[0] - 1.) / 2. + tx self.DRRorigin[1] = movImageInfo['Volume_center'][1] + projector_info['focal_lenght'] + ty #/ 2. self.DRRorigin[2] = movImageInfo['Volume_center'][2] - projector_info['DRR_ppy'] - self.DRRspacing[2]*(self.DRRsize[2] - 1.) / 2. + tz DRR.SetRegions(self.DRRregion) DRR.Allocate() DRR.SetSpacing(self.DRRspacing) DRR.SetOrigin(self.DRRorigin) #print(self.movDirection) DRR.SetDirection(self.movDirection) # Get array of physical coordinates for the DRR at the initial position PhysicalPointImagefilter=itk.PhysicalPointImageSource[PhyImageType].New() PhysicalPointImagefilter.SetReferenceImage(DRR) PhysicalPointImagefilter.SetUseReferenceImage(True) PhysicalPointImagefilter.Update() sourceDRR = PhysicalPointImagefilter.GetOutput() #self.sourceDRR_array_to_reshape = itk.PyBuffer[PhyImageType].GetArrayFromImage(sourceDRR)[0].copy(order = 'C') # array has to be reshaped for matrix multiplication self.sourceDRR_array_to_reshape = itk.GetArrayFromImage(sourceDRR)#[:,0] # array has to be reshaped for matrix multiplication # compute the transformation matrix and its inverse (itk always needs the inverse) Tr = rm.get_rigid_motion_mat_from_euler(0, 'z', 0, 'x', 0, 'y', 0, projector_info['focal_lenght'], 0) invT = np.linalg.inv(Tr) # very important conversion to float32, otherwise the code crashes # Move source point with transformation matrix source_transformed = np.dot(invT, np.array([self.source[0],self.source[1],self.source[2], 1.]).T)[0:3] source_forGpu = np.array([ source_transformed[0], source_transformed[1], source_transformed[2] ], dtype=np.float32) # Instantiate new 3D DRR image at its initial position (at +focal length along the z direction) newDRR = self.ImageType.New() newMask = self.MaskType.New() newLung = self.MaskType.New() newValue = self.MaskType.New() newDRR.SetRegions(self.DRRregion) newMask.SetRegions(self.DRRregion) newLung.SetRegions(self.DRRregion) newValue.SetRegions(self.DRRregion) newDRR.Allocate() newMask.Allocate() newLung.Allocate() newValue.Allocate() newDRR.SetSpacing(self.DRRspacing) newMask.SetSpacing(self.DRRspacing) newLung.SetSpacing(self.DRRspacing) newValue.SetSpacing(self.DRRspacing) newDRR.SetOrigin(self.DRRorigin) newMask.SetOrigin(self.DRRorigin) newLung.SetOrigin(self.DRRorigin) newValue.SetOrigin(self.DRRorigin) self.movDirection.SetIdentity() newDRR.SetDirection(self.movDirection) newMask.SetDirection(self.movDirection) newLung.SetDirection(self.movDirection) newValue.SetDirection(self.movDirection) # Get 3d array for DRR (where to store the final output, in the image plane that in fact does not move) #newDRRArray = itk.PyBuffer[self.ImageType].GetArrayFromImage(newDRR) newDRRArray = itk.GetArrayViewFromImage(newDRR) newMaskArray = itk.GetArrayViewFromImage(newMask) newLungArray = itk.GetArrayViewFromImage(newLung) newValueArray = itk.GetArrayViewFromImage(newValue) #tDRR3 = time.time() # Get array of physical coordinates of the transformed DRR sourceDRR_array_reshaped = self.sourceDRR_array_to_reshape.reshape((self.DRRsize[0]*self.DRRsize[2], self.Dimension), order = 'C') sourceDRR_array_transformed = np.dot(invT, rm.augment_matrix_coord(sourceDRR_array_reshaped))[0:3].T # apply inverse transform to detector plane, augmentation is needed for multiplication with rigid motion matrix sourceDRR_array_transf_to_ravel = sourceDRR_array_transformed.reshape((self.DRRsize[0],self.DRRsize[2], self.Dimension), order = 'C') DRRPhy_array = np.ravel(sourceDRR_array_transf_to_ravel, order = 'C').astype(np.float32) # Generate DRR #tGpu3 = time.time() output, output_mask, output_mask_lung, output_mask_value = self.projector.generateDRR(source_forGpu,DRRPhy_array) #tGpu4 = time.time() # Reshape copy output_reshaped = np.reshape(output, (self.DRRsize[2], self.DRRsize[1], self.DRRsize[0]), order='C') # no guarantee about memory contiguity output_mask_reshaped = np.reshape(output_mask, (self.DRRsize[2], self.DRRsize[1], self.DRRsize[0]), order='C') output_mask_lung_reshaped = np.reshape(output_mask_lung, (self.DRRsize[2], self.DRRsize[1], self.DRRsize[0]), order='C') # no guarantee about memory contiguity output_mask_value_reshaped = np.reshape(output_mask_value, (self.DRRsize[2], self.DRRsize[1], self.DRRsize[0]), order='C') #output_reshaped = np.reshape(output, (self.DRRsize[2], self.DRRsize[0]), order='C') # no guarantee about memory contiguity # Re-copy into original image array, hence into original image (since the former is just a view of the latter) newDRRArray.setfield(output_reshaped, newDRRArray.dtype) newMaskArray.setfield(output_mask_reshaped, newMaskArray.dtype) newLungArray.setfield(output_mask_lung_reshaped, newLungArray.dtype) newValueArray.setfield(output_mask_value_reshaped, newValueArray.dtype) # Redim filter to convert the DRR from 3D slice to 2D image (necessary for further metric comparison) filterRedim = itk.ExtractImageFilter[self.ImageType, self.ImageType2D].New() filterRedim.InPlaceOn() filterRedim.SetDirectionCollapseToSubmatrix() filterRedim_mask = itk.ExtractImageFilter[self.MaskType, self.MaskType2D].New() filterRedim_mask.InPlaceOn() filterRedim_mask.SetDirectionCollapseToSubmatrix() filterRedim_lung = itk.ExtractImageFilter[self.MaskType, self.MaskType2D].New() filterRedim_lung.InPlaceOn() filterRedim_lung.SetDirectionCollapseToSubmatrix() filterRedim_value = itk.ExtractImageFilter[self.MaskType, self.MaskType2D].New() filterRedim_value.InPlaceOn() filterRedim_value.SetDirectionCollapseToSubmatrix() newDRR.UpdateOutputInformation() # important, otherwise the following filterRayCast.GetOutput().GetLargestPossibleRegion() returns an empty image newMask.UpdateOutputInformation() newLung.UpdateOutputInformation() newValue.UpdateOutputInformation() size_input = newDRR.GetLargestPossibleRegion().GetSize() start_input = newDRR.GetLargestPossibleRegion().GetIndex() size_output = [0]*self.Dimension size_output[0] = size_input[0] size_output[1] = 0 size_output[2] = size_input[2] sliceNumber = 0 start_output = [0]*self.Dimension start_output[0] = start_input[0] start_output[1] = sliceNumber start_output[2] = start_input[2] desiredRegion = self.RegionType() desiredRegion.SetSize( size_output ) desiredRegion.SetIndex( start_output ) filterRedim.SetExtractionRegion( desiredRegion ) filterRedim_mask.SetExtractionRegion( desiredRegion ) filterRedim_lung.SetExtractionRegion( desiredRegion ) filterRedim_value.SetExtractionRegion( desiredRegion ) filterRedim.SetInput(newDRR) filterRedim_mask.SetInput(newMask) filterRedim_lung.SetInput(newLung) filterRedim_value.SetInput(newValue) #tDRR2 = time.time() filterRedim.Update() filterRedim_mask.Update() filterRedim_lung.Update() filterRedim_value.Update() #print( '\nTime elapsed for generation of DRR: ', tDRR2 - tDRR1) return filterRedim.GetOutput(), filterRedim_mask.GetOutput(), filterRedim_lung.GetOutput(), filterRedim_value.GetOutput()