biomedisa 24.8.11__py3-none-any.whl → 25.6.1__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
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/python3
2
2
  ##########################################################################
3
3
  ## ##
4
- ## Copyright (c) 2019-2024 Philipp Lösel. All rights reserved. ##
4
+ ## Copyright (c) 2019-2025 Philipp Lösel. All rights reserved. ##
5
5
  ## ##
6
6
  ## This file is part of the open source project biomedisa. ##
7
7
  ## ##
@@ -77,7 +77,8 @@ def deep_learning(img_data, label_data=None, val_img_data=None, val_label_data=N
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
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
+ separation=False, mask=None, refinement=False, ignore_mask=False, mixed_precision=False,
81
+ slicer=False, path_to_data=None):
81
82
 
82
83
  # create biomedisa
83
84
  bm = Biomedisa()
@@ -91,6 +92,7 @@ def deep_learning(img_data, label_data=None, val_img_data=None, val_label_data=N
91
92
  key_copy = tuple(locals().keys())
92
93
  for arg in key_copy:
93
94
  bm.__dict__[arg] = locals()[arg]
95
+ bm.path_to_data = bm.path_to_images
94
96
 
95
97
  # normalization
96
98
  bm.normalize = 1 if bm.normalization else 0
@@ -214,10 +216,16 @@ def deep_learning(img_data, label_data=None, val_img_data=None, val_label_data=N
214
216
 
215
217
  if bm.predict:
216
218
 
217
- # get meta data
218
- hf = h5py.File(bm.path_to_model, 'r')
219
- meta = hf.get('meta')
220
- configuration = meta.get('configuration')
219
+ # load model
220
+ try:
221
+ hf = h5py.File(bm.path_to_model, 'r')
222
+ meta = hf.get('meta')
223
+ configuration = meta.get('configuration')
224
+ bm.allLabels = np.array(meta.get('labels'))
225
+ except:
226
+ raise RuntimeError("Invalid model.")
227
+
228
+ # get configuration
221
229
  channels, bm.x_scale, bm.y_scale, bm.z_scale, bm.normalize, mu, sig = np.array(configuration)[:]
222
230
  channels, bm.x_scale, bm.y_scale, bm.z_scale, bm.normalize, mu, sig = int(channels), int(bm.x_scale), \
223
231
  int(bm.y_scale), int(bm.z_scale), int(bm.normalize), float(mu), float(sig)
@@ -225,7 +233,6 @@ def deep_learning(img_data, label_data=None, val_img_data=None, val_label_data=N
225
233
  normalization_parameters = np.array(meta['normalization'], dtype=float)
226
234
  else:
227
235
  normalization_parameters = np.array([[mu],[sig]])
228
- bm.allLabels = np.array(meta.get('labels'))
229
236
  if 'patch_normalization' in meta:
230
237
  bm.patch_normalization = bool(meta['patch_normalization'][()])
231
238
  if 'scaling' in meta:
@@ -506,6 +513,12 @@ if __name__ == '__main__':
506
513
  help='Save data in formats like NRRD or TIFF using --extension=".nrrd"')
507
514
  parser.add_argument('-ptm','--path_to_model', type=str, metavar='PATH', default=None,
508
515
  help='Specify the model location for training')
516
+ parser.add_argument('-im','--ignore_mask', action='store_true', default=False,
517
+ help='Use a binary mask in the second channel of the label file to define ignored (0) and considered (1) areas during training')
518
+ parser.add_argument('-mp','--mixed_precision', action='store_true', default=False,
519
+ help='Use mixed precision in model')
520
+ parser.add_argument('--slicer', action='store_true', default=False,
521
+ help='Required for starting Biomedisa from 3D Slicer')
509
522
  bm = parser.parse_args()
510
523
  bm.success = True
511
524
 
@@ -543,6 +556,12 @@ if __name__ == '__main__':
543
556
  bm.django_env = False
544
557
 
545
558
  kwargs = vars(bm)
559
+ bm.path_to_data = bm.path_to_images
560
+
561
+ # verify model
562
+ if bm.predict and os.path.splitext(bm.path)[1] != '.h5':
563
+ bm = _error_(bm, "Invalid model.")
564
+ raise RuntimeError("Invalid model.")
546
565
 
547
566
  # train or predict segmentation
548
567
  try:
@@ -561,5 +580,5 @@ if __name__ == '__main__':
561
580
  bm = _error_(bm, 'GPU out of memory. Reduce your batch size')
562
581
  except Exception as e:
563
582
  print(traceback.format_exc())
564
- bm = _error_(bm, e)
583
+ bm = _error_(bm, str(e))
565
584
 
@@ -1,6 +1,6 @@
1
1
  ##########################################################################
2
2
  ## ##
3
- ## Copyright (c) 2019-2024 Philipp Lösel. All rights reserved. ##
3
+ ## Copyright (c) 2019-2025 Philipp Lösel. All rights reserved. ##
4
4
  ## ##
5
5
  ## This file is part of the open source project biomedisa. ##
6
6
  ## ##
@@ -26,11 +26,11 @@
26
26
  ## ##
27
27
  ##########################################################################
28
28
 
29
+ from biomedisa.features.biomedisa_helper import welford_mean_std
29
30
  import numpy as np
30
31
  import tensorflow as tf
31
32
  import numba
32
33
  import random
33
- import scipy
34
34
 
35
35
  def get_random_rotation_matrix(batch_size):
36
36
  angle_xy = np.random.uniform(0, 2. * np.pi, batch_size)
@@ -80,7 +80,6 @@ def rotate_img_patch(src,trg,k,l,m,cos_a,sin_a,z_patch,y_patch,x_patch,imageHeig
80
80
  trg[z-k,y-l,x-m] = val
81
81
  return trg
82
82
 
83
-
84
83
  @numba.jit(nopython=True)#parallel=True
85
84
  def rotate_img_patch_3d(src,trg,k,l,m,rm_xx,rm_xy,rm_xz,rm_yx,rm_yy,rm_yz,rm_zx,rm_zy,rm_zz,z_patch,y_patch,x_patch,imageVertStride,imageDepth,imageHeight,imageWidth):
86
85
  #return rotate_label_patch_3d(src,trg,k,l,m,rm_xx,rm_xy,rm_xz,rm_yx,rm_yy,rm_yz,rm_zx,rm_zy,rm_zz,z_patch,y_patch,x_patch,imageVertStride,imageDepth,imageHeight,imageWidth)
@@ -175,34 +174,11 @@ def rotate_label_patch_3d(src,trg,k,l,m,rm_xx,rm_xy,rm_xz,rm_yx,rm_yy,rm_yz,rm_z
175
174
  trg[z-k,y-l,x-m] = src[idx_src_z,idx_src_y,idx_src_x]
176
175
  return trg
177
176
 
178
- def random_rotation_3d(image, max_angle=180):
179
- """ Randomly rotate an image by a random angle (-max_angle, max_angle).
180
-
181
- Arguments:
182
- max_angle: `float`. The maximum rotation angle.
183
-
184
- Returns:
185
- batch of rotated 3D images
186
- """
187
-
188
- # rotate along x-axis
189
- angle = random.uniform(-max_angle, max_angle)
190
- image2 = scipy.ndimage.rotate(image, angle, mode='nearest', axes=(0, 1), reshape=False)
191
-
192
- # rotate along y-axis
193
- angle = random.uniform(-max_angle, max_angle)
194
- image3 = scipy.ndimage.rotate(image2, angle, mode='nearest', axes=(0, 2), reshape=False)
195
-
196
- # rotate along z-axis
197
- angle = random.uniform(-max_angle, max_angle)
198
- image_rot = scipy.ndimage.rotate(image3, angle, mode='nearest', axes=(1, 2), reshape=False)
199
-
200
- return image_rot
201
-
202
177
  class DataGenerator(tf.keras.utils.Sequence):
203
178
  'Generates data for Keras'
204
- def __init__(self, img, label, list_IDs_fg, list_IDs_bg, shuffle, train, classification, batch_size=32, dim=(32,32,32),
205
- dim_img=(32,32,32), n_classes=10, n_channels=1, augment=(False,False,False,False,0,False), patch_normalization=False, separation=False):
179
+ def __init__(self, img, label, list_IDs_fg, list_IDs_bg, shuffle, train, batch_size=32, dim=(32,32,32),
180
+ dim_img=(32,32,32), n_classes=10, n_channels=1, augment=(False,False,False,False,0,False),
181
+ patch_normalization=False, separation=False, ignore_mask=False):
206
182
  'Initialization'
207
183
  self.dim = dim
208
184
  self.dim_img = dim_img
@@ -216,10 +192,10 @@ class DataGenerator(tf.keras.utils.Sequence):
216
192
  self.shuffle = shuffle
217
193
  self.augment = augment
218
194
  self.train = train
219
- self.classification = classification
220
195
  self.on_epoch_end()
221
196
  self.patch_normalization = patch_normalization
222
197
  self.separation = separation
198
+ self.ignore_mask = ignore_mask
223
199
 
224
200
  def __len__(self):
225
201
  'Denotes the number of batches per epoch'
@@ -276,12 +252,12 @@ class DataGenerator(tf.keras.utils.Sequence):
276
252
  def __data_generation(self, list_IDs_temp):
277
253
  'Generates data containing batch_size samples' # X : (n_samples, *dim, n_channels)
278
254
 
279
- # Initialization
255
+ # number of label channels
256
+ label_channels = 2 if self.ignore_mask else 1
257
+
258
+ # allocate memory
280
259
  X = np.empty((self.batch_size, *self.dim, self.n_channels), dtype=np.float32)
281
- if self.classification:
282
- y = np.empty((self.batch_size, 1), dtype=np.int32)
283
- else:
284
- y = np.empty((self.batch_size, *self.dim, 1), dtype=np.int32)
260
+ y = np.empty((self.batch_size, *self.dim, label_channels), dtype=np.int32)
285
261
 
286
262
  # get augmentation parameter
287
263
  flip_x, flip_y, flip_z, swapaxes, rotate, rotate3d = self.augment
@@ -306,119 +282,92 @@ class DataGenerator(tf.keras.utils.Sequence):
306
282
  m = rest % self.dim_img[2]
307
283
 
308
284
  # get patch
309
- if self.classification:
310
- tmp_X = self.img[k:k+self.dim[0],l:l+self.dim[1],m:m+self.dim[2]]
311
- tmp_y = self.label[k,l,m]
312
-
313
- # augmentation
314
- if self.train:
315
-
316
- # rotate in 3D
317
- if rotate:
318
- tmp_X = random_rotation_3d(tmp_X, max_angle=rotate)
319
-
320
- # flip patch along axes
321
- v = np.random.randint(n_aug+1)
322
- if np.any([flip_x, flip_y, flip_z]) and v>0:
323
- flip = flips[v-1]
324
- tmp_X = np.flip(tmp_X, flip)
325
-
326
- # swap axes
327
- if swapaxes:
328
- v = np.random.randint(4)
329
- if v==1:
330
- tmp_X = np.swapaxes(tmp_X,0,1)
331
- elif v==2:
332
- tmp_X = np.swapaxes(tmp_X,0,2)
333
- elif v==3:
334
- tmp_X = np.swapaxes(tmp_X,1,2)
335
-
336
- # assign to batch
337
- X[i,:,:,:,0] = tmp_X
338
- y[i,0] = tmp_y
339
-
340
- else:
341
- # get patch
342
- tmp_X = self.img[k:k+self.dim[0],l:l+self.dim[1],m:m+self.dim[2]]
343
- tmp_y = self.label[k:k+self.dim[0],l:l+self.dim[1],m:m+self.dim[2]]
344
-
345
- # center label gets value 1
346
- if self.separation:
347
- centerLabel = tmp_y[self.dim[0]//2,self.dim[1]//2,self.dim[2]//2]
348
- tmp_y = tmp_y.copy()
349
- tmp_y[tmp_y!=centerLabel]=0
350
- tmp_y[tmp_y==centerLabel]=1
351
-
352
- # augmentation
353
- if self.train:
354
-
355
- # rotate in xy plane
356
- if rotate:
357
- tmp_X = np.empty((*self.dim, self.n_channels), dtype=np.float32)
358
- tmp_y = np.empty(self.dim, dtype=np.int32)
359
- cos_a = cos_angle[i]
360
- sin_a = sin_angle[i]
361
- for c in range(self.n_channels):
362
- tmp_X[:,:,:,c] = rotate_img_patch(self.img[:,:,:,c],tmp_X[:,:,:,c],k,l,m,cos_a,sin_a,
363
- self.dim[0],self.dim[1],self.dim[2],
364
- self.dim_img[1],self.dim_img[2])
365
- tmp_y = rotate_label_patch(self.label,tmp_y,k,l,m,cos_a,sin_a,
285
+ tmp_X = self.img[k:k+self.dim[0],l:l+self.dim[1],m:m+self.dim[2]]
286
+ tmp_y = self.label[k:k+self.dim[0],l:l+self.dim[1],m:m+self.dim[2]]
287
+
288
+ # center label gets value 1
289
+ if self.separation:
290
+ centerLabel = tmp_y[self.dim[0]//2,self.dim[1]//2,self.dim[2]//2]
291
+ tmp_y = tmp_y.copy()
292
+ tmp_y[tmp_y!=centerLabel]=0
293
+ tmp_y[tmp_y==centerLabel]=1
294
+
295
+ # augmentation
296
+ if self.train:
297
+
298
+ # rotate in xy plane
299
+ if rotate:
300
+ tmp_X = np.empty((*self.dim, self.n_channels), dtype=np.float32)
301
+ tmp_y = np.empty((*self.dim, label_channels), dtype=np.int32)
302
+ cos_a = cos_angle[i]
303
+ sin_a = sin_angle[i]
304
+ for ch in range(self.n_channels):
305
+ tmp_X[...,ch] = rotate_img_patch(self.img[...,ch],tmp_X[...,ch],k,l,m,cos_a,sin_a,
306
+ self.dim[0],self.dim[1],self.dim[2],
307
+ self.dim_img[1],self.dim_img[2])
308
+ for ch in range(label_channels):
309
+ tmp_y[...,ch] = rotate_label_patch(self.label[...,ch],tmp_y[...,ch],k,l,m,cos_a,sin_a,
366
310
  self.dim[0],self.dim[1],self.dim[2],
367
311
  self.dim_img[1],self.dim_img[2])
368
-
369
- # rotate through a random 3d angle, uniformly distributed on a sphere.
370
- if rotate3d:
371
- tmp_X = np.empty((*self.dim, self.n_channels), dtype=np.float32)
372
- tmp_y = np.empty(self.dim, dtype=np.int32)
373
- rm_xx = rot_mtx[i, 0, 0]
374
- rm_xy = rot_mtx[i, 0, 1]
375
- rm_xz = rot_mtx[i, 0, 2]
376
- rm_yx = rot_mtx[i, 1, 0]
377
- rm_yy = rot_mtx[i, 1, 1]
378
- rm_yz = rot_mtx[i, 1, 2]
379
- rm_zx = rot_mtx[i, 2, 0]
380
- rm_zy = rot_mtx[i, 2, 1]
381
- rm_zz = rot_mtx[i, 2, 2]
382
- for c in range(self.n_channels):
383
- tmp_X[:,:,:,c] = rotate_img_patch_3d(self.img[:,:,:,c],tmp_X[:,:,:,c],k,l,m,
384
- rm_xx,rm_xy,rm_xz,rm_yx,rm_yy,rm_yz,rm_zx,rm_zy,rm_zz,
385
- self.dim[0],self.dim[1],self.dim[2],
386
- 256, self.dim_img[0],self.dim_img[1],self.dim_img[2])
387
- tmp_y = rotate_label_patch_3d(self.label,tmp_y,k,l,m,
312
+
313
+ # rotate through a random 3d angle, uniformly distributed on a sphere.
314
+ if rotate3d:
315
+ tmp_X = np.empty((*self.dim, self.n_channels), dtype=np.float32)
316
+ tmp_y = np.empty((*self.dim, label_channels), dtype=np.int32)
317
+ rm_xx = rot_mtx[i, 0, 0]
318
+ rm_xy = rot_mtx[i, 0, 1]
319
+ rm_xz = rot_mtx[i, 0, 2]
320
+ rm_yx = rot_mtx[i, 1, 0]
321
+ rm_yy = rot_mtx[i, 1, 1]
322
+ rm_yz = rot_mtx[i, 1, 2]
323
+ rm_zx = rot_mtx[i, 2, 0]
324
+ rm_zy = rot_mtx[i, 2, 1]
325
+ rm_zz = rot_mtx[i, 2, 2]
326
+ for ch in range(self.n_channels):
327
+ tmp_X[...,ch] = rotate_img_patch_3d(self.img[...,ch],tmp_X[...,ch],k,l,m,
328
+ rm_xx,rm_xy,rm_xz,rm_yx,rm_yy,rm_yz,rm_zx,rm_zy,rm_zz,
329
+ self.dim[0],self.dim[1],self.dim[2],
330
+ 256, self.dim_img[0],self.dim_img[1],self.dim_img[2])
331
+ for ch in range(label_channels):
332
+ tmp_y[...,ch] = rotate_label_patch_3d(self.label[...,ch],tmp_y[...,ch],k,l,m,
388
333
  rm_xx,rm_xy,rm_xz,rm_yx,rm_yy,rm_yz,rm_zx,rm_zy,rm_zz,
389
334
  self.dim[0],self.dim[1],self.dim[2],
390
335
  256, self.dim_img[0],self.dim_img[1],self.dim_img[2])
391
336
 
392
- # flip patch along axes
393
- v = np.random.randint(n_aug+1)
394
- if np.any([flip_x, flip_y, flip_z]) and v>0:
395
- flip = flips[v-1]
396
- tmp_X = np.flip(tmp_X, flip)
397
- tmp_y = np.flip(tmp_y, flip)
398
-
399
- # swap axes
400
- if swapaxes:
401
- v = np.random.randint(4)
402
- if v==1:
403
- tmp_X = np.swapaxes(tmp_X,0,1)
404
- tmp_y = np.swapaxes(tmp_y,0,1)
405
- elif v==2:
406
- tmp_X = np.swapaxes(tmp_X,0,2)
407
- tmp_y = np.swapaxes(tmp_y,0,2)
408
- elif v==3:
409
- tmp_X = np.swapaxes(tmp_X,1,2)
410
- tmp_y = np.swapaxes(tmp_y,1,2)
411
-
412
- # patch normalization
413
- if self.patch_normalization:
414
- tmp_X = tmp_X.copy().astype(np.float32)
415
- for c in range(self.n_channels):
416
- tmp_X[:,:,:,c] -= np.mean(tmp_X[:,:,:,c])
417
- tmp_X[:,:,:,c] /= max(np.std(tmp_X[:,:,:,c]), 1e-6)
418
-
419
- # assign to batch
420
- X[i] = tmp_X
421
- y[i,:,:,:,0] = tmp_y
422
-
423
- return X, tf.keras.utils.to_categorical(y, num_classes=self.n_classes)
337
+ # flip patch along axes
338
+ v = np.random.randint(n_aug+1)
339
+ if np.any([flip_x, flip_y, flip_z]) and v>0:
340
+ flip = flips[v-1]
341
+ tmp_X = np.flip(tmp_X, flip)
342
+ tmp_y = np.flip(tmp_y, flip)
343
+
344
+ # swap axes
345
+ if swapaxes:
346
+ v = np.random.randint(4)
347
+ if v==1:
348
+ tmp_X = np.swapaxes(tmp_X,0,1)
349
+ tmp_y = np.swapaxes(tmp_y,0,1)
350
+ elif v==2:
351
+ tmp_X = np.swapaxes(tmp_X,0,2)
352
+ tmp_y = np.swapaxes(tmp_y,0,2)
353
+ elif v==3:
354
+ tmp_X = np.swapaxes(tmp_X,1,2)
355
+ tmp_y = np.swapaxes(tmp_y,1,2)
356
+
357
+ # patch normalization
358
+ if self.patch_normalization:
359
+ tmp_X = tmp_X.copy().astype(np.float32)
360
+ for ch in range(self.n_channels):
361
+ mean, std = welford_mean_std(tmp_X[...,ch])
362
+ tmp_X[...,ch] -= mean
363
+ tmp_X[...,ch] /= max(std, 1e-6)
364
+
365
+ # assign to batch
366
+ X[i] = tmp_X
367
+ y[i] = tmp_y
368
+
369
+ if self.ignore_mask:
370
+ return X, y
371
+ else:
372
+ return X, tf.keras.utils.to_categorical(y, num_classes=self.n_classes)
424
373
 
@@ -1,6 +1,6 @@
1
1
  ##########################################################################
2
2
  ## ##
3
- ## Copyright (c) 2019-2024 Philipp Lösel. All rights reserved. ##
3
+ ## Copyright (c) 2019-2025 Philipp Lösel. All rights reserved. ##
4
4
  ## ##
5
5
  ## This file is part of the open source project biomedisa. ##
6
6
  ## ##
@@ -26,6 +26,7 @@
26
26
  ## ##
27
27
  ##########################################################################
28
28
 
29
+ from biomedisa.features.biomedisa_helper import welford_mean_std
29
30
  import numpy as np
30
31
  import tensorflow as tf
31
32
 
@@ -77,10 +78,11 @@ class PredictDataGenerator(tf.keras.utils.Sequence):
77
78
  # get patch
78
79
  tmp_X = self.img[k:k+self.dim[0],l:l+self.dim[1],m:m+self.dim[2]]
79
80
  if self.patch_normalization:
80
- tmp_X = np.copy(tmp_X, order='C')
81
- for c in range(self.n_channels):
82
- tmp_X[:,:,:,c] -= np.mean(tmp_X[:,:,:,c])
83
- tmp_X[:,:,:,c] /= max(np.std(tmp_X[:,:,:,c]), 1e-6)
81
+ tmp_X = tmp_X.copy().astype(np.float32)
82
+ for ch in range(self.n_channels):
83
+ mean, std = welford_mean_std(tmp_X[...,ch])
84
+ tmp_X[...,ch] -= mean
85
+ tmp_X[...,ch] /= max(std, 1e-6)
84
86
  X[i] = tmp_X
85
87
 
86
88
  return X
@@ -52,6 +52,19 @@ def silent_remove(filename):
52
52
  except OSError:
53
53
  pass
54
54
 
55
+ # calculate mean and standard deviation using Welford's algorithm
56
+ @numba.jit(nopython=True)
57
+ def welford_mean_std(arr):
58
+ mean, m2, count = 0.0, 0.0, 0
59
+ for x in arr.ravel():
60
+ count += 1
61
+ delta = x - mean
62
+ mean += delta / count
63
+ delta2 = x - mean
64
+ m2 += delta * delta2 # Running sum of squared differences
65
+ std_dev = np.sqrt(m2 / count) if count > 1 else 0.0 # Population std deviation
66
+ return mean, std_dev
67
+
55
68
  # determine all values and their count from an array
56
69
  def unique(arr, return_counts=False):
57
70
  try:
@@ -408,14 +421,21 @@ def load_data(path_to_data, process='None', return_extension=False):
408
421
  else:
409
422
  return data, header
410
423
 
411
- def _error_(bm, message):
424
+ def _error_(bm, message, level=1):
412
425
  if bm.django_env:
413
426
  from biomedisa.features.django_env import create_error_object
414
427
  create_error_object(message, bm.remote, bm.queue, bm.img_id)
415
428
  with open(bm.path_to_logfile, 'a') as logfile:
416
429
  print('%s %s %s %s' %(time.ctime(), bm.username, bm.shortfilename, message), file=logfile)
417
- print('Error:', message)
418
- bm.success = False
430
+ elif bm.slicer and bm.path_to_data:
431
+ error_path = os.path.dirname(bm.path_to_data) + '/biomedisa-error.txt'
432
+ with open(error_path, 'w') as file:
433
+ file.write(message)
434
+ if level==0:
435
+ print('Warning:', message)
436
+ elif level==1:
437
+ print('Error:', message)
438
+ bm.success = False
419
439
  return bm
420
440
 
421
441
  def pre_processing(bm):
@@ -613,7 +633,10 @@ def _get_platform(bm):
613
633
  if cl and bm.platform is None:
614
634
  for vendor in ['NVIDIA', 'Intel', 'AMD', 'Apple']:
615
635
  for dev, device_type in [('GPU',cl.device_type.GPU),('CPU',cl.device_type.CPU)]:
616
- all_platforms = cl.get_platforms()
636
+ try:
637
+ all_platforms = cl.get_platforms()
638
+ except:
639
+ all_platforms = []
617
640
  my_devices = []
618
641
  for p in all_platforms:
619
642
  if p.get_devices(device_type=device_type) and vendor in p.name:
@@ -634,7 +657,10 @@ def _get_platform(bm):
634
657
  elif cl and len(bm.platform.split('_')) == 3:
635
658
  plat, vendor, dev = bm.platform.split('_')
636
659
  device_type=cl.device_type.GPU if dev=='GPU' else cl.device_type.CPU
637
- all_platforms = cl.get_platforms()
660
+ try:
661
+ all_platforms = cl.get_platforms()
662
+ except:
663
+ all_platforms = []
638
664
  my_devices = []
639
665
  for p in all_platforms:
640
666
  if p.get_devices(device_type=device_type) and vendor in p.name:
@@ -1,6 +1,6 @@
1
1
  ##########################################################################
2
2
  ## ##
3
- ## Copyright (c) 2019-2024 Philipp Lösel. All rights reserved. ##
3
+ ## Copyright (c) 2019-2025 Philipp Lösel. All rights reserved. ##
4
4
  ## ##
5
5
  ## This file is part of the open source project biomedisa. ##
6
6
  ## ##
@@ -28,7 +28,8 @@
28
28
 
29
29
  import os
30
30
  from biomedisa.features.keras_helper import read_img_list
31
- from biomedisa.features.biomedisa_helper import img_resize, load_data, save_data, set_labels_to_zero
31
+ from biomedisa.features.biomedisa_helper import (img_resize,
32
+ load_data, save_data, set_labels_to_zero, welford_mean_std)
32
33
  from tensorflow.python.framework.errors_impl import ResourceExhaustedError
33
34
  from tensorflow.keras.applications import DenseNet121, densenet
34
35
  from tensorflow.keras.optimizers import Adam
@@ -161,7 +162,7 @@ def load_cropping_training_data(normalize, img_list, label_list, x_scale, y_scal
161
162
  # normalize first validation image
162
163
  if normalize and np.any(normalization_parameters):
163
164
  for c in range(channels):
164
- mean, std = np.mean(img[:,:,:,c]), np.std(img[:,:,:,c])
165
+ mean, std = welford_mean_std(img[:,:,:,c])
165
166
  img[:,:,:,c] = (img[:,:,:,c] - mean) / std
166
167
  img[:,:,:,c] = img[:,:,:,c] * normalization_parameters[1,c] + normalization_parameters[0,c]
167
168
 
@@ -170,8 +171,7 @@ def load_cropping_training_data(normalize, img_list, label_list, x_scale, y_scal
170
171
  normalization_parameters = np.zeros((2,channels))
171
172
  if normalize:
172
173
  for c in range(channels):
173
- normalization_parameters[0,c] = np.mean(img[:,:,:,c])
174
- normalization_parameters[1,c] = np.std(img[:,:,:,c])
174
+ normalization_parameters[:,c] = welford_mean_std(img[:,:,:,c])
175
175
 
176
176
  # loop over list of images
177
177
  if any(img_list) or type(img_in) is list:
@@ -223,7 +223,7 @@ def load_cropping_training_data(normalize, img_list, label_list, x_scale, y_scal
223
223
  next_img[:,:,:,c] -= np.amin(next_img[:,:,:,c])
224
224
  next_img[:,:,:,c] /= np.amax(next_img[:,:,:,c])
225
225
  if normalize:
226
- mean, std = np.mean(next_img[:,:,:,c]), np.std(next_img[:,:,:,c])
226
+ mean, std = welford_mean_std(next_img[:,:,:,c])
227
227
  next_img[:,:,:,c] = (next_img[:,:,:,c] - mean) / std
228
228
  next_img[:,:,:,c] = next_img[:,:,:,c] * normalization_parameters[1,c] + normalization_parameters[0,c]
229
229
  img = np.append(img, next_img, axis=0)
@@ -391,7 +391,7 @@ def load_data_to_crop(path_to_img, channels, x_scale, y_scale, z_scale,
391
391
  img[:,:,:,c] -= np.amin(img[:,:,:,c])
392
392
  img[:,:,:,c] /= np.amax(img[:,:,:,c])
393
393
  if normalize:
394
- mean, std = np.mean(img[:,:,:,c]), np.std(img[:,:,:,c])
394
+ mean, std = welford_mean_std(img[:,:,:,c])
395
395
  img[:,:,:,c] = (img[:,:,:,c] - mean) / std
396
396
  img[:,:,:,c] = img[:,:,:,c] * normalization_parameters[1,c] + normalization_parameters[0,c]
397
397
  img[img<0] = 0