biomedisa 24.7.1__tar.gz → 24.8.2__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.
- {biomedisa-24.7.1 → biomedisa-24.8.2}/PKG-INFO +9 -8
- {biomedisa-24.7.1 → biomedisa-24.8.2}/README.md +8 -7
- {biomedisa-24.7.1 → biomedisa-24.8.2}/pyproject.toml +1 -1
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/deeplearning.py +12 -3
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/DataGenerator.py +9 -1
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/biomedisa_helper.py +20 -11
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/crop_helper.py +2 -1
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/keras_helper.py +136 -48
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/interpolation.py +1 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa.egg-info/PKG-INFO +9 -8
- {biomedisa-24.7.1 → biomedisa-24.8.2}/LICENSE +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/setup.cfg +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/__init__.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/__main__.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/DataGeneratorCrop.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/PredictDataGenerator.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/PredictDataGeneratorCrop.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/__init__.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/active_contour.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/amira_to_np/__init__.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/amira_to_np/amira_data_stream.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/amira_to_np/amira_grammar.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/amira_to_np/amira_header.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/amira_to_np/amira_helper.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/assd.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/create_slices.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/curvop_numba.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/django_env.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/nc_reader.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/pid.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/process_image.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/pycuda_test.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/random_walk/__init__.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/random_walk/gpu_kernels.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/random_walk/pycuda_large.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/random_walk/pycuda_large_allx.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/random_walk/pycuda_small.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/random_walk/pycuda_small_allx.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/random_walk/pyopencl_large.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/random_walk/pyopencl_small.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/random_walk/rw_large.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/random_walk/rw_small.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/remove_outlier.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/split_volume.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/mesh.py +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa.egg-info/SOURCES.txt +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa.egg-info/dependency_links.txt +0 -0
- {biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: biomedisa
|
3
|
-
Version: 24.
|
3
|
+
Version: 24.8.2
|
4
4
|
Summary: Segmentation of 3D volumetric image data
|
5
5
|
Author: Philipp Lösel
|
6
6
|
Author-email: philipp.loesel@anu.edu.au
|
@@ -36,17 +36,17 @@ License-File: LICENSE
|
|
36
36
|
Biomedisa (https://biomedisa.info) is a free and easy-to-use open-source application for segmenting large 3D volumetric images such as CT and MRI scans, developed at [The Australian National University CTLab](https://ctlab.anu.edu.au/). Biomedisa's smart interpolation of sparsely pre-segmented slices enables accurate semi-automated segmentation by considering the complete underlying image data. Additionally, Biomedisa enables deep learning for fully automated segmentation across similar samples and structures. It is compatible with segmentation tools like Amira/Avizo, ImageJ/Fiji and 3D Slicer. If you are using Biomedisa or the data for your research please cite: Lösel, P.D. et al. [Introducing Biomedisa as an open-source online platform for biomedical image segmentation.](https://www.nature.com/articles/s41467-020-19303-w) *Nat. Commun.* **11**, 5577 (2020).
|
37
37
|
|
38
38
|
## Hardware Requirements
|
39
|
-
+ One or more NVIDIA GPUs with compute capability 3.0 or higher
|
39
|
+
+ One or more NVIDIA GPUs with compute capability 3.0 or higher.
|
40
40
|
|
41
41
|
## Installation (command-line based)
|
42
|
-
+ [Ubuntu 22.04 +
|
43
|
-
+ [Ubuntu 22.04 +
|
44
|
-
+ [Windows 10 +
|
45
|
-
+ [Windows
|
46
|
-
+ [Windows 10 + OpenCL + CPU (very slow)](https://github.com/biomedisa/biomedisa/blob/master/README/windows10_opencl_cpu_cli.md)
|
42
|
+
+ [Ubuntu 22.04 + Smart Interpolation](https://github.com/biomedisa/biomedisa/blob/master/README/ubuntu2204_interpolation_cli.md)
|
43
|
+
+ [Ubuntu 22.04 + Smart Interpolation + Deep Learning](https://github.com/biomedisa/biomedisa/blob/master/README/ubuntu2204_cuda11.8_gpu_cli.md)
|
44
|
+
+ [Windows 10 + Smart Interpolation + Deep Learning](https://github.com/biomedisa/biomedisa/blob/master/README/windows10_cuda_gpu_cli.md)
|
45
|
+
+ [Windows (WSL) + Smart Interpolation + Deep Learning](https://github.com/biomedisa/biomedisa/blob/master/README/windows_wsl.md)
|
47
46
|
|
48
47
|
## Installation (3D Slicer extension)
|
49
|
-
+ [Ubuntu 22.04 +
|
48
|
+
+ [Ubuntu 22.04 + Smart Interpolation + Deep Learning](https://github.com/biomedisa/biomedisa/blob/master/README/ubuntu2204_cuda11.8_gpu_slicer.md)
|
49
|
+
+ [Windows 10 + Smart Interpolation](https://github.com/biomedisa/biomedisa/blob/master/README/windows10_cuda_gpu_slicer.md)
|
50
50
|
|
51
51
|
## Installation (browser based)
|
52
52
|
+ [Ubuntu 22.04](https://github.com/biomedisa/biomedisa/blob/master/README/ubuntu2204_cuda11.8.md)
|
@@ -58,6 +58,7 @@ Biomedisa (https://biomedisa.info) is a free and easy-to-use open-source applica
|
|
58
58
|
24.7.1
|
59
59
|
+ 3D Slicer extension
|
60
60
|
+ Prediction of large data block by block
|
61
|
+
|
61
62
|
24.5.22
|
62
63
|
+ Pip is the preferred installation method
|
63
64
|
+ Commands, module names and imports have been changed to conform to the Pip standard
|
@@ -20,17 +20,17 @@
|
|
20
20
|
Biomedisa (https://biomedisa.info) is a free and easy-to-use open-source application for segmenting large 3D volumetric images such as CT and MRI scans, developed at [The Australian National University CTLab](https://ctlab.anu.edu.au/). Biomedisa's smart interpolation of sparsely pre-segmented slices enables accurate semi-automated segmentation by considering the complete underlying image data. Additionally, Biomedisa enables deep learning for fully automated segmentation across similar samples and structures. It is compatible with segmentation tools like Amira/Avizo, ImageJ/Fiji and 3D Slicer. If you are using Biomedisa or the data for your research please cite: Lösel, P.D. et al. [Introducing Biomedisa as an open-source online platform for biomedical image segmentation.](https://www.nature.com/articles/s41467-020-19303-w) *Nat. Commun.* **11**, 5577 (2020).
|
21
21
|
|
22
22
|
## Hardware Requirements
|
23
|
-
+ One or more NVIDIA GPUs with compute capability 3.0 or higher
|
23
|
+
+ One or more NVIDIA GPUs with compute capability 3.0 or higher.
|
24
24
|
|
25
25
|
## Installation (command-line based)
|
26
|
-
+ [Ubuntu 22.04 +
|
27
|
-
+ [Ubuntu 22.04 +
|
28
|
-
+ [Windows 10 +
|
29
|
-
+ [Windows
|
30
|
-
+ [Windows 10 + OpenCL + CPU (very slow)](https://github.com/biomedisa/biomedisa/blob/master/README/windows10_opencl_cpu_cli.md)
|
26
|
+
+ [Ubuntu 22.04 + Smart Interpolation](https://github.com/biomedisa/biomedisa/blob/master/README/ubuntu2204_interpolation_cli.md)
|
27
|
+
+ [Ubuntu 22.04 + Smart Interpolation + Deep Learning](https://github.com/biomedisa/biomedisa/blob/master/README/ubuntu2204_cuda11.8_gpu_cli.md)
|
28
|
+
+ [Windows 10 + Smart Interpolation + Deep Learning](https://github.com/biomedisa/biomedisa/blob/master/README/windows10_cuda_gpu_cli.md)
|
29
|
+
+ [Windows (WSL) + Smart Interpolation + Deep Learning](https://github.com/biomedisa/biomedisa/blob/master/README/windows_wsl.md)
|
31
30
|
|
32
31
|
## Installation (3D Slicer extension)
|
33
|
-
+ [Ubuntu 22.04 +
|
32
|
+
+ [Ubuntu 22.04 + Smart Interpolation + Deep Learning](https://github.com/biomedisa/biomedisa/blob/master/README/ubuntu2204_cuda11.8_gpu_slicer.md)
|
33
|
+
+ [Windows 10 + Smart Interpolation](https://github.com/biomedisa/biomedisa/blob/master/README/windows10_cuda_gpu_slicer.md)
|
34
34
|
|
35
35
|
## Installation (browser based)
|
36
36
|
+ [Ubuntu 22.04](https://github.com/biomedisa/biomedisa/blob/master/README/ubuntu2204_cuda11.8.md)
|
@@ -42,6 +42,7 @@ Biomedisa (https://biomedisa.info) is a free and easy-to-use open-source applica
|
|
42
42
|
24.7.1
|
43
43
|
+ 3D Slicer extension
|
44
44
|
+ Prediction of large data block by block
|
45
|
+
|
45
46
|
24.5.22
|
46
47
|
+ Pip is the preferred installation method
|
47
48
|
+ Commands, module names and imports have been changed to conform to the Pip standard
|
@@ -76,7 +76,8 @@ def deep_learning(img_data, label_data=None, val_img_data=None, val_label_data=N
|
|
76
76
|
path=None, success=True, return_probs=False, patch_normalization=False,
|
77
77
|
z_patch=64, y_patch=64, x_patch=64, path_to_logfile=None, img_id=None, label_id=None,
|
78
78
|
remote=False, queue=0, username=None, shortfilename=None, dice_loss=False,
|
79
|
-
acwe=False, acwe_alpha=1.0, acwe_smooth=1, acwe_steps=3, clean=None, fill=None
|
79
|
+
acwe=False, acwe_alpha=1.0, acwe_smooth=1, acwe_steps=3, clean=None, fill=None,
|
80
|
+
separation=False, mask=None, refinement=False):
|
80
81
|
|
81
82
|
# create biomedisa
|
82
83
|
bm = Biomedisa()
|
@@ -220,7 +221,7 @@ def deep_learning(img_data, label_data=None, val_img_data=None, val_label_data=N
|
|
220
221
|
normalization_parameters = np.array(meta['normalization'], dtype=float)
|
221
222
|
else:
|
222
223
|
normalization_parameters = np.array([[mu],[sig]])
|
223
|
-
allLabels = np.array(meta.get('labels'))
|
224
|
+
bm.allLabels = np.array(meta.get('labels'))
|
224
225
|
if 'patch_normalization' in meta:
|
225
226
|
bm.patch_normalization = bool(meta['patch_normalization'][()])
|
226
227
|
if 'scaling' in meta:
|
@@ -293,7 +294,7 @@ def deep_learning(img_data, label_data=None, val_img_data=None, val_label_data=N
|
|
293
294
|
|
294
295
|
# make prediction
|
295
296
|
results, bm = predict_semantic_segmentation(bm,
|
296
|
-
header, img_header,
|
297
|
+
header, img_header,
|
297
298
|
region_of_interest, extension, img_data,
|
298
299
|
channels, normalization_parameters)
|
299
300
|
|
@@ -479,6 +480,14 @@ if __name__ == '__main__':
|
|
479
480
|
help='Processing queue when using a remote server')
|
480
481
|
parser.add_argument('-hf','--header_file', type=str, metavar='PATH', default=None,
|
481
482
|
help='Location of header file')
|
483
|
+
parser.add_argument('-s','--separation', action='store_true', default=False,
|
484
|
+
help='Instance segmentation of objects such as cells or rock particles')
|
485
|
+
parser.add_argument('-m','--mask', type=str, metavar='PATH', default=None,
|
486
|
+
help='Location of mask')
|
487
|
+
parser.add_argument('-rf','--refinement', action='store_true', default=False,
|
488
|
+
help='Refine segmentation on full size data')
|
489
|
+
parser.add_argument('-ext','--extension', type=str, default='.tif',
|
490
|
+
help='Save data for example as NRRD file using --extension=".nrrd"')
|
482
491
|
bm = parser.parse_args()
|
483
492
|
bm.success = True
|
484
493
|
|
@@ -107,7 +107,7 @@ def random_rotation_3d(image, max_angle=180):
|
|
107
107
|
class DataGenerator(tf.keras.utils.Sequence):
|
108
108
|
'Generates data for Keras'
|
109
109
|
def __init__(self, img, label, list_IDs_fg, list_IDs_bg, shuffle, train, classification, batch_size=32, dim=(32,32,32),
|
110
|
-
dim_img=(32,32,32), n_classes=10, n_channels=1, augment=(False,False,False,False,0), patch_normalization=False):
|
110
|
+
dim_img=(32,32,32), n_classes=10, n_channels=1, augment=(False,False,False,False,0), patch_normalization=False, separation=False):
|
111
111
|
'Initialization'
|
112
112
|
self.dim = dim
|
113
113
|
self.dim_img = dim_img
|
@@ -124,6 +124,7 @@ class DataGenerator(tf.keras.utils.Sequence):
|
|
124
124
|
self.classification = classification
|
125
125
|
self.on_epoch_end()
|
126
126
|
self.patch_normalization = patch_normalization
|
127
|
+
self.separation = separation
|
127
128
|
|
128
129
|
def __len__(self):
|
129
130
|
'Denotes the number of batches per epoch'
|
@@ -247,6 +248,13 @@ class DataGenerator(tf.keras.utils.Sequence):
|
|
247
248
|
tmp_X = self.img[k:k+self.dim[0],l:l+self.dim[1],m:m+self.dim[2]]
|
248
249
|
tmp_y = self.label[k:k+self.dim[0],l:l+self.dim[1],m:m+self.dim[2]]
|
249
250
|
|
251
|
+
# center label gets value 1
|
252
|
+
if self.separation:
|
253
|
+
centerLabel = tmp_y[self.dim[0]//2,self.dim[1]//2,self.dim[2]//2]
|
254
|
+
tmp_y = tmp_y.copy()
|
255
|
+
tmp_y[tmp_y!=centerLabel]=0
|
256
|
+
tmp_y[tmp_y==centerLabel]=1
|
257
|
+
|
250
258
|
# augmentation
|
251
259
|
if self.train:
|
252
260
|
|
@@ -416,25 +416,33 @@ def pre_processing(bm):
|
|
416
416
|
if bm.labelData is None:
|
417
417
|
return _error_(bm, 'Invalid label data.')
|
418
418
|
|
419
|
+
# dimension errors
|
419
420
|
if len(bm.labelData.shape) != 3:
|
420
|
-
return _error_(bm, 'Label must be three-dimensional.')
|
421
|
-
|
421
|
+
return _error_(bm, 'Label data must be three-dimensional.')
|
422
422
|
if bm.data.shape != bm.labelData.shape:
|
423
|
-
return _error_(bm, 'Image and label must have the same x,y,z-dimensions.')
|
423
|
+
return _error_(bm, 'Image and label data must have the same x,y,z-dimensions.')
|
424
|
+
|
425
|
+
# label data type
|
426
|
+
if bm.labelData.dtype in ['float16','float32','float64']:
|
427
|
+
if bm.django_env:
|
428
|
+
return _error_(bm, 'Label data must be of integer type.')
|
429
|
+
print(f'Warning: Potential label loss during conversion from {bm.labelData.dtype} to int32.')
|
430
|
+
bm.labelData = bm.labelData.astype(np.int32)
|
424
431
|
|
425
432
|
# get labels
|
426
433
|
bm.allLabels = np.unique(bm.labelData)
|
427
434
|
index = np.argwhere(bm.allLabels<0)
|
428
435
|
bm.allLabels = np.delete(bm.allLabels, index)
|
429
436
|
|
430
|
-
|
431
|
-
return _error_(bm, 'No labels higher than 255 allowed.')
|
432
|
-
|
437
|
+
# labels greater than 255
|
433
438
|
if np.any(bm.allLabels > 255):
|
434
|
-
bm.
|
435
|
-
|
436
|
-
|
437
|
-
|
439
|
+
if bm.django_env:
|
440
|
+
return _error_(bm, 'No labels greater than 255 allowed.')
|
441
|
+
else:
|
442
|
+
bm.labelData[bm.labelData > 255] = 0
|
443
|
+
index = np.argwhere(bm.allLabels > 255)
|
444
|
+
bm.allLabels = np.delete(bm.allLabels, index)
|
445
|
+
print('Warning: Only labels <=255 are allowed. Labels greater than 255 will be removed.')
|
438
446
|
|
439
447
|
# add background label if not existing
|
440
448
|
if not np.any(bm.allLabels==0):
|
@@ -486,7 +494,8 @@ def save_data(path_to_final, final, header=None, final_image_type=None, compress
|
|
486
494
|
np_to_nc(path_to_final, final, header)
|
487
495
|
elif final_image_type in ['.hdr', '.mhd', '.mha', '.nrrd', '.nii', '.nii.gz']:
|
488
496
|
simg = sitk.GetImageFromArray(final)
|
489
|
-
|
497
|
+
if header is not None:
|
498
|
+
simg.CopyInformation(header)
|
490
499
|
sitk.WriteImage(simg, path_to_final, useCompression=compress)
|
491
500
|
elif final_image_type in ['.zip', 'directory', '']:
|
492
501
|
with tempfile.TemporaryDirectory() as temp_dir:
|
@@ -542,7 +542,8 @@ def load_and_train(normalize,path_to_img,path_to_labels,path_to_model,
|
|
542
542
|
cropping_weights.append(arr)
|
543
543
|
|
544
544
|
# configuration data
|
545
|
-
cropping_config = np.array([channels, x_scale, y_scale, z_scale, normalize,
|
545
|
+
cropping_config = np.array([channels, x_scale, y_scale, z_scale, normalize,
|
546
|
+
normalization_parameters[0,0], normalization_parameters[1,0]])
|
546
547
|
|
547
548
|
return cropping_weights, cropping_config, normalization_parameters
|
548
549
|
|
@@ -355,7 +355,7 @@ def read_img_list(img_list, label_list, temp_img_dir, temp_label_dir):
|
|
355
355
|
label_names.append(label_name)
|
356
356
|
return img_names, label_names
|
357
357
|
|
358
|
-
def load_training_data(normalize, img_list, label_list, channels, x_scale, y_scale, z_scale, scaling,
|
358
|
+
def load_training_data(bm, normalize, img_list, label_list, channels, x_scale, y_scale, z_scale, scaling,
|
359
359
|
crop_data, labels_to_compute, labels_to_remove, img_in=None, label_in=None,
|
360
360
|
normalization_parameters=None, allLabels=None, header=None, extension='.tif',
|
361
361
|
x_puffer=25, y_puffer=25, z_puffer=25):
|
@@ -382,8 +382,9 @@ def load_training_data(normalize, img_list, label_list, channels, x_scale, y_sca
|
|
382
382
|
label_names = ['label_1']
|
383
383
|
label_dim = label.shape
|
384
384
|
label = set_labels_to_zero(label, labels_to_compute, labels_to_remove)
|
385
|
-
|
386
|
-
|
385
|
+
if scaling:
|
386
|
+
label_values, counts = np.unique(label, return_counts=True)
|
387
|
+
print(f'{os.path.basename(label_names[0])}:', 'Labels:', label_values[1:], 'Sizes:', counts[1:])
|
387
388
|
if crop_data:
|
388
389
|
argmin_z,argmax_z,argmin_y,argmax_y,argmin_x,argmax_x = predict_blocksize(label, x_puffer, y_puffer, z_puffer)
|
389
390
|
label = np.copy(label[argmin_z:argmax_z,argmin_y:argmax_y,argmin_x:argmax_x], order='C')
|
@@ -465,8 +466,9 @@ def load_training_data(normalize, img_list, label_list, channels, x_scale, y_sca
|
|
465
466
|
a = label_in[k]
|
466
467
|
label_dim = a.shape
|
467
468
|
a = set_labels_to_zero(a, labels_to_compute, labels_to_remove)
|
468
|
-
|
469
|
-
|
469
|
+
if scaling:
|
470
|
+
label_values, counts = np.unique(a, return_counts=True)
|
471
|
+
print(f'{os.path.basename(label_names[k])}:', 'Labels:', label_values[1:], 'Sizes:', counts[1:])
|
470
472
|
if crop_data:
|
471
473
|
argmin_z,argmax_z,argmin_y,argmax_y,argmin_x,argmax_x = predict_blocksize(a, x_puffer, y_puffer, z_puffer)
|
472
474
|
a = np.copy(a[argmin_z:argmax_z,argmin_y:argmax_y,argmin_x:argmax_x], order='C')
|
@@ -509,13 +511,16 @@ def load_training_data(normalize, img_list, label_list, channels, x_scale, y_sca
|
|
509
511
|
img[img<0] = 0
|
510
512
|
img[img>1] = 1
|
511
513
|
|
512
|
-
|
513
|
-
|
514
|
-
|
514
|
+
if bm.separation:
|
515
|
+
allLabels = np.array([0,1])
|
516
|
+
else:
|
517
|
+
# get labels
|
518
|
+
if allLabels is None:
|
519
|
+
allLabels = np.unique(label)
|
515
520
|
|
516
|
-
|
517
|
-
|
518
|
-
|
521
|
+
# labels must be in ascending order
|
522
|
+
for k, l in enumerate(allLabels):
|
523
|
+
label[label==l] = k
|
519
524
|
|
520
525
|
return img, label, allLabels, normalization_parameters, header, extension, channels
|
521
526
|
|
@@ -775,19 +780,21 @@ def train_semantic_segmentation(bm,
|
|
775
780
|
header=None, extension='.tif'):
|
776
781
|
|
777
782
|
# training data
|
778
|
-
img, label, allLabels, normalization_parameters, header, extension, bm.channels = load_training_data(bm.normalize,
|
783
|
+
img, label, allLabels, normalization_parameters, header, extension, bm.channels = load_training_data(bm, bm.normalize,
|
779
784
|
img_list, label_list, None, bm.x_scale, bm.y_scale, bm.z_scale, bm.scaling, bm.crop_data,
|
780
785
|
bm.only, bm.ignore, img, label, None, None, header, extension)
|
781
786
|
|
782
787
|
# configuration data
|
783
|
-
configuration_data = np.array([bm.channels,
|
788
|
+
configuration_data = np.array([bm.channels,
|
789
|
+
bm.x_scale, bm.y_scale, bm.z_scale, bm.normalize,
|
790
|
+
normalization_parameters[0,0], normalization_parameters[1,0]])
|
784
791
|
|
785
792
|
# img shape
|
786
793
|
zsh, ysh, xsh, _ = img.shape
|
787
794
|
|
788
795
|
# validation data
|
789
796
|
if any(val_img_list) or img_val is not None:
|
790
|
-
img_val, label_val, _, _, _, _, _ = load_training_data(bm.normalize,
|
797
|
+
img_val, label_val, _, _, _, _, _ = load_training_data(bm, bm.normalize,
|
791
798
|
val_img_list, val_label_list, bm.channels, bm.x_scale, bm.y_scale, bm.z_scale, bm.scaling, bm.crop_data,
|
792
799
|
bm.only, bm.ignore, img_val, label_val, normalization_parameters, allLabels)
|
793
800
|
|
@@ -815,7 +822,13 @@ def train_semantic_segmentation(bm,
|
|
815
822
|
for k in range(0, zsh-bm.z_patch+1, bm.stride_size):
|
816
823
|
for l in range(0, ysh-bm.y_patch+1, bm.stride_size):
|
817
824
|
for m in range(0, xsh-bm.x_patch+1, bm.stride_size):
|
818
|
-
|
825
|
+
if bm.separation:
|
826
|
+
centerLabel = label[k+bm.z_patch//2,l+bm.y_patch//2,m+bm.x_patch//2]
|
827
|
+
patch = label[k:k+bm.z_patch, l:l+bm.y_patch, m:m+bm.x_patch]
|
828
|
+
if centerLabel>0 and np.any(patch!=centerLabel):
|
829
|
+
list_IDs_fg.append(k*ysh*xsh+l*xsh+m)
|
830
|
+
else:
|
831
|
+
list_IDs_fg.append(k*ysh*xsh+l*xsh+m)
|
819
832
|
|
820
833
|
if img_val is not None:
|
821
834
|
|
@@ -838,7 +851,13 @@ def train_semantic_segmentation(bm,
|
|
838
851
|
for k in range(0, zsh_val-bm.z_patch+1, bm.validation_stride_size):
|
839
852
|
for l in range(0, ysh_val-bm.y_patch+1, bm.validation_stride_size):
|
840
853
|
for m in range(0, xsh_val-bm.x_patch+1, bm.validation_stride_size):
|
841
|
-
|
854
|
+
if bm.separation:
|
855
|
+
centerLabel = label_val[k+bm.z_patch//2,l+bm.y_patch//2,m+bm.x_patch//2]
|
856
|
+
patch = label_val[k:k+bm.z_patch, l:l+bm.y_patch, m:m+bm.x_patch]
|
857
|
+
if centerLabel>0 and np.any(patch!=centerLabel):
|
858
|
+
list_IDs_val_fg.append(k*ysh_val*xsh_val+l*xsh_val+m)
|
859
|
+
else:
|
860
|
+
list_IDs_val_fg.append(k*ysh_val*xsh_val+l*xsh_val+m)
|
842
861
|
|
843
862
|
# number of labels
|
844
863
|
nb_labels = len(allLabels)
|
@@ -853,7 +872,8 @@ def train_semantic_segmentation(bm,
|
|
853
872
|
'n_classes': nb_labels,
|
854
873
|
'n_channels': bm.channels,
|
855
874
|
'augment': (bm.flip_x, bm.flip_y, bm.flip_z, bm.swapaxes, bm.rotate),
|
856
|
-
'patch_normalization': bm.patch_normalization
|
875
|
+
'patch_normalization': bm.patch_normalization,
|
876
|
+
'separation': bm.separation}
|
857
877
|
|
858
878
|
# data generator
|
859
879
|
validation_generator = None
|
@@ -959,6 +979,10 @@ def load_prediction_data(bm, channels, normalize, normalization_parameters,
|
|
959
979
|
img_header = None
|
960
980
|
tif = TiffFile(bm.path_to_image)
|
961
981
|
img = imread(bm.path_to_image, key=range(z,min(len(tif.pages),z+bm.z_patch)))
|
982
|
+
if img.shape[0] < bm.z_patch:
|
983
|
+
rest = bm.z_patch - img.shape[0]
|
984
|
+
tmp = imread(bm.path_to_image, key=range(len(tif.pages)-rest,len(tif.pages)))
|
985
|
+
img = np.append(img, tmp[::-1], axis=0)
|
962
986
|
else:
|
963
987
|
img, img_header = load_data(bm.path_to_image, 'first_queue')
|
964
988
|
|
@@ -1031,8 +1055,25 @@ def append_ghost_areas(bm, img):
|
|
1031
1055
|
img = np.append(img, img[:,:,-x_rest:][:,:,::-1], axis=2)
|
1032
1056
|
return img, z_rest, y_rest, x_rest
|
1033
1057
|
|
1058
|
+
def gradient(volData):
|
1059
|
+
grad = np.zeros(volData.shape, dtype=np.uint8)
|
1060
|
+
tmp = np.abs(volData[:-1] - volData[1:])
|
1061
|
+
tmp[tmp>0]=1
|
1062
|
+
grad[:-1] += tmp
|
1063
|
+
grad[1:] += tmp
|
1064
|
+
tmp = np.abs(volData[:,:-1] - volData[:,1:])
|
1065
|
+
tmp[tmp>0]=1
|
1066
|
+
grad[:,:-1] += tmp
|
1067
|
+
grad[:,1:] += tmp
|
1068
|
+
tmp = np.abs(volData[:,:,:-1] - volData[:,:,1:])
|
1069
|
+
tmp[tmp>0]=1
|
1070
|
+
grad[:,:,:-1] += tmp
|
1071
|
+
grad[:,:,1:] += tmp
|
1072
|
+
grad[grad>0]=1
|
1073
|
+
return grad
|
1074
|
+
|
1034
1075
|
def predict_semantic_segmentation(bm,
|
1035
|
-
header, img_header,
|
1076
|
+
header, img_header,
|
1036
1077
|
region_of_interest, extension, img_data,
|
1037
1078
|
channels, normalization_parameters):
|
1038
1079
|
|
@@ -1040,7 +1081,8 @@ def predict_semantic_segmentation(bm,
|
|
1040
1081
|
results = {}
|
1041
1082
|
|
1042
1083
|
# number of labels
|
1043
|
-
nb_labels = len(allLabels)
|
1084
|
+
nb_labels = len(bm.allLabels)
|
1085
|
+
results['allLabels'] = bm.allLabels
|
1044
1086
|
|
1045
1087
|
# load model
|
1046
1088
|
if bm.dice_loss:
|
@@ -1065,6 +1107,13 @@ def predict_semantic_segmentation(bm,
|
|
1065
1107
|
zsh = len(tif.pages)
|
1066
1108
|
ysh, xsh = tif.pages[0].shape
|
1067
1109
|
|
1110
|
+
# load mask
|
1111
|
+
if bm.separation or bm.refinement:
|
1112
|
+
mask, _ = load_data(bm.mask)
|
1113
|
+
mask = mask.reshape(zsh, ysh, xsh, 1)
|
1114
|
+
mask, _, _, _ = append_ghost_areas(bm, mask)
|
1115
|
+
mask = mask.reshape(mask.shape[:-1])
|
1116
|
+
|
1068
1117
|
# determine new image size after appending ghost areas to make image dimensions divisible by patch size
|
1069
1118
|
z_rest = bm.z_patch - (zsh % bm.z_patch)
|
1070
1119
|
if z_rest == bm.z_patch:
|
@@ -1087,9 +1136,20 @@ def predict_semantic_segmentation(bm,
|
|
1087
1136
|
for k in range(0, zsh-bm.z_patch+1, bm.stride_size):
|
1088
1137
|
for l in range(0, ysh-bm.y_patch+1, bm.stride_size):
|
1089
1138
|
for m in range(0, xsh-bm.x_patch+1, bm.stride_size):
|
1090
|
-
|
1139
|
+
if bm.separation:
|
1140
|
+
centerLabel = mask[k+bm.z_patch//2,l+bm.y_patch//2,m+bm.x_patch//2]
|
1141
|
+
patch = mask[k:k+bm.z_patch, l:l+bm.y_patch, m:m+bm.x_patch]
|
1142
|
+
if centerLabel>0 and np.any(patch!=centerLabel):
|
1143
|
+
list_IDs.append(k*ysh*xsh+l*xsh+m)
|
1144
|
+
elif bm.refinement:
|
1145
|
+
patch = mask[k:k+bm.z_patch, l:l+bm.y_patch, m:m+bm.x_patch]
|
1146
|
+
if np.any(patch==0) and np.any(patch!=0):
|
1147
|
+
list_IDs.append(k*ysh*xsh+l*xsh+m)
|
1148
|
+
else:
|
1149
|
+
list_IDs.append(k*ysh*xsh+l*xsh+m)
|
1091
1150
|
|
1092
1151
|
# make length of list divisible by batch size
|
1152
|
+
max_i = len(list_IDs)
|
1093
1153
|
rest = bm.batch_size - (len(list_IDs) % bm.batch_size)
|
1094
1154
|
list_IDs = list_IDs + list_IDs[:rest]
|
1095
1155
|
|
@@ -1177,27 +1237,37 @@ def predict_semantic_segmentation(bm,
|
|
1177
1237
|
img, _, _, _ = append_ghost_areas(bm, img)
|
1178
1238
|
|
1179
1239
|
# list of IDs
|
1180
|
-
|
1240
|
+
list_IDs_block = []
|
1181
1241
|
|
1182
1242
|
# get Ids of patches
|
1183
1243
|
for l in range(0, ysh-bm.y_patch+1, bm.stride_size):
|
1184
1244
|
for m in range(0, xsh-bm.x_patch+1, bm.stride_size):
|
1185
|
-
|
1245
|
+
if bm.separation:
|
1246
|
+
centerLabel = mask[z+bm.z_patch//2,l+bm.y_patch//2,m+bm.x_patch//2]
|
1247
|
+
patch = mask[z:z+bm.z_patch, l:l+bm.y_patch, m:m+bm.x_patch]
|
1248
|
+
if centerLabel>0 and np.any(patch!=centerLabel):
|
1249
|
+
list_IDs_block.append(z*ysh*xsh+l*xsh+m)
|
1250
|
+
elif bm.refinement:
|
1251
|
+
patch = mask[z:z+bm.z_patch, l:l+bm.y_patch, m:m+bm.x_patch]
|
1252
|
+
if np.any(patch==0) and np.any(patch!=0):
|
1253
|
+
list_IDs_block.append(z*ysh*xsh+l*xsh+m)
|
1254
|
+
else:
|
1255
|
+
list_IDs_block.append(z*ysh*xsh+l*xsh+m)
|
1186
1256
|
|
1187
1257
|
# make length of list divisible by batch size
|
1188
|
-
|
1189
|
-
rest = bm.batch_size - (len(
|
1190
|
-
|
1258
|
+
max_i_block = len(list_IDs_block)
|
1259
|
+
rest = bm.batch_size - (len(list_IDs_block) % bm.batch_size)
|
1260
|
+
list_IDs_block = list_IDs_block + list_IDs_block[:rest]
|
1191
1261
|
|
1192
1262
|
# number of patches
|
1193
|
-
nb_patches = len(
|
1263
|
+
nb_patches = len(list_IDs_block)
|
1194
1264
|
|
1195
1265
|
# allocate tmp probabilities array
|
1196
1266
|
probs = np.zeros((bm.z_patch, ysh, xsh, nb_labels), dtype=np.float32)
|
1197
1267
|
|
1198
1268
|
# get one batch of image patches
|
1199
1269
|
for step in range(nb_patches//bm.batch_size):
|
1200
|
-
for i, ID in enumerate(
|
1270
|
+
for i, ID in enumerate(list_IDs_block[step*bm.batch_size:(step+1)*bm.batch_size]):
|
1201
1271
|
|
1202
1272
|
# get patch indices
|
1203
1273
|
k=0 if load_blockwise else ID // (ysh*xsh)
|
@@ -1218,29 +1288,46 @@ def predict_semantic_segmentation(bm,
|
|
1218
1288
|
Y = model.predict(X, verbose=0, steps=None, batch_size=bm.batch_size)
|
1219
1289
|
|
1220
1290
|
# loop over result patches
|
1221
|
-
for i, ID in enumerate(
|
1291
|
+
for i, ID in enumerate(list_IDs_block[step*bm.batch_size:(step+1)*bm.batch_size]):
|
1222
1292
|
rest = ID % (ysh*xsh)
|
1223
1293
|
l = rest // xsh
|
1224
1294
|
m = rest % xsh
|
1225
|
-
if i <
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1295
|
+
if step*bm.batch_size+i < max_i_block:
|
1296
|
+
if bm.separation:
|
1297
|
+
patch = np.argmax(Y[i], axis=-1).astype(np.uint8)
|
1298
|
+
label[z:z+bm.z_patch,l:l+bm.y_patch,m:m+bm.x_patch] += gradient(patch)
|
1299
|
+
else:
|
1300
|
+
probs[:,l:l+bm.y_patch,m:m+bm.x_patch] += Y[i]
|
1301
|
+
|
1302
|
+
if not bm.separation:
|
1303
|
+
# overlap in z direction
|
1304
|
+
if bm.stride_size < bm.z_patch:
|
1305
|
+
if j>0:
|
1306
|
+
probs[:bm.stride_size] += overlap
|
1307
|
+
overlap = probs[bm.stride_size:].copy()
|
1308
|
+
|
1309
|
+
# calculate result
|
1310
|
+
if z==z_indices[-1]:
|
1311
|
+
label[z:z+bm.z_patch] = np.argmax(probs, axis=-1).astype(np.uint8)
|
1312
|
+
if bm.return_probs:
|
1313
|
+
final[z:z+bm.z_patch] = probs
|
1314
|
+
else:
|
1315
|
+
block_zsh = min(bm.stride_size, bm.z_patch)
|
1316
|
+
label[z:z+block_zsh] = np.argmax(probs[:block_zsh], axis=-1).astype(np.uint8)
|
1317
|
+
if bm.return_probs:
|
1318
|
+
final[z:z+block_zsh] = probs[:block_zsh]
|
1319
|
+
|
1320
|
+
# refine mask data with result
|
1321
|
+
if bm.refinement:
|
1322
|
+
# loop over boundary patches
|
1323
|
+
for i, ID in enumerate(list_IDs):
|
1324
|
+
if i < max_i:
|
1325
|
+
k = ID // (ysh*xsh)
|
1326
|
+
rest = ID % (ysh*xsh)
|
1327
|
+
l = rest // xsh
|
1328
|
+
m = rest % xsh
|
1329
|
+
mask[k:k+bm.z_patch, l:l+bm.y_patch, m:m+bm.x_patch] = label[k:k+bm.z_patch, l:l+bm.y_patch, m:m+bm.x_patch]
|
1330
|
+
label = mask
|
1244
1331
|
|
1245
1332
|
# remove appendix
|
1246
1333
|
if bm.return_probs:
|
@@ -1280,7 +1367,8 @@ def predict_semantic_segmentation(bm,
|
|
1280
1367
|
label = np.copy(tmp, order='C')
|
1281
1368
|
|
1282
1369
|
# get result
|
1283
|
-
|
1370
|
+
if not bm.separation:
|
1371
|
+
label = get_labels(label, bm.allLabels)
|
1284
1372
|
results['regular'] = label
|
1285
1373
|
|
1286
1374
|
# load header from file
|
@@ -154,6 +154,7 @@ def smart_interpolation(data, labelData, nbrw=10, sorw=4000, acwe=False, acwe_al
|
|
154
154
|
bm.data /= np.amax(bm.data)
|
155
155
|
bm.data *= 255.0
|
156
156
|
if bm.labelData.dtype in ['uint32','int64','uint64']:
|
157
|
+
print(f'Warning: Potential label loss during conversion from {bm.labelData.dtype} to int32.')
|
157
158
|
bm.labelData = bm.labelData.astype(np.int32)
|
158
159
|
|
159
160
|
# denoise image data
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: biomedisa
|
3
|
-
Version: 24.
|
3
|
+
Version: 24.8.2
|
4
4
|
Summary: Segmentation of 3D volumetric image data
|
5
5
|
Author: Philipp Lösel
|
6
6
|
Author-email: philipp.loesel@anu.edu.au
|
@@ -36,17 +36,17 @@ License-File: LICENSE
|
|
36
36
|
Biomedisa (https://biomedisa.info) is a free and easy-to-use open-source application for segmenting large 3D volumetric images such as CT and MRI scans, developed at [The Australian National University CTLab](https://ctlab.anu.edu.au/). Biomedisa's smart interpolation of sparsely pre-segmented slices enables accurate semi-automated segmentation by considering the complete underlying image data. Additionally, Biomedisa enables deep learning for fully automated segmentation across similar samples and structures. It is compatible with segmentation tools like Amira/Avizo, ImageJ/Fiji and 3D Slicer. If you are using Biomedisa or the data for your research please cite: Lösel, P.D. et al. [Introducing Biomedisa as an open-source online platform for biomedical image segmentation.](https://www.nature.com/articles/s41467-020-19303-w) *Nat. Commun.* **11**, 5577 (2020).
|
37
37
|
|
38
38
|
## Hardware Requirements
|
39
|
-
+ One or more NVIDIA GPUs with compute capability 3.0 or higher
|
39
|
+
+ One or more NVIDIA GPUs with compute capability 3.0 or higher.
|
40
40
|
|
41
41
|
## Installation (command-line based)
|
42
|
-
+ [Ubuntu 22.04 +
|
43
|
-
+ [Ubuntu 22.04 +
|
44
|
-
+ [Windows 10 +
|
45
|
-
+ [Windows
|
46
|
-
+ [Windows 10 + OpenCL + CPU (very slow)](https://github.com/biomedisa/biomedisa/blob/master/README/windows10_opencl_cpu_cli.md)
|
42
|
+
+ [Ubuntu 22.04 + Smart Interpolation](https://github.com/biomedisa/biomedisa/blob/master/README/ubuntu2204_interpolation_cli.md)
|
43
|
+
+ [Ubuntu 22.04 + Smart Interpolation + Deep Learning](https://github.com/biomedisa/biomedisa/blob/master/README/ubuntu2204_cuda11.8_gpu_cli.md)
|
44
|
+
+ [Windows 10 + Smart Interpolation + Deep Learning](https://github.com/biomedisa/biomedisa/blob/master/README/windows10_cuda_gpu_cli.md)
|
45
|
+
+ [Windows (WSL) + Smart Interpolation + Deep Learning](https://github.com/biomedisa/biomedisa/blob/master/README/windows_wsl.md)
|
47
46
|
|
48
47
|
## Installation (3D Slicer extension)
|
49
|
-
+ [Ubuntu 22.04 +
|
48
|
+
+ [Ubuntu 22.04 + Smart Interpolation + Deep Learning](https://github.com/biomedisa/biomedisa/blob/master/README/ubuntu2204_cuda11.8_gpu_slicer.md)
|
49
|
+
+ [Windows 10 + Smart Interpolation](https://github.com/biomedisa/biomedisa/blob/master/README/windows10_cuda_gpu_slicer.md)
|
50
50
|
|
51
51
|
## Installation (browser based)
|
52
52
|
+ [Ubuntu 22.04](https://github.com/biomedisa/biomedisa/blob/master/README/ubuntu2204_cuda11.8.md)
|
@@ -58,6 +58,7 @@ Biomedisa (https://biomedisa.info) is a free and easy-to-use open-source applica
|
|
58
58
|
24.7.1
|
59
59
|
+ 3D Slicer extension
|
60
60
|
+ Prediction of large data block by block
|
61
|
+
|
61
62
|
24.5.22
|
62
63
|
+ Pip is the preferred installation method
|
63
64
|
+ Commands, module names and imports have been changed to conform to the Pip standard
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/amira_to_np/amira_data_stream.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/random_walk/pycuda_large_allx.py
RENAMED
File without changes
|
File without changes
|
{biomedisa-24.7.1 → biomedisa-24.8.2}/src/biomedisa/features/random_walk/pycuda_small_allx.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|