biomedisa 24.7.1__py3-none-any.whl → 24.8.2__py3-none-any.whl

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/deeplearning.py CHANGED
@@ -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, allLabels,
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
- if bm.django_env and np.any(bm.allLabels > 255):
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.labelData[bm.labelData > 255] = 0
435
- index = np.argwhere(bm.allLabels > 255)
436
- bm.allLabels = np.delete(bm.allLabels, index)
437
- print('Warning: Only labels <=255 are allowed. Labels higher than 255 will be removed.')
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
- simg.CopyInformation(header)
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, 0, 1])
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
- label_values, counts = np.unique(label, return_counts=True)
386
- print(f'{os.path.basename(label_names[0])}:', 'Labels:', label_values[1:], 'Sizes:', counts[1:])
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
- label_values, counts = np.unique(a, return_counts=True)
469
- print(f'{os.path.basename(label_names[k])}:', 'Labels:', label_values[1:], 'Sizes:', counts[1:])
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
- # get labels
513
- if allLabels is None:
514
- allLabels = np.unique(label)
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
- # labels must be in ascending order
517
- for k, l in enumerate(allLabels):
518
- label[label==l] = k
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, bm.x_scale, bm.y_scale, bm.z_scale, bm.normalize, 0, 1])
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
- list_IDs_fg.append(k*ysh*xsh+l*xsh+m)
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
- list_IDs_val_fg.append(k*ysh_val*xsh_val+l*xsh_val+m)
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, allLabels,
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
- list_IDs.append(k*ysh*xsh+l*xsh+m)
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
- list_IDs = []
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
- list_IDs.append(z*ysh*xsh+l*xsh+m)
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
- max_i = len(list_IDs)
1189
- rest = bm.batch_size - (len(list_IDs) % bm.batch_size)
1190
- list_IDs = list_IDs + list_IDs[:rest]
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(list_IDs)
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(list_IDs[step*bm.batch_size:(step+1)*bm.batch_size]):
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(list_IDs[step*bm.batch_size:(step+1)*bm.batch_size]):
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 < max_i:
1226
- probs[:,l:l+bm.y_patch,m:m+bm.x_patch] += Y[i]
1227
-
1228
- # overlap in z direction
1229
- if bm.stride_size < bm.z_patch:
1230
- if j>0:
1231
- probs[:bm.stride_size] += overlap
1232
- overlap = probs[bm.stride_size:].copy()
1233
-
1234
- # calculate result
1235
- if z==z_indices[-1]:
1236
- label[z:z+bm.z_patch] = np.argmax(probs, axis=-1).astype(np.uint8)
1237
- if bm.return_probs:
1238
- final[z:z+bm.z_patch] = probs
1239
- else:
1240
- block_zsh = min(bm.stride_size, bm.z_patch)
1241
- label[z:z+block_zsh] = np.argmax(probs[:block_zsh], axis=-1).astype(np.uint8)
1242
- if bm.return_probs:
1243
- final[z:z+block_zsh] = probs[:block_zsh]
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
- label = get_labels(label, allLabels)
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.7.1
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 or an Intel CPU
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 + CUDA + GPU (recommended)](https://github.com/biomedisa/biomedisa/blob/master/README/ubuntu2204_cuda11.8_gpu_cli.md)
43
- + [Ubuntu 22.04 + OpenCL + CPU (very slow)](https://github.com/biomedisa/biomedisa/blob/master/README/ubuntu2204_opencl_cpu_cli.md)
44
- + [Windows 10 + CUDA + GPU (recommended)](https://github.com/biomedisa/biomedisa/blob/master/README/windows10_cuda_gpu_cli.md)
45
- + [Windows 10 + OpenCL + GPU (easy to install but lacks features like allaxis, smoothing, uncertainty, optimized GPU memory usage)](https://github.com/biomedisa/biomedisa/blob/master/README/windows10_opencl_gpu_cli.md)
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 + CUDA + GPU](https://github.com/biomedisa/biomedisa/blob/master/README/ubuntu2204_cuda11.8_gpu_slicer.md)
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
@@ -1,21 +1,21 @@
1
1
  biomedisa/__init__.py,sha256=hw4mzEjGFXm-vxus2DBfKFW0nKoG0ibL5SH6ShfchrY,1526
2
2
  biomedisa/__main__.py,sha256=a1--8vhtztWEloHVtbM43FZLCfrFo4BELgdsgtWE8ls,536
3
- biomedisa/deeplearning.py,sha256=eVFoy3FsSb8h2hqFBdI8kz63tATLUvuMfSPzSa_wX5Q,27813
4
- biomedisa/interpolation.py,sha256=tehhMhm3WEVzUpfAemujMixJMK6BMNLQ6uw7Z9TR9Go,17163
3
+ biomedisa/deeplearning.py,sha256=myCIJqwMj707qzgba-BgNO92UGHqXyy_l63UGfmUz08,28479
4
+ biomedisa/interpolation.py,sha256=i10aqwEl-wsVU_nQ-zyubhAs27NSKF4ial7LyhaBLv0,17273
5
5
  biomedisa/mesh.py,sha256=8-iuVsrfW5JovaMrAez7qSxv1LCU3eiqOdik0s0DV1w,16062
6
- biomedisa/features/DataGenerator.py,sha256=MYPSY9-ssMwPx9UOI_ZfE7_5rddOSn4aHbVQ0HtYQVA,12757
6
+ biomedisa/features/DataGenerator.py,sha256=MINc7emhELPxACOYdnLFHgh-RHUKODLH0DH7zz6u6mc,13116
7
7
  biomedisa/features/DataGeneratorCrop.py,sha256=23R4Z-8tB1CsjYTYfhHGovlJpAny_q9OV9hq8kc2GJg,5454
8
8
  biomedisa/features/PredictDataGenerator.py,sha256=JH8SPGQm-Y7_Drec2fw3jBUupvpIkQ1FvkDXP7mUjDY,4074
9
9
  biomedisa/features/PredictDataGeneratorCrop.py,sha256=HF5tJbGtlJMHr7lMT9IiIdLG2CTjXstbKoOjlZJ93Is,3431
10
10
  biomedisa/features/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  biomedisa/features/active_contour.py,sha256=FnPuvYck_KL4xYRFqwzm4Grdm288EdlcLFt88E0OtqA,17938
12
12
  biomedisa/features/assd.py,sha256=q9NUQXEoA4Pi3d8b5fmys615CWu06Sm0N9-OGwJOFnw,6537
13
- biomedisa/features/biomedisa_helper.py,sha256=d5wCtiP8pRTUbXv-jrN-b7cNStm8T1B_FtQR2Msd5OY,32286
13
+ biomedisa/features/biomedisa_helper.py,sha256=oIsOmIJ8xUQVwgbzMgw65dXcZmzwePpFQoIdbgLTnF8,32727
14
14
  biomedisa/features/create_slices.py,sha256=uSDH1OcEYc5BFPZHSy3UpS4P2DuoVnxOZ-l7wmyT_Po,13108
15
- biomedisa/features/crop_helper.py,sha256=si72n9Q-C7U0cXYOD9Ux2UqIbZdXbZSOARBYDeqRggI,24533
15
+ biomedisa/features/crop_helper.py,sha256=5do03z_DT13qWRR6IGtkFn4BNaw0mWmUXgg3Lk-U6QY,24597
16
16
  biomedisa/features/curvop_numba.py,sha256=AjKQJcUBoURTB8pq1HmugQYpBwBELthhcEu51_r_xPI,7049
17
17
  biomedisa/features/django_env.py,sha256=pdiPcBpqu1BWuyvh-palIGVwHFaY-leQ4Gatlbm8hIg,8942
18
- biomedisa/features/keras_helper.py,sha256=0rgMLD3mvLuV9PFbsOwypH4fr3IhPkQveCtUiqTCZdc,57270
18
+ biomedisa/features/keras_helper.py,sha256=bPA4wc2W3kPRLKd7qcHE6nXJ4sOm8lKHvCB5yC4NGOI,61587
19
19
  biomedisa/features/nc_reader.py,sha256=RoRMwu3ELSNfoV3qZtaT2OWACnXb2EhNFu_DAF1T93o,7406
20
20
  biomedisa/features/pid.py,sha256=Jmn1VIp0fBlgBrqZ-yUIQVVb5-NAxNBdibXALVr2PPI,2545
21
21
  biomedisa/features/process_image.py,sha256=VtS3fGDvglqJiiJLPK1toe76J58j914NJ8XQKg3CRwo,11091
@@ -37,8 +37,8 @@ biomedisa/features/random_walk/pyopencl_large.py,sha256=q79AxG3p3qFjxfiAZfUK9I5B
37
37
  biomedisa/features/random_walk/pyopencl_small.py,sha256=opNlS-qzOa9qWafBNJdvf6r1aRAFf7_JXf6ISDnkdXE,17068
38
38
  biomedisa/features/random_walk/rw_large.py,sha256=ZnITvk00Y11ZZlGuBRaJO1EwU0wYBdEwdpj9vvXCqF4,19805
39
39
  biomedisa/features/random_walk/rw_small.py,sha256=RPzZe24YrEwYelJukDjvqaoD_SyhgdriEi7uV3kZGXI,14881
40
- biomedisa-24.7.1.dist-info/LICENSE,sha256=sehayP6UhydNnmstfL4yFR3genMRdpuUh6uZVWJN1H0,14152
41
- biomedisa-24.7.1.dist-info/METADATA,sha256=4ziBlBpd6JbYp9YSmxs0ptZpm_XX3J4pERQAL6Kg118,10631
42
- biomedisa-24.7.1.dist-info/WHEEL,sha256=Wyh-_nZ0DJYolHNn1_hMa4lM7uDedD_RGVwbmTjyItk,91
43
- biomedisa-24.7.1.dist-info/top_level.txt,sha256=opsf1Eb4vCguPSxev4HHSeiUKCccT_C_RcUCdAYbHWQ,10
44
- biomedisa-24.7.1.dist-info/RECORD,,
40
+ biomedisa-24.8.2.dist-info/LICENSE,sha256=sehayP6UhydNnmstfL4yFR3genMRdpuUh6uZVWJN1H0,14152
41
+ biomedisa-24.8.2.dist-info/METADATA,sha256=WNs0EZIdWznoBXsBUHlpUo1WhlgcKTx7tH5oxR0dCXw,10569
42
+ biomedisa-24.8.2.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
43
+ biomedisa-24.8.2.dist-info/top_level.txt,sha256=opsf1Eb4vCguPSxev4HHSeiUKCccT_C_RcUCdAYbHWQ,10
44
+ biomedisa-24.8.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (71.1.0)
2
+ Generator: setuptools (74.1.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5