biapy 3.4.2__tar.gz → 3.4.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {biapy-3.4.2 → biapy-3.4.3}/PKG-INFO +1 -1
- {biapy-3.4.2 → biapy-3.4.3}/biapy/_biapy.py +2 -1
- {biapy-3.4.2 → biapy-3.4.3}/biapy/config/config.py +18 -18
- {biapy-3.4.2 → biapy-3.4.3}/biapy/data/data_2D_manipulation.py +95 -30
- {biapy-3.4.2 → biapy-3.4.3}/biapy/data/data_3D_manipulation.py +101 -28
- {biapy-3.4.2 → biapy-3.4.3}/biapy/data/generators/__init__.py +8 -3
- {biapy-3.4.2 → biapy-3.4.3}/biapy/data/generators/augmentors.py +1 -1
- {biapy-3.4.2 → biapy-3.4.3}/biapy/data/generators/pair_base_data_generator.py +17 -21
- {biapy-3.4.2 → biapy-3.4.3}/biapy/data/generators/pair_data_2D_generator.py +4 -3
- {biapy-3.4.2 → biapy-3.4.3}/biapy/data/generators/pair_data_3D_generator.py +10 -8
- {biapy-3.4.2 → biapy-3.4.3}/biapy/data/generators/single_base_data_generator.py +21 -10
- {biapy-3.4.2 → biapy-3.4.3}/biapy/data/generators/test_pair_data_generators.py +15 -8
- {biapy-3.4.2 → biapy-3.4.3}/biapy/data/generators/test_single_data_generator.py +17 -4
- {biapy-3.4.2 → biapy-3.4.3}/biapy/data/post_processing/post_processing.py +6 -5
- {biapy-3.4.2 → biapy-3.4.3}/biapy/data/pre_processing.py +3 -2
- {biapy-3.4.2 → biapy-3.4.3}/biapy/engine/base_workflow.py +15 -16
- {biapy-3.4.2 → biapy-3.4.3}/biapy/engine/check_configuration.py +37 -32
- {biapy-3.4.2 → biapy-3.4.3}/biapy/engine/classification.py +20 -5
- {biapy-3.4.2 → biapy-3.4.3}/biapy/engine/detection.py +11 -9
- {biapy-3.4.2 → biapy-3.4.3}/biapy/engine/instance_seg.py +22 -16
- {biapy-3.4.2 → biapy-3.4.3}/biapy/engine/train_engine.py +4 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/models/mae.py +8 -5
- biapy-3.4.3/biapy/utils/scripts/run_checks.py +2788 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy.egg-info/PKG-INFO +1 -1
- {biapy-3.4.2 → biapy-3.4.3}/biapy.egg-info/SOURCES.txt +1 -0
- {biapy-3.4.2 → biapy-3.4.3}/pyproject.toml +1 -1
- {biapy-3.4.2 → biapy-3.4.3}/LICENSE.md +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/README.md +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/__init__.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/config/__init__.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/data/__init__.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/data/generators/single_data_2D_generator.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/data/generators/single_data_3D_generator.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/data/post_processing/__init__.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/data/post_processing/smooth_tiled_predictions.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/engine/__init__.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/engine/denoising.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/engine/image_to_image.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/engine/metrics.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/engine/schedulers/warmup_cosine_decay.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/engine/self_supervised.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/engine/semantic_seg.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/engine/super_resolution.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/models/__init__.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/models/attention_unet.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/models/blocks.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/models/dfcan.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/models/edsr.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/models/efficientnet.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/models/multiresunet.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/models/rcan.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/models/resunet++.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/models/resunet.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/models/seunet.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/models/simple_cnn.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/models/tr_layers.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/models/unet.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/models/unetr.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/models/vit.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/models/wdsr.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/utils/callbacks.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/utils/matching.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/utils/misc.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/utils/scripts/calculate_detection_metrics.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/utils/scripts/calculate_metrics_3D.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/utils/scripts/create_probability_csv.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/utils/scripts/crop_2D_dataset.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/utils/scripts/crop_3D_dataset.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/utils/scripts/crop_and_discard_3D_dataset.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/utils/scripts/detection_plots.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/utils/scripts/detection_probs_to_points.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/utils/scripts/fill_holes_in_seg_masks.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/utils/scripts/filter_close_points.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/utils/scripts/from_class_csv_to_folders.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/utils/scripts/h5_to_tif.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/utils/scripts/h5_to_zarr.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/utils/scripts/lightmycell_data_preparation.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/utils/scripts/merge_dataset_channels.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/utils/scripts/order_axes.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/utils/scripts/tif_to_h5.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy/utils/util.py +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy.egg-info/dependency_links.txt +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy.egg-info/entry_points.txt +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy.egg-info/requires.txt +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/biapy.egg-info/top_level.txt +0 -0
- {biapy-3.4.2 → biapy-3.4.3}/setup.cfg +0 -0
|
@@ -11,7 +11,7 @@ import numpy as np
|
|
|
11
11
|
import importlib
|
|
12
12
|
import multiprocessing
|
|
13
13
|
|
|
14
|
-
from biapy.utils.misc import init_devices, is_dist_avail_and_initialized, set_seed, get_rank
|
|
14
|
+
from biapy.utils.misc import init_devices, is_dist_avail_and_initialized, set_seed, get_rank, setup_for_distributed
|
|
15
15
|
from biapy.config.config import Config
|
|
16
16
|
from biapy.engine.check_configuration import check_configuration
|
|
17
17
|
|
|
@@ -420,6 +420,7 @@ class BiaPy():
|
|
|
420
420
|
|
|
421
421
|
if is_dist_avail_and_initialized():
|
|
422
422
|
print(f"[Rank {get_rank()} ({os.getpid()})] Process waiting (test finished) . . . ")
|
|
423
|
+
setup_for_distributed(self.args.rank == 0)
|
|
423
424
|
dist.barrier()
|
|
424
425
|
dist.destroy_process_group()
|
|
425
426
|
|
|
@@ -184,24 +184,26 @@ class Config:
|
|
|
184
184
|
_C.DATA.W_BACKGROUND = 0.06 # Used when _C.DATA.PROBABILITY_MAP=True
|
|
185
185
|
|
|
186
186
|
# Whether to reshape the dimensions that does not satisfy the patch shape selected by padding it with reflect. It's not
|
|
187
|
-
# implemented in super-resolution workflow.
|
|
187
|
+
# implemented in super-resolution inference phase workflow (as usually the patch size is small).
|
|
188
188
|
_C.DATA.REFLECT_TO_COMPLETE_SHAPE = False
|
|
189
189
|
|
|
190
190
|
_C.DATA.NORMALIZATION = CN()
|
|
191
|
+
# Whether to apply or not a percentile clipping before normalizing the data
|
|
192
|
+
_C.DATA.NORMALIZATION.PERC_CLIP = False
|
|
193
|
+
# Lower and upper bound for percentile clip. Must be set when DATA.NORMALIZATION.PERC_CLIP = 'True'
|
|
194
|
+
_C.DATA.NORMALIZATION.PERC_LOWER = -1.0
|
|
195
|
+
_C.DATA.NORMALIZATION.PERC_UPPER = -1.0
|
|
191
196
|
# Normalization type to use. Possible options:
|
|
192
197
|
# 'div' to divide values from 0/255 (or 0/65535 if uint16) in [0,1] range
|
|
193
198
|
# 'custom' to use DATA.NORMALIZATION.CUSTOM_MEAN and DATA.NORMALIZATION.CUSTOM_STD to normalize
|
|
194
199
|
_C.DATA.NORMALIZATION.TYPE = 'div'
|
|
195
|
-
# Whether to apply the normalization by sample ("image") or by all dataset statistics ("dataset").
|
|
200
|
+
# Whether to apply the normalization by sample ("image") or by all dataset statistics ("dataset").
|
|
201
|
+
# Used with 'DATA.NORMALIZATION.PERC_CLIP' == 'True' and/or when 'DATA.NORMALIZATION.TYPE' == 'custom'.
|
|
202
|
+
# Options: ["image", "dataset"]
|
|
196
203
|
_C.DATA.NORMALIZATION.APPLICATION_MODE = "image"
|
|
197
204
|
# Custom normalization variables: mean and std (they are calculated if not provided)
|
|
198
205
|
_C.DATA.NORMALIZATION.CUSTOM_MEAN = -1.0
|
|
199
206
|
_C.DATA.NORMALIZATION.CUSTOM_STD = -1.0
|
|
200
|
-
# Whether to apply or not a percentile clipping before normalizing the data
|
|
201
|
-
_C.DATA.NORMALIZATION.PERC_CLIP = False
|
|
202
|
-
# Lower and upper bound for percentile clip. Must be set when DATA.NORMALIZATION.PERC_CLIP = 'True'
|
|
203
|
-
_C.DATA.NORMALIZATION.PERC_LOWER = -1.0
|
|
204
|
-
_C.DATA.NORMALIZATION.PERC_UPPER = -1.0
|
|
205
207
|
|
|
206
208
|
# If 'DATA.PATCH_SIZE' selected has 3 channels, e.g. RGB images are expected, so will force grayscale images to be
|
|
207
209
|
# converted into RGB (e.g. in ImageNet some of the images are grayscale)
|
|
@@ -384,9 +386,6 @@ class Config:
|
|
|
384
386
|
# Padding to be done in (y,x)/(z,y,x) when cropping validation data. Useful to avoid patch 'border effect'. This
|
|
385
387
|
# is only used when the validation is loaded from disk, and thus, not extracted from training.
|
|
386
388
|
_C.DATA.VAL.PADDING = (0,0)
|
|
387
|
-
# Directory where validation binary masks should be located. This binary mask will be applied only when MW_TH*
|
|
388
|
-
# optimized values are find, that is, when _C.PROBLEM.INSTANCE_SEG.DATA_MW_OPTIMIZE_THS = True and _C.TEST.POST_PROCESSING.APPLY_MASK = True
|
|
389
|
-
_C.DATA.VAL.BINARY_MASKS = os.path.join("user_data", 'val', 'bin_mask')
|
|
390
389
|
# Not used yet.
|
|
391
390
|
_C.DATA.VAL.RESOLUTION = (-1,)
|
|
392
391
|
# Order of the axes of the image when using Zarr/H5 images to train
|
|
@@ -435,7 +434,7 @@ class Config:
|
|
|
435
434
|
# How to fill up the new values created with affine transformations (rotations, shear, shift and zoom).
|
|
436
435
|
# Same meaning as in scipy: 'reflect', grid-'mirror', 'constant', 'grid-constant', 'nearest', 'mirror',
|
|
437
436
|
# 'grid-wrap' and 'wrap'.
|
|
438
|
-
_C.AUGMENTOR.AFFINE_MODE = '
|
|
437
|
+
_C.AUGMENTOR.AFFINE_MODE = 'reflect'
|
|
439
438
|
# Make vertical flips
|
|
440
439
|
_C.AUGMENTOR.VFLIP = False
|
|
441
440
|
# Make horizontal flips
|
|
@@ -843,7 +842,7 @@ class Config:
|
|
|
843
842
|
_C.TEST.REUSE_PREDICTIONS = False
|
|
844
843
|
|
|
845
844
|
# If PROBLEM.NDIM = '2D' this can be activated to process each image entirely instead of patch by patch. Only can be done
|
|
846
|
-
# if the neural network is fully convolutional
|
|
845
|
+
# if the neural network is fully convolutional. It's not implemented in super-resolution workflow.
|
|
847
846
|
_C.TEST.FULL_IMG = False
|
|
848
847
|
|
|
849
848
|
### Instance segmentation
|
|
@@ -891,9 +890,12 @@ class Config:
|
|
|
891
890
|
_C.TEST.POST_PROCESSING.YZ_FILTERING_SIZE = 5
|
|
892
891
|
_C.TEST.POST_PROCESSING.Z_FILTERING = False
|
|
893
892
|
_C.TEST.POST_PROCESSING.Z_FILTERING_SIZE = 5
|
|
894
|
-
# Apply a binary mask to remove possible segmentation outside it
|
|
893
|
+
# Apply a binary mask to remove possible segmentation outside it (you need to provide the mask and it must
|
|
894
|
+
# contain two values: '1' -> preserve the pixel ; '0' discard pixel ). A mask for each test sample must be
|
|
895
|
+
# provided and it will be loaded using 'DATA.TEST.BINARY_MASKS' variable.
|
|
895
896
|
_C.TEST.POST_PROCESSING.APPLY_MASK = False
|
|
896
897
|
|
|
898
|
+
### Instance segmentation
|
|
897
899
|
# Whether to measure morphological features on each instances, i.e. 'circularity' (2D), 'elongation' (2D), 'npixels', 'area', 'diameter',
|
|
898
900
|
# 'perimeter', 'sphericity' (3D)
|
|
899
901
|
_C.TEST.POST_PROCESSING.MEASURE_PROPERTIES = CN()
|
|
@@ -964,7 +966,6 @@ class Config:
|
|
|
964
966
|
# "greather equal", e.g. ">=", "less than", e.g. "<", and "less equal" e.g. "<=" comparisons.
|
|
965
967
|
_C.TEST.POST_PROCESSING.MEASURE_PROPERTIES.REMOVE_BY_PROPERTIES.SIGN = []
|
|
966
968
|
|
|
967
|
-
### Instance segmentation
|
|
968
969
|
# Whether to apply Voronoi using 'BC' or 'M' channels need to be present
|
|
969
970
|
_C.TEST.POST_PROCESSING.VORONOI_ON_MASK = False
|
|
970
971
|
# Threshold to be applied to the 'M' channel when expanding the instances with Voronoi. Need to be in [0,1] range.
|
|
@@ -986,7 +987,8 @@ class Config:
|
|
|
986
987
|
_C.TEST.POST_PROCESSING.REMOVE_CLOSE_POINTS_RADIUS = [-1.0]
|
|
987
988
|
# Whether to apply a watershed to grow the points detected
|
|
988
989
|
_C.TEST.POST_PROCESSING.DET_WATERSHED = False
|
|
989
|
-
# Structure per each class to dilate the initial seeds before watershed
|
|
990
|
+
# Structure per each class to dilate the initial seeds before watershed. For instance, with two classes in a 3D problem:
|
|
991
|
+
# [ [2,2,1], [10,10,4] ]
|
|
990
992
|
_C.TEST.POST_PROCESSING.DET_WATERSHED_FIRST_DILATION = [[-1,-1],]
|
|
991
993
|
# List of classes to be consider as 'donuts'. For those class points, the 'donuts' type cell means that their nucleus is
|
|
992
994
|
# to big and that the seeds need to be dilated more so the watershed can grow the instances properly.
|
|
@@ -1014,6 +1016,7 @@ class Config:
|
|
|
1014
1016
|
_C.PATHS.RESULT_DIR.FULL_IMAGE_INSTANCES = os.path.join(_C.PATHS.RESULT_DIR.PATH, 'full_image_instances')
|
|
1015
1017
|
_C.PATHS.RESULT_DIR.FULL_IMAGE_POST_PROCESSING = os.path.join(_C.PATHS.RESULT_DIR.PATH, 'full_image_post_processing')
|
|
1016
1018
|
_C.PATHS.RESULT_DIR.AS_3D_STACK = os.path.join(_C.PATHS.RESULT_DIR.PATH, 'as_3d_stack')
|
|
1019
|
+
_C.PATHS.RESULT_DIR.AS_3D_STACK_BIN = os.path.join(_C.PATHS.RESULT_DIR.PATH, 'as_3d_stack_binarized')
|
|
1017
1020
|
_C.PATHS.RESULT_DIR.AS_3D_STACK_POST_PROCESSING = os.path.join(_C.PATHS.RESULT_DIR.PATH, 'as_3d_stack_post_processing')
|
|
1018
1021
|
_C.PATHS.RESULT_DIR.DET_LOCAL_MAX_COORDS_CHECK = os.path.join(_C.PATHS.RESULT_DIR.PATH, 'per_image_local_max_check')
|
|
1019
1022
|
_C.PATHS.RESULT_DIR.DET_ASSOC_POINTS = os.path.join(_C.PATHS.RESULT_DIR.PATH, 'point_associations')
|
|
@@ -1023,7 +1026,6 @@ class Config:
|
|
|
1023
1026
|
_C.PATHS.PROFILER = os.path.join(_C.PATHS.RESULT_DIR.PATH, 'profiler')
|
|
1024
1027
|
|
|
1025
1028
|
# Name of the folder where the charts of the loss and metrics values while training the network are stored.
|
|
1026
|
-
# Additionally, MW_TH* variable charts are stored if _C.PROBLEM.INSTANCE_SEG.DATA_MW_OPTIMIZE_THS = True
|
|
1027
1029
|
_C.PATHS.CHARTS = os.path.join(_C.PATHS.RESULT_DIR.PATH, 'charts')
|
|
1028
1030
|
# Folder where samples of DA will be stored
|
|
1029
1031
|
_C.PATHS.DA_SAMPLES = os.path.join(_C.PATHS.RESULT_DIR.PATH, 'aug')
|
|
@@ -1091,8 +1093,6 @@ class Config:
|
|
|
1091
1093
|
self._C.DATA.VAL.INSTANCE_CHANNELS_DIR = self._C.DATA.VAL.PATH+'_'+self._C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS+'_'+self._C.PROBLEM.INSTANCE_SEG.DATA_CONTOUR_MODE
|
|
1092
1094
|
self._C.DATA.VAL.INSTANCE_CHANNELS_MASK_DIR = self._C.DATA.VAL.GT_PATH+'_'+self._C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS+'_'+self._C.PROBLEM.INSTANCE_SEG.DATA_CONTOUR_MODE
|
|
1093
1095
|
# If value is not the default
|
|
1094
|
-
if self._C.DATA.VAL.BINARY_MASKS == os.path.join("user_data", 'val', 'bin_mask'):
|
|
1095
|
-
self._C.DATA.VAL.BINARY_MASKS = os.path.join(self._C.DATA.VAL.PATH, '..', 'bin_mask')
|
|
1096
1096
|
self._C.DATA.VAL.DETECTION_MASK_DIR = self._C.DATA.VAL.GT_PATH+'_detection_masks'
|
|
1097
1097
|
self._C.DATA.VAL.SSL_SOURCE_DIR = self._C.DATA.VAL.PATH+'_ssl_source'
|
|
1098
1098
|
self._C.DATA.TEST.INSTANCE_CHANNELS_DIR = self._C.DATA.TEST.PATH+'_'+self._C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS+'_'+self._C.PROBLEM.INSTANCE_SEG.DATA_CONTOUR_MODE
|
|
@@ -102,7 +102,7 @@ def load_and_prepare_2D_train_data(train_path, train_mask_path, cross_val=False,
|
|
|
102
102
|
filenames : List of str
|
|
103
103
|
Loaded train filenames.
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
test_index : List of ints
|
|
106
106
|
Indexes of the samples beloging to the validation.
|
|
107
107
|
|
|
108
108
|
Examples
|
|
@@ -144,7 +144,7 @@ def load_and_prepare_2D_train_data(train_path, train_mask_path, cross_val=False,
|
|
|
144
144
|
print("### LOAD ###")
|
|
145
145
|
|
|
146
146
|
# Disable crops when random_crops_in_DA is selected
|
|
147
|
-
|
|
147
|
+
delay_crop = False
|
|
148
148
|
if random_crops_in_DA:
|
|
149
149
|
crop = False
|
|
150
150
|
else:
|
|
@@ -154,7 +154,6 @@ def load_and_prepare_2D_train_data(train_path, train_mask_path, cross_val=False,
|
|
|
154
154
|
delay_crop = True
|
|
155
155
|
else:
|
|
156
156
|
crop = True
|
|
157
|
-
delay_crop = False
|
|
158
157
|
|
|
159
158
|
# Check validation
|
|
160
159
|
if val_split > 0 or cross_val:
|
|
@@ -172,6 +171,19 @@ def load_and_prepare_2D_train_data(train_path, train_mask_path, cross_val=False,
|
|
|
172
171
|
Y_train, _, _, _ = load_data_from_dir(train_mask_path, crop=crop, crop_shape=scrop, overlap=ov, padding=padding,
|
|
173
172
|
return_filenames=True, check_channel=False, check_drange=False, reflect_to_complete_shape=reflect_to_complete_shape,
|
|
174
173
|
preprocess_cfg=preprocess_cfg, is_mask=is_y_mask, preprocess_f=preprocess_f)
|
|
174
|
+
|
|
175
|
+
# Check that the shape of all images match
|
|
176
|
+
if isinstance(Y_train, list):
|
|
177
|
+
for i in range(len(Y_train)):
|
|
178
|
+
xshape = X_train[i].shape
|
|
179
|
+
yshape = Y_train[i].shape
|
|
180
|
+
real_x_shape = (xshape[0]*y_upscaling[0], xshape[1]*y_upscaling[1], xshape[2])
|
|
181
|
+
real_y_shape = (yshape[0]*y_upscaling[0], yshape[1]*y_upscaling[1], yshape[2])
|
|
182
|
+
print(real_x_shape,real_y_shape)
|
|
183
|
+
if real_x_shape != real_y_shape:
|
|
184
|
+
raise ValueError(f"There is a mismatch between input image and its corresponding ground truth ({real_x_shape} vs "
|
|
185
|
+
f"{real_y_shape}). Please check the images. Specifically, the sample that doesn't match is the number {i}"
|
|
186
|
+
f" (file: {t_filenames[i]})")
|
|
175
187
|
else:
|
|
176
188
|
Y_train = None
|
|
177
189
|
|
|
@@ -257,22 +269,36 @@ def load_and_prepare_2D_train_data(train_path, train_mask_path, cross_val=False,
|
|
|
257
269
|
skf = StratifiedKFold(n_splits=cross_val_nsplits, shuffle=shuffle_val,
|
|
258
270
|
random_state=seed)
|
|
259
271
|
fold = 1
|
|
260
|
-
train_index,
|
|
272
|
+
train_index, test_index = None, None
|
|
261
273
|
|
|
262
274
|
y_len = len(Y_train) if Y_train is not None else len(X_train)
|
|
263
275
|
for t_index, te_index in skf.split(np.zeros(len(X_train)), np.zeros(y_len)):
|
|
264
276
|
if cross_val_fold == fold:
|
|
265
|
-
|
|
277
|
+
if not isinstance(X_train, list):
|
|
278
|
+
X_train, X_val = X_train[t_index], X_train[te_index]
|
|
279
|
+
else:
|
|
280
|
+
X_val = []
|
|
281
|
+
for val_idx in te_index:
|
|
282
|
+
X_val.append(X_train[val_idx])
|
|
283
|
+
for val_idx in te_index:
|
|
284
|
+
del X_val[val_idx]
|
|
266
285
|
if Y_train is not None:
|
|
267
|
-
|
|
286
|
+
if not isinstance(Y_train, list):
|
|
287
|
+
Y_train, Y_val = Y_train[t_index], Y_train[te_index]
|
|
288
|
+
else:
|
|
289
|
+
Y_val = []
|
|
290
|
+
for val_idx in te_index:
|
|
291
|
+
Y_val.append(Y_val[val_idx])
|
|
292
|
+
for val_idx in te_index:
|
|
293
|
+
del Y_val[val_idx]
|
|
268
294
|
train_index, test_index = t_index.copy(), te_index.copy()
|
|
269
295
|
break
|
|
270
296
|
fold+= 1
|
|
271
297
|
|
|
272
|
-
if len(
|
|
273
|
-
print("Fold number {}. Printing the first 5 ids: {}".format(fold,
|
|
298
|
+
if len(test_index) > 5:
|
|
299
|
+
print("Fold number {}. Printing the first 5 ids: {}".format(fold, test_index[:5]))
|
|
274
300
|
else:
|
|
275
|
-
print("Fold number {}. Indexes used in cross validation: {}".format(fold,
|
|
301
|
+
print("Fold number {}. Indexes used in cross validation: {}".format(fold, test_index))
|
|
276
302
|
|
|
277
303
|
# Then crop after cross validation
|
|
278
304
|
if delay_crop:
|
|
@@ -280,8 +306,8 @@ def load_and_prepare_2D_train_data(train_path, train_mask_path, cross_val=False,
|
|
|
280
306
|
data = []
|
|
281
307
|
for img_num in range(len(X_train)):
|
|
282
308
|
if X_train[img_num].shape != crop_shape[:2]+(X_train[img_num].shape[-1],):
|
|
283
|
-
img =
|
|
284
|
-
|
|
309
|
+
img = crop_data_with_overlap(
|
|
310
|
+
X_train[img_num][0] if isinstance(X_train, list) else np.expand_dims(X_train[img_num],0),
|
|
285
311
|
crop_shape[:2]+(X_train[img_num].shape[-1],), overlap=ov, padding=padding, verbose=False)
|
|
286
312
|
data.append(img)
|
|
287
313
|
X_train = np.concatenate(data)
|
|
@@ -293,8 +319,8 @@ def load_and_prepare_2D_train_data(train_path, train_mask_path, cross_val=False,
|
|
|
293
319
|
scrop = (crop_shape[0]*y_upscaling[0], crop_shape[1]*y_upscaling[1], crop_shape[2])
|
|
294
320
|
for img_num in range(len(Y_train)):
|
|
295
321
|
if Y_train[img_num].shape != scrop[:2]+(Y_train[img_num].shape[-1],):
|
|
296
|
-
img =
|
|
297
|
-
|
|
322
|
+
img = crop_data_with_overlap(
|
|
323
|
+
Y_train[img_num][0] if isinstance(Y_train, list) else np.expand_dims(Y_train[img_num],0),
|
|
298
324
|
scrop[:2]+(Y_train[img_num].shape[-1],), overlap=ov, padding=padding, verbose=False)
|
|
299
325
|
data_mask.append(img)
|
|
300
326
|
Y_train = np.concatenate(data_mask)
|
|
@@ -304,8 +330,8 @@ def load_and_prepare_2D_train_data(train_path, train_mask_path, cross_val=False,
|
|
|
304
330
|
data = []
|
|
305
331
|
for img_num in range(len(X_val)):
|
|
306
332
|
if X_val[img_num].shape != crop_shape[:2]+(X_val[img_num].shape[-1],):
|
|
307
|
-
img =
|
|
308
|
-
|
|
333
|
+
img = crop_data_with_overlap(
|
|
334
|
+
X_val[img_num][0] if isinstance(X_val, list) else np.expand_dims(X_val[img_num],0),
|
|
309
335
|
crop_shape[:2]+(X_val[img_num].shape[-1],), overlap=ov, padding=padding, verbose=False)
|
|
310
336
|
data.append(img)
|
|
311
337
|
X_val = np.concatenate(data)
|
|
@@ -317,13 +343,26 @@ def load_and_prepare_2D_train_data(train_path, train_mask_path, cross_val=False,
|
|
|
317
343
|
scrop = (crop_shape[0]*y_upscaling[0], crop_shape[1]*y_upscaling[1], crop_shape[2])
|
|
318
344
|
for img_num in range(len(Y_val)):
|
|
319
345
|
if Y_val[img_num].shape != scrop[:2]+(Y_val[img_num].shape[-1],):
|
|
320
|
-
img =
|
|
321
|
-
|
|
346
|
+
img = crop_data_with_overlap(
|
|
347
|
+
Y_val[img_num][0] if isinstance(Y_val, list) else np.expand_dims(Y_val[img_num],0),
|
|
322
348
|
scrop[:2]+(Y_val[img_num].shape[-1],), overlap=ov, padding=padding, verbose=False)
|
|
323
349
|
data_mask.append(img)
|
|
324
350
|
Y_val = np.concatenate(data_mask)
|
|
325
351
|
del data_mask
|
|
326
352
|
|
|
353
|
+
# Check that the shape of all images match
|
|
354
|
+
if Y_train is not None:
|
|
355
|
+
if not isinstance(X_train, list):
|
|
356
|
+
if Y_train.shape[0] != X_train.shape[0]:
|
|
357
|
+
raise ValueError(f"Seems that input images do not correspond to their ground truth in shape ({X_train.shape[0]} samples vs "
|
|
358
|
+
f"{Y_train.shape[0]} samples). Please check the images. If you are in super-resolution workflow maybe you did not "
|
|
359
|
+
"configured properly 'PROBLEM.SUPER_RESOLUTION.UPSCALING' variable")
|
|
360
|
+
else:
|
|
361
|
+
if Y_train[0].shape[0] != X_train[0].shape[0]:
|
|
362
|
+
raise ValueError(f"Seems that input images do not correspond to their ground truth in shape ({X_train[0].shape[0]} samples vs "
|
|
363
|
+
f"{Y_train[0].shape[0]} samples). Please check the images. If you are in super-resolution workflow maybe you did not "
|
|
364
|
+
"configured properly 'PROBLEM.SUPER_RESOLUTION.UPSCALING' variable")
|
|
365
|
+
|
|
327
366
|
s = X_train.shape if not isinstance(X_train, list) else (len(X_train),)+X_train[0].shape[1:]
|
|
328
367
|
if Y_train is not None:
|
|
329
368
|
sm = Y_train.shape if not isinstance(Y_train, list) else (len(Y_train),)+Y_train[0].shape[1:]
|
|
@@ -344,7 +383,7 @@ def load_and_prepare_2D_train_data(train_path, train_mask_path, cross_val=False,
|
|
|
344
383
|
if not cross_val:
|
|
345
384
|
return X_train, Y_train, X_val, Y_val, t_filenames
|
|
346
385
|
else:
|
|
347
|
-
return X_train, Y_train, X_val, Y_val, t_filenames,
|
|
386
|
+
return X_train, Y_train, X_val, Y_val, t_filenames, test_index
|
|
348
387
|
else:
|
|
349
388
|
print("*** Loaded train data shape is: {}".format(s))
|
|
350
389
|
print("### END LOAD ###")
|
|
@@ -443,7 +482,11 @@ def crop_data_with_overlap(data, crop_shape, data_mask=None, overlap=(0,0), padd
|
|
|
443
482
|
# **** New data shape is: (3960, 256, 256, 1)
|
|
444
483
|
"""
|
|
445
484
|
|
|
485
|
+
if data.ndim != 4:
|
|
486
|
+
raise ValueError("data expected to be 4 dimensional, given {}".format(data.shape))
|
|
446
487
|
if data_mask is not None:
|
|
488
|
+
if data.ndim != 4:
|
|
489
|
+
raise ValueError("data mask expected to be 4 dimensional, given {}".format(data_mask.shape))
|
|
447
490
|
if data.shape[:-1] != data_mask.shape[:-1]:
|
|
448
491
|
raise ValueError("data and data_mask shapes mismatch: {} vs {}".format(data.shape[:-1], data_mask.shape[:-1]))
|
|
449
492
|
|
|
@@ -799,8 +842,8 @@ def merge_data_with_overlap(data, original_shape, data_mask=None, overlap=(0,0),
|
|
|
799
842
|
return merged_data
|
|
800
843
|
|
|
801
844
|
|
|
802
|
-
def load_data_classification(data_dir, patch_shape, convert_to_rgb=True, expected_classes=None, cross_val=False, cross_val_nsplits=5,
|
|
803
|
-
val_split=0.1, seed=0, shuffle_val=True):
|
|
845
|
+
def load_data_classification(data_dir, patch_shape, convert_to_rgb=True, expected_classes=None, cross_val=False, cross_val_nsplits=5,
|
|
846
|
+
cross_val_fold=1, val_split=0.1, seed=0, shuffle_val=True, preprocess_cfg=None, preprocess_f=None):
|
|
804
847
|
"""
|
|
805
848
|
Load data to train classification methods.
|
|
806
849
|
|
|
@@ -837,6 +880,12 @@ def load_data_classification(data_dir, patch_shape, convert_to_rgb=True, expecte
|
|
|
837
880
|
shuffle_val : bool, optional
|
|
838
881
|
Take random training examples to create validation data.
|
|
839
882
|
|
|
883
|
+
preprocess_cfg : dict, optional
|
|
884
|
+
Configuration parameters for preprocessing, is necessary in case you want to apply any preprocessing.
|
|
885
|
+
|
|
886
|
+
preprocess_f : function, optional
|
|
887
|
+
The preprocessing function, is necessary in case you want to apply any preprocessing.
|
|
888
|
+
|
|
840
889
|
Returns
|
|
841
890
|
-------
|
|
842
891
|
X_data : 4D Numpy array
|
|
@@ -854,7 +903,7 @@ def load_data_classification(data_dir, patch_shape, convert_to_rgb=True, expecte
|
|
|
854
903
|
all_ids : List of str
|
|
855
904
|
Loaded data filenames.
|
|
856
905
|
|
|
857
|
-
|
|
906
|
+
test_index : List of ints
|
|
858
907
|
Indexes of the samples beloging to the validation.
|
|
859
908
|
"""
|
|
860
909
|
|
|
@@ -889,7 +938,8 @@ def load_data_classification(data_dir, patch_shape, convert_to_rgb=True, expecte
|
|
|
889
938
|
|
|
890
939
|
# Loading images
|
|
891
940
|
images, _, _, image_ids = load_data_from_dir(f, return_filenames=True, crop_shape=patch_shape,
|
|
892
|
-
convert_to_rgb=convert_to_rgb
|
|
941
|
+
convert_to_rgb=convert_to_rgb, preprocess_cfg=preprocess_cfg, is_mask=False,
|
|
942
|
+
preprocess_f=preprocess_f)
|
|
893
943
|
|
|
894
944
|
X_data.append(images)
|
|
895
945
|
Y_data.append((c_num,)*len(ids))
|
|
@@ -908,26 +958,41 @@ def load_data_classification(data_dir, patch_shape, convert_to_rgb=True, expecte
|
|
|
908
958
|
if create_val:
|
|
909
959
|
print("Creating validation data")
|
|
910
960
|
if not cross_val:
|
|
961
|
+
if len(X_data) == 1:
|
|
962
|
+
raise ValueError("Validation data can not be extracted from training data as it only has one sample. Please check the data.")
|
|
911
963
|
X_data, X_val, Y_data, Y_val = train_test_split(
|
|
912
964
|
X_data, Y_data, test_size=val_split, shuffle=shuffle_val, random_state=seed,
|
|
913
965
|
stratify=Y_data)
|
|
914
966
|
else:
|
|
967
|
+
if len(X_data) < cross_val_nsplits:
|
|
968
|
+
raise ValueError(f"Validation data can not be extracted from training data as the number of splits ({cross_val_nsplits}) "
|
|
969
|
+
f"is greater than the number of samples {len(X_data)}. Please check the data.")
|
|
915
970
|
skf = StratifiedKFold(n_splits=cross_val_nsplits, shuffle=shuffle_val,
|
|
916
971
|
random_state=seed)
|
|
917
972
|
fold = 1
|
|
918
|
-
train_index,
|
|
973
|
+
train_index, test_index = None, None
|
|
919
974
|
|
|
920
975
|
for t_index, te_index in skf.split(X_data, Y_data):
|
|
921
976
|
if cross_val_fold == fold:
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
977
|
+
if not isinstance(X_data, list):
|
|
978
|
+
X_data, X_val = X_data[t_index], X_data[te_index]
|
|
979
|
+
Y_data, Y_val = Y_data[t_index], Y_data[te_index]
|
|
980
|
+
else:
|
|
981
|
+
X_val = []
|
|
982
|
+
Y_val = []
|
|
983
|
+
for val_idx in te_index:
|
|
984
|
+
X_val.append(X_data[val_idx])
|
|
985
|
+
Y_val.append(Y_data[val_idx])
|
|
986
|
+
for val_idx in te_index:
|
|
987
|
+
del X_val[val_idx]
|
|
988
|
+
del Y_val[val_idx]
|
|
989
|
+
train_index, test_index = t_index.copy(), te_index.copy()
|
|
925
990
|
break
|
|
926
991
|
fold+= 1
|
|
927
|
-
if len(
|
|
928
|
-
print("Fold number {}. Printing the first 5 ids: {}".format(fold,
|
|
992
|
+
if len(test_index) > 5:
|
|
993
|
+
print("Fold number {}. Printing the first 5 ids: {}".format(fold, test_index[:5]))
|
|
929
994
|
else:
|
|
930
|
-
print("Fold number {}. Indexes used in cross validation: {}".format(fold,
|
|
995
|
+
print("Fold number {}. Indexes used in cross validation: {}".format(fold, test_index))
|
|
931
996
|
|
|
932
997
|
if create_val:
|
|
933
998
|
print("*** Loaded train data shape is: {}".format(X_data.shape))
|
|
@@ -935,7 +1000,7 @@ def load_data_classification(data_dir, patch_shape, convert_to_rgb=True, expecte
|
|
|
935
1000
|
if not cross_val:
|
|
936
1001
|
return X_data, Y_data, X_val, Y_val, all_ids
|
|
937
1002
|
else:
|
|
938
|
-
return X_data, Y_data, X_val, Y_val, all_ids,
|
|
1003
|
+
return X_data, Y_data, X_val, Y_val, all_ids, test_index
|
|
939
1004
|
else:
|
|
940
1005
|
print("*** Loaded train data shape is: {}".format(X_data.shape))
|
|
941
1006
|
return X_data, Y_data, all_ids
|