def test_warp_image_ddf(): """ Test warp_image_ddf by checking input/output shapes """ batch_size = 2 fixed_image_size = (32, 32, 16) moving_image_size = (24, 24, 16) channel = 6 image = tf.ones((batch_size, *moving_image_size), dtype="float32") image_ch = tf.ones((batch_size, *moving_image_size, channel), dtype="float32") ddf = tf.ones((batch_size, *fixed_image_size, 3), dtype="float32") grid_ref = tf.ones((1, *fixed_image_size, 3), dtype="float32") # without channel, with grid_ref got = layer_util.warp_image_ddf(image=image, ddf=ddf, grid_ref=grid_ref) assert got.shape == (batch_size, *fixed_image_size) # without channel, without grid_ref got = layer_util.warp_image_ddf(image=image, ddf=ddf, grid_ref=None) assert got.shape == (batch_size, *fixed_image_size) # with channel, with grid_ref got = layer_util.warp_image_ddf(image=image_ch, ddf=ddf, grid_ref=grid_ref) assert got.shape == (batch_size, *fixed_image_size, channel) # with channel, without grid_ref got = layer_util.warp_image_ddf(image=image_ch, ddf=ddf, grid_ref=None) assert got.shape == (batch_size, *fixed_image_size, channel) # wrong image shape wrong_image = tf.ones(moving_image_size, dtype="float32") with pytest.raises(ValueError) as err_info: layer_util.warp_image_ddf(image=wrong_image, ddf=ddf, grid_ref=grid_ref) assert "image shape must be (batch, m_dim1, m_dim2, m_dim3)" in str( err_info.value) # wrong ddf shape wrong_ddf = tf.ones((batch_size, *fixed_image_size, 2), dtype="float32") with pytest.raises(ValueError) as err_info: layer_util.warp_image_ddf(image=image, ddf=wrong_ddf, grid_ref=grid_ref) assert "ddf shape must be (batch, f_dim1, f_dim2, f_dim3, 3)" in str( err_info.value) # wrong grid_ref shape wrong_grid_ref = tf.ones((batch_size, *moving_image_size, 3), dtype="float32") with pytest.raises(ValueError) as err_info: layer_util.warp_image_ddf(image=image, ddf=ddf, grid_ref=wrong_grid_ref) assert "grid_ref shape must be (1, f_dim1, f_dim2, f_dim3, 3) or None" in str( err_info.value)
def gif_warp( img_paths, ddf_path, slice_inds=None, num_interval=100, interval=50, save_path="" ): """ Apply ddf to image slice/s to generate gif :param img_paths: list or comma separated string of image paths :param ddf_path: path to ddf to use for warping :param slice_inds: list of slice indices to use for each image :param num_interval: number of intervals in which to apply ddf :param interval: time in miliseconds between frames of gif :param save_path: path to directory where visualisation/s is/are to be saved """ if type(img_paths) is str: img_paths = string_to_list(img_paths) image = load_nifti_file(img_paths[0]) img_shape = np.shape(image) if slice_inds is None: slice_inds = [round(np.random.rand() * (img_shape[-1]) - 1)] for img_path in img_paths: for slice_ind in slice_inds: fig = plt.figure() ax = plt.Axes(fig, [0.0, 0.0, 1.0, 1.0]) ax.set_axis_off() fig.add_axes(ax) ddf_scalers = np.linspace(0, 1, num=num_interval) frames = [] for ddf_scaler in ddf_scalers: image = load_nifti_file(img_path) ddf = load_nifti_file(ddf_path) image = np.expand_dims(image, axis=0) ddf = np.expand_dims(ddf, axis=0) * ddf_scaler warped_image = warp_image_ddf(image=image, ddf=ddf, grid_ref=None) warped_image = np.squeeze(warped_image.numpy()) frame = plt.imshow( warped_image[:, :, slice_ind], aspect="auto", animated=True ) frames.append([frame]) anim = animation.ArtistAnimation(fig, frames, interval=interval) path_to_anim_save = os.path.join( save_path, os.path.split(img_path)[-1].split(".")[0] + "_slice_" + str(slice_ind) + ".gif", ) anim.save(path_to_anim_save) print("Animation saved to:", path_to_anim_save)
def call(self, inputs, **kwargs) -> tf.Tensor: """ :param inputs: (ddf, image) - ddf, shape = (batch, f_dim1, f_dim2, f_dim3, 3), dtype = float32 - image, shape = (batch, m_dim1, m_dim2, m_dim3), dtype = float32 :param kwargs: additional arguments. :return: shape = (batch, f_dim1, f_dim2, f_dim3) """ return layer_util.warp_image_ddf( image=inputs[1], ddf=inputs[0], grid_ref=self.grid_ref )
def call(self, inputs, **kwargs): """ wrap an image into a fixed size using ddf same functionality as transform of neuron https://github.com/adalca/neuron/blob/master/neuron/utils.py vol = image loc_shift = ddf :param inputs: [ddf, image] ddf.shape = (batch, f_dim1, f_dim2, f_dim3, 3) image.shape = (batch, m_dim1, m_dim2, m_dim3) ddf.type = float32 image.type = float32 :param kwargs: :return: shape = (batch, f_dim1, f_dim2, f_dim3) """ return layer_util.warp_image_ddf(image=inputs[1], ddf=inputs[0], grid_ref=self.grid_ref)
def warp(image_path: str, ddf_path: str, out_path: str): """ :param image_path: file path of the image file :param ddf_path: file path of the ddf file :param out_path: file path of the output """ if out_path == "": out_path = "warped.nii.gz" logging.warning( f"Output file path is not provided, will save output in {out_path}." ) else: if not (out_path.endswith(".nii") or out_path.endswith(".nii.gz")): out_path = os.path.join(os.path.dirname(out_path), "warped.nii.gz") logging.warning( f"Output file path should end with .nii or .nii.gz, " f"will save output in {out_path}.") os.makedirs(os.path.dirname(out_path), exist_ok=True) # load image and ddf image = load_nifti_file(image_path) ddf = load_nifti_file(ddf_path) if len(image.shape) not in [3, 4]: raise ValueError(f"image shape must be (m_dim1, m_dim2, m_dim3) " f"or (m_dim1, m_dim2, m_dim3, ch)," f" got {image.shape}") if not (len(ddf.shape) == 4 and ddf.shape[-1] == 3): raise ValueError( f"ddf shape must be (f_dim1, f_dim2, f_dim3, 3), got {ddf.shape}") # add batch dimension manually image = tf.expand_dims(image, axis=0) ddf = tf.expand_dims(ddf, axis=0) # warp warped_image = warp_image_ddf(image=image, ddf=ddf, grid_ref=None) warped_image = warped_image.numpy() warped_image = warped_image[0, ...] # removed added batch dimension # save output nib.save(img=nib.Nifti2Image(warped_image, affine=np.eye(4)), filename=out_path)
def warp(image_path: str, ddf_path: str, out_path: str): """ :param image_path: file path of the image file :param ddf_path: file path of the ddf file :param out_path: file path of the output """ if out_path == "": out_path = "warped.nii.gz" logging.warning( f"Output file path is not provided, will save output in {out_path}." ) else: if not (out_path.endswith(".nii") or out_path.endswith(".nii.gz")): out_path = os.path.join(os.path.dirname(out_path), "warped.nii.gz") logging.warning( f"Output file path should end with .nii or .nii.gz, " f"will save output in {out_path}." ) os.makedirs(os.path.dirname(out_path), exist_ok=True) # load image and ddf image = load_nifti_file(image_path) ddf = load_nifti_file(ddf_path) shape_sanity_check(image=image, ddf=ddf) # add batch dimension manually image = tf.expand_dims(image, axis=0) ddf = tf.expand_dims(ddf, axis=0) # warp warped_image = warp_image_ddf(image=image, ddf=ddf, grid_ref=None) warped_image = warped_image.numpy() warped_image = warped_image[0, ...] # removed added batch dimension # save output nib.save(img=nib.Nifti1Image(warped_image, affine=np.eye(4)), filename=out_path)