def test_kwargs(self): spatial_size = (32, 64, 128) test_image = np.random.rand(*spatial_size) with tempfile.TemporaryDirectory() as tempdir: filename = os.path.join(tempdir, "test_image.nii.gz") itk_np_view = itk.image_view_from_array(test_image) itk.imwrite(itk_np_view, filename) loader = LoadImage(image_only=True) reader = ITKReader(fallback_only=False) loader.register(reader) result = loader(filename) reader = ITKReader() img = reader.read(filename, fallback_only=False) result_raw = reader.get_data(img) result_raw = MetaTensor.ensure_torch_and_prune_meta(*result_raw) self.assertTupleEqual(result.shape, result_raw.shape)
def test_itk_reader(self, input_param, filenames, expected_shape): test_image = np.random.rand(128, 128, 128) with tempfile.TemporaryDirectory() as tempdir: for i, name in enumerate(filenames): filenames[i] = os.path.join(tempdir, name) itk_np_view = itk.image_view_from_array(test_image) itk.imwrite(itk_np_view, filenames[i]) result = LoadImage(**input_param)(filenames) if isinstance(result, tuple): result, header = result self.assertTrue("affine" in header) self.assertEqual(header["filename_or_obj"], os.path.join(tempdir, "test_image.nii.gz")) np_diag = np.diag([-1, -1, 1, 1]) np.testing.assert_allclose(header["affine"], np_diag) np.testing.assert_allclose(header["original_affine"], np_diag) self.assertTupleEqual(result.shape, expected_shape)
def test_itk_reader_multichannel(self): test_image = np.random.randint(0, 256, size=(256, 224, 3)).astype("uint8") with tempfile.TemporaryDirectory() as tempdir: filename = os.path.join(tempdir, "test_image.png") itk_np_view = itk.image_view_from_array(test_image, is_vector=True) itk.imwrite(itk_np_view, filename) for flag in (False, True): result = LoadImage(image_only=True, reader=ITKReader(reverse_indexing=flag))( Path(filename)) test_image = test_image.transpose(1, 0, 2) np.testing.assert_allclose(result[:, :, 0], test_image[:, :, 0]) np.testing.assert_allclose(result[:, :, 1], test_image[:, :, 1]) np.testing.assert_allclose(result[:, :, 2], test_image[:, :, 2])
def test_kwargs(self): spatial_size = (32, 64, 128) test_image = np.random.rand(*spatial_size) with tempfile.TemporaryDirectory() as tempdir: filename = os.path.join(tempdir, "test_image.nii.gz") itk_np_view = itk.image_view_from_array(test_image) itk.imwrite(itk_np_view, filename) loader = LoadImage(image_only=False) reader = ITKReader(fallback_only=False) loader.register(reader) result, header = loader(filename) reader = ITKReader() img = reader.read(filename, fallback_only=False) result_raw, header_raw = reader.get_data(img) np.testing.assert_allclose(header["spatial_shape"], header_raw["spatial_shape"]) self.assertTupleEqual(result.shape, result_raw.shape)
def image_from_xarray(data_array): """Convert an xarray.DataArray to an itk.Image. Metadata encoded with xarray_from_image is applied to the itk.Image. This interface is and behavior is experimental and is subject to possible future changes.""" import numpy as np import itk spatial_dims = list({'z', 'y', 'x'}.intersection(set(data_array.dims))) spatial_dims.sort(reverse=True) spatial_dimension = len(spatial_dims) ordered_dims = ('z', 'y', 'x')[-spatial_dimension:] if ordered_dims != tuple(spatial_dims): raise ValueError( 'Spatial dimensions do not have the required order: ' + str(ordered_dims)) is_vector = False if spatial_dimension < len(data_array.dims): is_vector = True itk_image = itk.image_view_from_array(data_array.values, is_vector=is_vector) origin = [0.0] * spatial_dimension spacing = [1.0] * spatial_dimension for index, dim in enumerate(spatial_dims): origin[index] = float(data_array.coords[dim][0]) spacing[index] = float(data_array.coords[dim][1]) - float( data_array.coords[dim][0]) spacing.reverse() itk_image.SetSpacing(spacing) origin.reverse() itk_image.SetOrigin(origin) if 'direction' in data_array.attrs: direction = data_array.attrs['direction'] itk_image.SetDirection(np.flip(direction)) return itk_image
def set_air_external(img_file, structure_file, output_img_file): """Set all HUs outside of BODY/EXTERNAL contour to air HU=-1000 The img_file must be the .mhd """ img = itk.imread(img_file) ds = pydicom.dcmread(structure_file) contour = get_external_name(structure_file) # MODIFYING GATETOOLS; get_mask() disn't work for HFP setup aroi = roiutils.region_of_interest(ds, contour) mask = aroi.get_mask(img, corrected=False) #itk.imwrite(mask, "mask.mhd") ''' aroi = rt.region_of_interest( ds, contour) mask = aroi.get_mask(img, corrected=False) # NOTE: if corrected=True mask has dtype=np.float32; if not dtype=np.uint8 ''' pix_mask = itk.array_view_from_image(mask) pix_img = itk.array_view_from_image(img) if (pix_mask.shape != pix_img.shape): print("Inconsistent shapes of mask and image") pix_img_flat = pix_img.flatten() for i, val in enumerate(pix_mask.flatten()): if val == 0: pix_img_flat[i] = HU_AIR pix_img = pix_img_flat.reshape(pix_img.shape) img_modified = itk.image_view_from_array(pix_img) img_modified.CopyInformation(img) #img_modified.SetSpacing( img.GetSpacing() ) # "ElementSpacing" in .mhd #img_modified.SetOrigin( img.GetOrigin() ) # "Offset" in .mhd itk.imwrite(img_modified, output_img_file)
def image_from_xarray(data_array): """Convert an xarray.DataArray to an itk.Image. Metadata encoded with xarray_from_image is applied to the itk.Image. This interface is and behavior is experimental and is subject to possible future changes.""" import numpy as np import itk spatial_dims = list({"z", "y", "x"}.intersection(set(data_array.dims))) spatial_dims.sort(reverse=True) spatial_dimension = len(spatial_dims) ordered_dims = ("z", "y", "x")[-spatial_dimension:] if ordered_dims != tuple(spatial_dims): raise ValueError( "Spatial dimensions do not have the required order: " + str(ordered_dims)) is_vector = "c" in data_array.dims itk_image = itk.image_view_from_array(data_array.values, is_vector=is_vector) l_origin = [0.0] * spatial_dimension l_spacing = [1.0] * spatial_dimension for l_index, dim in enumerate(spatial_dims): coords = data_array.coords[dim] if coords.shape[0] > 1: l_origin[l_index] = float(coords[0]) l_spacing[l_index] = float(coords[1]) - float(coords[0]) l_spacing.reverse() itk_image.SetSpacing(l_spacing) l_origin.reverse() itk_image.SetOrigin(l_origin) if "direction" in data_array.attrs: direction = data_array.attrs["direction"] itk_image.SetDirection(np.flip(direction)) return itk_image
def test_load_nifti_multichannel(self): test_image = np.random.randint(0, 256, size=(31, 64, 16, 2)).astype(np.float32) with tempfile.TemporaryDirectory() as tempdir: filename = os.path.join(tempdir, "test_image.nii.gz") itk_np_view = itk.image_view_from_array(test_image, is_vector=True) itk.imwrite(itk_np_view, filename) itk_img = LoadImage(image_only=True, reader=ITKReader())(Path(filename)) self.assertTupleEqual(tuple(itk_img.shape), (16, 64, 31, 2)) nib_image = LoadImage( image_only=True, reader=NibabelReader(squeeze_non_spatial_dims=True))( Path(filename)) self.assertTupleEqual(tuple(nib_image.shape), (16, 64, 31, 2)) np.testing.assert_allclose(itk_img, nib_image, atol=1e-3, rtol=1e-3)
def set_air_external(image, structure_file): """Set all HUs outside of BODY/EXTERNAL contour to air HU=-1000 The img_file must be the .mhd """ img = None if type(image) == str: #Assume we have file path img = itk.imread(image) else: #Assume we have itk image object img = image ds = pydicom.dcmread(structure_file) contour = get_external_name(structure_file) #contour = "zPatient" # get_mask() doesn't work for HFP setup; need to reorientate aroi = roiutils.region_of_interest(ds, contour) mask = aroi.get_mask(img, corrected=False) pix_mask = itk.array_view_from_image(mask) pix_img = itk.array_view_from_image(img) if (pix_mask.shape != pix_img.shape): print("Inconsistent shapes of mask and image") pix_img_flat = pix_img.flatten() for i, val in enumerate(pix_mask.flatten()): if val == 0: pix_img_flat[i] = HU_AIR #pix_img_flat[i] = 0 pix_img = pix_img_flat.reshape(pix_img.shape) img_modified = itk.image_view_from_array(pix_img) img_modified.CopyInformation(img) return img_modified
def test_image_layer_from_image_rgb(): data = np.random.randint(256, size=(10, 10, 3), dtype=np.uint8) image = itk.image_view_from_array(data, itk.RGBPixel[itk.UC]) image_layer = itk_napari_conversion.image_layer_from_image(image) assert np.array_equal(data, image_layer.data) assert image_layer.rgb is True
) # Test .astype for conversion between vector-like pixel types. components = 3 numpyImage = np.random.randint(0, 256, (12, 8, components)).astype(np.uint8) input_image = itk.image_from_array(numpyImage, is_vector=True) if type(input_image) == itk.Image[itk.RGBPixel[itk.UC], 2] and hasattr( itk.CastImageFilter, "IRGBUC2IVF32" ): output_pixel_type = itk.Vector[itk.F, components] output_image = input_image.astype(output_pixel_type) assert type(output_image) == itk.Image[output_pixel_type, 2] if "(<itkCType unsigned char>, 4)" in itk.Image.GetTypesAsList(): arr = np.random.randint(0, 255, size=(3, 4, 5, 6), dtype=np.uint8) image = itk.image_view_from_array(arr) arr_back = itk.array_view_from_image(image) assert np.allclose(arr, arr_back) image = itk.image_from_array(arr) arr_back = itk.array_from_image(image) assert np.allclose(arr, arr_back) # xarray conversion try: import xarray as xr print("Testing xarray conversion") image = itk.imread(filename) image.SetSpacing((0.1, 0.2))
n1 = (np_image.shape[1]-patch_size[0])/stride_1 + 1 n2 = (np_image.shape[2]-patch_size[1])/stride_2 + 1 n3 = (np_image.shape[3]-patch_size[2])/stride_3 + 1 # create patches covering the entire image image_patches = tensor_image.unfold(1, patch_size[0], get_stride(np_image.shape[1], patch_size[0])).unfold(2, patch_size[1], get_stride(np_image.shape[2], patch_size[1])).unfold(3, patch_size[2], get_stride(np_image.shape[3], patch_size[2])) image_patches = image_patches.reshape(-1, 1, patch_size[0], patch_size[1], patch_size[2]) patch_output = np.zeros(image_patches.shape) for i_patch in range(image_patches.shape[0]): tensor_prob_output = model(image_patches[i_patch, :, :, :, :,].view(-1, num_channels, patch_size[0], patch_size[1], patch_size[2]).to(device, dtype=torch.float)).detach() patch_prob_output = tensor_prob_output.cpu().numpy() for i_label in range(num_classes): patch_output[i_patch, np.argmax(patch_prob_output[:], axis=1)==i_label] = i_label # squeeze patch_output = np.squeeze(patch_output, axis=1) # self fold function: combine patch results i_patch = 0 for k in range(int(n1)): for j in range(int(n2)): for i in range(int(n3)): predict_label[0+int(stride_1*k):patch_size[0]+int(stride_1*k), 0+int(stride_2*j):patch_size[1]+int(stride_2*j), 0+int(stride_3*i):patch_size[2]+int(stride_3*i)] = patch_output[i_patch, :] i_patch += 1 # output result itk_predict_label = itk.image_view_from_array(predict_label) itk.imwrite(itk_predict_label, os.path.join(output_path, 'Sample_{}_predicted.nrrd'.format(i_sample)))
def test_image_layer_from_image(): data = np.random.randint(256, size=(10, 10), dtype=np.uint8) image = itk.image_view_from_array(data) image_layer = itk_napari_conversion.image_layer_from_image(image) assert np.array_equal(data, image_layer.data)
def image_filter_wrapper(*args, **kwargs): have_array_input = False have_xarray_input = False have_torch_input = False args_list = list(args) for index, arg in enumerate(args): if _HAVE_XARRAY and isinstance(arg, xr.DataArray): have_xarray_input = True image = itk.image_from_xarray(arg) args_list[index] = image elif _HAVE_TORCH and isinstance(arg, torch.Tensor): have_torch_input = True image = itk.image_view_from_array(np.asarray(arg)) args_list[index] = image elif not isinstance(arg, itk.Object) and is_arraylike(arg): have_array_input = True array = np.asarray(arg) image = itk.image_view_from_array(array) args_list[index] = image potential_image_input_kwargs = ('input', 'input1', 'input2', 'input3') for key, value in kwargs.items(): if (key.lower() in potential_image_input_kwargs or "image" in key.lower()): if _HAVE_XARRAY and isinstance(value, xr.DataArray): have_xarray_input = True image = itk.image_from_xarray(value) kwargs[key] = image elif _HAVE_TORCH and isinstance(value, torch.Tensor): have_torch_input = True image = itk.image_view_from_array(np.asarray(value)) kwargs[key] = image elif not isinstance(value, itk.Object) and is_arraylike(value): have_array_input = True array = np.asarray(value) image = itk.image_view_from_array(array) kwargs[key] = image if have_xarray_input or have_torch_input or have_array_input: # Convert output itk.Image's to numpy.ndarray's output = image_filter(*tuple(args_list), **kwargs) if isinstance(output, tuple): output_list = list(output) for index, value in output_list: if isinstance(value, itk.Image): if have_xarray_input: data_array = itk.xarray_from_image(value) output_list[index] = data_array elif have_torch_input: data_array = itk.array_view_from_image(value) torch_tensor = torch.from_numpy(data_array) output_list[index] = torch_tensor else: array = itk.array_view_from_image(value) output_list[index] = array return tuple(output_list) else: if isinstance(output, itk.Image): if have_xarray_input: output = itk.xarray_from_image(output) elif have_torch_input: output = itk.array_view_from_image(output) output = torch.from_numpy(output) else: output = itk.array_view_from_image(output) return output else: return image_filter(*args, **kwargs)
def to_itk_image(image_like): if isinstance(image_like, (itk.Image, itk.VectorImage)): return image_like if is_arraylike(image_like): array = np.asarray(image_like) can_use_view = array.flags['OWNDATA'] if have_dask and isinstance(image_like, dask.array.core.Array): can_use_view = False array = np.ascontiguousarray(array) # JavaScript does not support 64-bit integers if array.dtype == np.int64: array = array.astype(np.float32) elif array.dtype == np.uint64: array = array.astype(np.float32) if can_use_view: image_from_array = itk.image_view_from_array(array) else: image_from_array = itk.image_from_array(array) return image_from_array elif have_vtk and isinstance(image_like, vtk.vtkImageData): from vtk.util import numpy_support as vtk_numpy_support array = vtk_numpy_support.vtk_to_numpy( image_like.GetPointData().GetScalars()) dims = list(image_like.GetDimensions()) spacing = list(image_like.GetSpacing()) origin = list(image_like.GetOrigin()) # Check for zdim==1 zdim = dims.pop() if zdim > 1: # zdim>1, put it back in the dims array dims.append(zdim) else: #zdim==1, remove z-spacing and z-origin spacing.pop() origin.pop() array.shape = dims[::-1] image_from_array = itk.image_view_from_array(array) image_from_array.SetSpacing(spacing) image_from_array.SetOrigin(origin) return image_from_array elif have_simpleitk and isinstance(image_like, sitk.Image): array = sitk.GetArrayViewFromImage(image_like) image_from_array = itk.image_view_from_array(array) image_from_array.SetSpacing(image_like.GetSpacing()) image_from_array.SetOrigin(image_like.GetOrigin()) direction = image_like.GetDirection() npdirection = np.asarray(direction) npdirection = np.reshape(npdirection, (-1, image_like.GetDimension())) itkdirection = itk.matrix_from_array(npdirection) image_from_array.SetDirection(itkdirection) return image_from_array elif have_imagej: import imglyb if isinstance(image_like, imglyb.util.ReferenceGuardingRandomAccessibleInterval): array = imglyb.to_numpy(image_like) image_from_array = itk.image_view_from_array(array) return image_from_array elif isinstance(image_like, itk.ProcessObject): return itk.output(image_like) return None
# Read input image itk_image = itk.imread(input_filename) # Run filters on itk.Image # View only of itk.Image, data is not copied np_view = itk.array_view_from_image(itk_image) # Copy of itk.Image, data is copied np_copy = itk.array_from_image(itk_image) # Do NumPy stuff... # Convert back to ITK, view only, data is not copied itk_np_view = itk.image_view_from_array(np_copy) # Convert back to ITK, data is copied itk_np_copy = itk.image_from_array(np_copy) # Save result itk.imwrite(itk_np_view, output_filename) # VNL matrix from array arr = np.zeros([3, 3], np.uint8) matrix = itk.vnl_matrix_from_array(arr) # Array from VNL matrix arr = itk.array_from_vnl_matrix(matrix) # VNL vector from array
def image_filter_wrapper(*args, **kwargs): have_array_input = False have_xarray_input = False have_torch_input = False args_list = list(args) for index, arg in enumerate(args): if _HAVE_XARRAY and isinstance(arg, xr.DataArray): have_xarray_input = True image = itk.image_from_xarray(arg) args_list[index] = image elif _HAVE_TORCH and isinstance(arg, torch.Tensor): have_torch_input = True channels = arg.shape[0] # assume first dimension is channels arr = np.asarray(arg) if channels > 1: # change from contiguous to interleaved channel order arr = move_last_dimension_to_first(arr) image = itk.image_view_from_array(arr, is_vector=channels > 1) args_list[index] = image elif not isinstance(arg, itk.Object) and is_arraylike(arg): have_array_input = True array = np.asarray(arg) image = itk.image_view_from_array(array) args_list[index] = image potential_image_input_kwargs = ("input", "input1", "input2", "input3") for key, value in kwargs.items(): if key.lower( ) in potential_image_input_kwargs or "image" in key.lower(): if _HAVE_XARRAY and isinstance(value, xr.DataArray): have_xarray_input = True image = itk.image_from_xarray(value) kwargs[key] = image elif _HAVE_TORCH and isinstance(value, torch.Tensor): have_torch_input = True channels = value.shape[ 0] # assume first dimension is channels arr = np.asarray(value) if ( channels > 1 ): # change from contiguous to interleaved channel order arr = move_last_dimension_to_first(arr) image = itk.image_view_from_array(arr, is_vector=channels > 1) kwargs[key] = image elif not isinstance(value, itk.Object) and is_arraylike(value): have_array_input = True array = np.asarray(value) image = itk.image_view_from_array(array) kwargs[key] = image if have_xarray_input or have_torch_input or have_array_input: # Convert output itk.Image's to numpy.ndarray's output = image_filter(*tuple(args_list), **kwargs) if isinstance(output, tuple): output_list = list(output) for index, value in enumerate(output_list): if isinstance(value, itk.Image): if have_xarray_input: data_array = itk.xarray_from_image(value) output_list[index] = data_array elif have_torch_input: channels = value.GetNumberOfComponentsPerPixel() data_array = itk.array_view_from_image(value) if ( channels > 1 ): # change from interleaved to contiguous channel order data_array = move_first_dimension_to_last( data_array) torch_tensor = torch.from_numpy(data_array) output_list[index] = torch_tensor else: array = itk.array_view_from_image(value) output_list[index] = array return tuple(output_list) else: if isinstance(output, itk.Image): if have_xarray_input: output = itk.xarray_from_image(output) elif have_torch_input: channels = output.GetNumberOfComponentsPerPixel() output = itk.array_view_from_image(output) if ( channels > 1 ): # change from interleaved to contiguous channel order output = move_first_dimension_to_last(output) output = torch.from_numpy(output) else: output = itk.array_view_from_image(output) return output else: return image_filter(*args, **kwargs)
import itk import time # open image and psf imgName = '/home/bnorthan/Images/fromMM/ex6-2_CamB_ch0_CAM1_stack0198_488nm_8662163msec_0009953958msecAbs_000x_000y_000z_0000t.tif' psfName = '/home/bnorthan/Images/fromMM/PSF_488nm_dz100nm.tif' img = io.imread(imgName).astype(np.float32) # crop image so it fits on the GPU img = np.ascontiguousarray(img[:, 256:-256, 128:-128]) print(img.shape) psf = io.imread(psfName).astype(np.float32) print(psf.shape) print(psf.sum()) psf = psf / (psf.sum()) print(psf.sum()) imgitk = itk.image_view_from_array(img) # Convert to ITK object psfitk = itk.image_view_from_array(psf) # Convert to ITK object print('try with ITK') start = time.time() deconvolved = itk.richardson_lucy_deconvolution_image_filter( imgitk, kernel_image=psfitk, number_of_iterations=100) end = time.time() print(end - start) result_itk = itk.array_from_image(deconvolved) io.imsave('/home/bnorthan/Images/fromMM/result_itk.tif', result_itk)