diff --git a/doc/source/config_spec.md b/doc/source/config_spec.md index 730d67ba..d8f9c6f2 100644 --- a/doc/source/config_spec.md +++ b/doc/source/config_spec.md @@ -194,7 +194,7 @@ See also: [Patch-base analysis guide](./window_sizes.html) ###### `loader` Specify the loader to be used to load the files in the input section. Some loaders require additional Python packages. -Supported loaders: `nibabel`, `opencv`, `skimage`, `pillow`, `simpleitk`, `dummy` in prioriy order. +Supported loaders: `nibabel`, `opencv`, `skimage`, `pillow`, `simpleitk`, `dummy` in prioriy order. Default value `None` indicates trying all available loaders, in the above priority order. This section will be used by [ImageReader](./niftynet.io.image_reader.html) @@ -258,9 +258,9 @@ This option is ignored if there's no GPU device. Directory to save/load intermediate training models and logs. NiftyNet tries to interpret this parameter as an absolute system path or a path relative to the current command. It's defaulting to the directory of the current -configuration file if left blank. +configuration file if left blank. -It is assumed that `model_dir` contains two folders, `models` and `logs`. +It is assumed that `model_dir` contains two folders, `models` and `logs`. ###### `dataset_split_file` File assigning subjects to training/validation/inference subsets. @@ -595,6 +595,7 @@ Value should be in `[0, 1]`. [rotation_angle](#rotation-angle) | `float array` | `rotation_angle=-10.0,10.0` | `''` [scaling_percentage](#scaling-percentage) | `float array` | `scaling_percentage=-20.0,20.0` | `''` [antialiasing](#scaling-percentage) | `boolean` | `antialiasing=True` | `True` +[isotropic_scaling](#scaling-percentage) | `boolean` | `isotropic_scaling=True` | `False` [random_flipping_axes](#random-flipping-axes) | `integer array` | `random_flipping_axes=1,2` | `-1` [do_elastic_deformation](#do-elastic-deformation) | `boolean` | `do_elastic_deformation=True` | `False` [num_ctrl_points](#do-elastic-deformation) | `integer` | `num_ctrl_points=1` | `4` @@ -616,8 +617,10 @@ E.g, `(-50, 50)` indicates transforming image (size `d`) to image with its size in between `0.5*d` and `1.5d`. When random scaling is enabled, it is possible to further specify: -- `antialiasing` indicating if antialiasing should be performed +- `antialiasing` indicating if Gaussian filtering should be performed when randomly downsampling the input images. +- `isotropic_scaling` indicating if the same amount of scaling should be applied +in each dimension. ###### `random_flipping_axes` The axes which can be flipped to augment the data. @@ -682,7 +685,7 @@ Interpolation order of the network outputs. ###### `dataset_to_infer` String specifies which dataset ('all', 'training', 'validation', 'inference') to compute inference for. By default 'inference' dataset is used. If no `dataset_split_file` is specified, then all data specified -in the csv or search path are used for inference. +in the csv or search path are used for inference. ### EVALUATION diff --git a/niftynet/application/classification_application.py b/niftynet/application/classification_application.py index 098e9b6d..c48c7a31 100755 --- a/niftynet/application/classification_application.py +++ b/niftynet/application/classification_application.py @@ -136,7 +136,8 @@ def initialise_dataset_loader( augmentation_layers.append(RandomSpatialScalingLayer( min_percentage=train_param.scaling_percentage[0], max_percentage=train_param.scaling_percentage[1], - antialiasing=train_param.antialiasing)) + antialiasing=train_param.antialiasing, + isotropic=train_param.isotropic_scaling)) if train_param.rotation_angle or \ self.action_param.rotation_angle_x or \ self.action_param.rotation_angle_y or \ diff --git a/niftynet/application/gan_application.py b/niftynet/application/gan_application.py index ae09ee5f..66e45290 100755 --- a/niftynet/application/gan_application.py +++ b/niftynet/application/gan_application.py @@ -104,7 +104,8 @@ def initialise_dataset_loader( augmentation_layers.append(RandomSpatialScalingLayer( min_percentage=self.action_param.scaling_percentage[0], max_percentage=self.action_param.scaling_percentage[1], - antialiasing=self.action_param.antialiasing)) + antialiasing=self.action_param.antialiasing, + isotropic=self.action_param.isotropic_scaling)) if self.action_param.rotation_angle: augmentation_layers.append(RandomRotationLayer()) augmentation_layers[-1].init_uniform_angle( diff --git a/niftynet/application/regression_application.py b/niftynet/application/regression_application.py index 9777468e..82101ae0 100755 --- a/niftynet/application/regression_application.py +++ b/niftynet/application/regression_application.py @@ -125,7 +125,8 @@ def initialise_dataset_loader( augmentation_layers.append(RandomSpatialScalingLayer( min_percentage=train_param.scaling_percentage[0], max_percentage=train_param.scaling_percentage[1], - antialiasing=train_param.antialiasing)) + antialiasing=train_param.antialiasing, + isotropic=train_param.isotropic_scaling)) if train_param.rotation_angle: rotation_layer = RandomRotationLayer() if train_param.rotation_angle: diff --git a/niftynet/application/segmentation_application.py b/niftynet/application/segmentation_application.py index 644d28f1..d2f3672a 100755 --- a/niftynet/application/segmentation_application.py +++ b/niftynet/application/segmentation_application.py @@ -151,7 +151,8 @@ def initialise_dataset_loader( augmentation_layers.append(RandomSpatialScalingLayer( min_percentage=train_param.scaling_percentage[0], max_percentage=train_param.scaling_percentage[1], - antialiasing=train_param.antialiasing)) + antialiasing=train_param.antialiasing, + isotropic=train_param.isotropic_scaling)) if train_param.rotation_angle or \ train_param.rotation_angle_x or \ train_param.rotation_angle_y or \ diff --git a/niftynet/contrib/preprocessors/preprocessing.py b/niftynet/contrib/preprocessors/preprocessing.py index 6199815b..bc8dca05 100644 --- a/niftynet/contrib/preprocessors/preprocessing.py +++ b/niftynet/contrib/preprocessors/preprocessing.py @@ -58,7 +58,8 @@ def prepare_augmentation_layers(self): augmentation_layers.append(RandomSpatialScalingLayer( min_percentage=self.action_param.scaling_percentage[0], max_percentage=self.action_param.scaling_percentage[1], - antialiasing=self.action_param.antialiasing)) + antialiasing=self.action_param.antialiasing, + isotropic=self.action_param.isotropic_scaling)) if self.action_param.rotation_angle or \ self.action_param.rotation_angle_x or \ self.action_param.rotation_angle_y or \ diff --git a/niftynet/layer/rand_spatial_scaling.py b/niftynet/layer/rand_spatial_scaling.py index 8767feba..07d7dcec 100755 --- a/niftynet/layer/rand_spatial_scaling.py +++ b/niftynet/layer/rand_spatial_scaling.py @@ -3,6 +3,7 @@ import warnings +import tensorflow as tf import numpy as np import scipy.ndimage as ndi @@ -21,19 +22,26 @@ def __init__(self, min_percentage=-10.0, max_percentage=10.0, antialiasing=True, + isotropic=True, name='random_spatial_scaling'): super(RandomSpatialScalingLayer, self).__init__(name=name) assert min_percentage <= max_percentage self._min_percentage = max(min_percentage, -99.9) self._max_percentage = max_percentage self.antialiasing = antialiasing + self.isotropic = isotropic self._rand_zoom = None def randomise(self, spatial_rank=3): spatial_rank = int(np.floor(spatial_rank)) - rand_zoom = np.random.uniform(low=self._min_percentage, - high=self._max_percentage, - size=(spatial_rank,)) + if self.isotropic: + one_rand_zoom = np.random.uniform(low=self._min_percentage, + high=self._max_percentage) + rand_zoom = np.repeat(one_rand_zoom, spatial_rank) + else: + rand_zoom = np.random.uniform(low=self._min_percentage, + high=self._max_percentage, + size=(spatial_rank,)) self._rand_zoom = (rand_zoom + 100.0) / 100.0 def _get_sigma(self, zoom): diff --git a/niftynet/utilities/user_parameters_default.py b/niftynet/utilities/user_parameters_default.py index 28271997..4f5c3dfe 100755 --- a/niftynet/utilities/user_parameters_default.py +++ b/niftynet/utilities/user_parameters_default.py @@ -484,6 +484,13 @@ def add_training_args(parser): type=float_array, default=()) + parser.add_argument( + "--isotropic_scaling", + help="Indicates if the same random scaling factor should be applied " + "to each dimension", + type=str2boolean, + default=False) + parser.add_argument( "--antialiasing", help="Indicates if antialiasing must be performed "