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 +27 -8
- biomedisa/features/DataGenerator.py +93 -144
- biomedisa/features/PredictDataGenerator.py +7 -5
- biomedisa/features/biomedisa_helper.py +31 -5
- biomedisa/features/crop_helper.py +7 -7
- biomedisa/features/keras_helper.py +275 -150
- biomedisa/features/random_walk/rw_large.py +6 -2
- biomedisa/features/random_walk/rw_small.py +7 -3
- biomedisa/interpolation.py +3 -1
- {biomedisa-24.8.11.dist-info → biomedisa-25.6.1.dist-info}/METADATA +3 -2
- {biomedisa-24.8.11.dist-info → biomedisa-25.6.1.dist-info}/RECORD +14 -14
- {biomedisa-24.8.11.dist-info → biomedisa-25.6.1.dist-info}/WHEEL +1 -1
- {biomedisa-24.8.11.dist-info → biomedisa-25.6.1.dist-info/licenses}/LICENSE +0 -0
- {biomedisa-24.8.11.dist-info → biomedisa-25.6.1.dist-info}/top_level.txt +0 -0
biomedisa/deeplearning.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/python3
|
2
2
|
##########################################################################
|
3
3
|
## ##
|
4
|
-
## Copyright (c) 2019-
|
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
|
-
#
|
218
|
-
|
219
|
-
|
220
|
-
|
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-
|
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,
|
205
|
-
dim_img=(32,32,32), n_classes=10, n_channels=1, augment=(False,False,False,False,0,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
|
-
#
|
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
|
-
|
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
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
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
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
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
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
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-
|
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 =
|
81
|
-
for
|
82
|
-
|
83
|
-
tmp_X[
|
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
|
-
|
418
|
-
|
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
|
-
|
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
|
-
|
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-
|
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,
|
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 =
|
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[
|
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 =
|
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 =
|
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
|