1.5 MiB
1.5 MiB
In [1]:
from skimage import io
import numpy as np
import matplotlib.pyplot as plt
from skimage import filters
from skimage import feature
from skimage.morphology import disk,ball
from sklearn.ensemble import RandomForestClassifier
from scipy import ndimage
import os
import imageio
import sysIn [2]:
im = io.imread(r"U:\01_Python\00_playground\test_pytorch\Dataset\test_tomcat\test_im.tif")
plt.imshow(im)
# "U:\01_Python\00_playground\test_pytorch\Dataset\test_tomcat\water_truth.tif"Out [2]:
<matplotlib.image.AxesImage at 0x21a7fc3b1f0>
In [3]:
air = io.imread(r"U:\01_Python\00_playground\test_pytorch\Dataset\test_tomcat\air_truth.tif")>0
water = io.imread(r"U:\01_Python\00_playground\test_pytorch\Dataset\test_tomcat\water_truth.tif")>0
fiber = io.imread(r"U:\01_Python\00_playground\test_pytorch\Dataset\test_tomcat\fiber_truth.tif")>0
truth = io.imread(r"U:\01_Python\00_playground\test_pytorch\Dataset\test_tomcat\test_truth.tif")In [155]:
def TWS_gaussian(im, sig=0):
G = filters.gaussian(im, sigma=sig, mode='reflect') #, preserve_range=True
fullname = ''.join(['gaussian_',f'{sig:.1f}'])
return G, fullname
def TWS_gaussian_stack(im, sigmas):
fullnames = []
gstack = np.zeros((im.shape[0],im.shape[1], len(sigmas)))
for sig,i in zip(sigmas, range(len(sigmas))):
# if np.abs(sig-0)<0.1:
# gstack[:,:,i] = im
# name = ''.join(['gaussian_',f'{0:.1f}'])
# else:
gstack[:,:,i], name = TWS_gaussian(im, sig)
fullnames.append(name)
return gstack, fullnames
def TWS_sobel(im, sig):
#sigma is only passed to the name! make sure it's correct
S = filters.sobel(im, mode='reflect')
name = ''.join(['sobel_',f'{sig:.1f}'])
return S, name
def TWS_sobel_stack(gstack, sigmas):
Sstack = np.zeros(gstack.shape)
fullnames = []
for i in range(len(sigmas)):
Sstack[:,:,i], name = TWS_sobel(gstack[:,:,i], sigmas[i])
fullnames.append(name)
return Sstack, fullnames
def TWS_hessian(im, sig):
#creates 8 images per sigma
#sigma is only passed to the name! make sure it's correct
a, b, d = feature.hessian_matrix(im, mode='reflect')
c = b
mod = np.sqrt(a**2+b*c+d**2)
trace = a+d
det = a*d-c*b
eig1 = (a+d)/2 + np.sqrt((4*b**2+(a-d)**2)/2)
eig2 = (a+d)/2 - np.sqrt((4*b**2+(a-d)**2)/2)
gamma_norm_eig_diff = (a-d)**2*((a-d)**2+4*b**2)
square_norm_eig_diff = ((a-d)**2+4*b**2)
orient = 0.5*np.arccos(4*b**2+(a-d)**2)
hessian_stack = np.dstack([mod,trace,det,eig1,eig2,orient,gamma_norm_eig_diff,square_norm_eig_diff])
names = ['module', 'trace', 'determinant', 'eigenvalue1', 'eigenvalue2', 'orientation', 'gamma_norm_eig_diff', 'square_norm_eig_diff']
fullnames = []
for name in names:
fullname = ''.join(['hessian_',name,'_',f'{sig:.1f}'])
fullnames.append(fullname)
return hessian_stack, fullnames
def TWS_hessian_stack(gstack, sigmas):
size = len(sigmas)*8
Hstack = np.zeros((gstack.shape[0],gstack.shape[1], size))
fullnames = []
for i in range(len(sigmas)):
Hstack[:,:,i*8:i*8+8], names = TWS_hessian(gstack[:,:,i],sigmas[i])
fullnames = fullnames + names
return Hstack, fullnames
def TWS_diff_of_gaussians(gstack, sigmas):
#creates a stack of {size} (see below)
n = len(sigmas)
size = int(n*(n-1)/2)
diff_stack = np.zeros((im.shape[0], im.shape[1], size))
fullnames = []
cc = 0
for i in range(1,n):
for j in range(i):
DG = gstack[:,:,i]-gstack[:,:,j]
diff_stack[:,:,cc] = DG
name = ''.join(['diff_of_gauss_',f'{sigmas[i]:.1f}','_',f'{sigmas[j]:.1f}'])
fullnames.append(name)
cc = cc + 1
return diff_stack, fullnames
def TWS_minimum(im, sigma):
M = filters.rank.minimum(im, disk(sigma))
fullname = ''.join(['minimum_',f'{sigma:.1f}'])
return M, fullname
def TWS_minimum_stack(im, sigmas):
size = len(sigmas)-1
min_stack = np.zeros((im.shape[0], im.shape[1], size))
fullnames = []
i = 0
for i in range(size):
sig = sigmas[i+1]
min_stack[:,:,i], fullname = TWS_minimum(im, sig)
fullnames.append(fullname)
return min_stack, fullnames
def TWS_maximum(im, sigma):
M = filters.rank.maximum(im, disk(sigma))
fullname = ''.join(['maximum_',f'{sigma:.1f}'])
return M, fullname
def TWS_maximum_stack(im, sigmas):
size = len(sigmas)-1
max_stack = np.zeros((im.shape[0], im.shape[1], size))
fullnames = []
i = 0
for i in range(size):
sig = sigmas[i+1]
max_stack[:,:,i], fullname = TWS_maximum(im, sig)
fullnames.append(fullname)
return max_stack, fullnames
def TWS_median(im, sigma):
M = filters.rank.median(im, disk(sigma))
fullname = ''.join(['median_',f'{sigma:.1f}'])
return M, fullname
def TWS_median_stack(im, sigmas):
size = len(sigmas)-1
med_stack = np.zeros((im.shape[0], im.shape[1], size))
fullnames = []
i = 0
for i in range(size):
sig = sigmas[i+1]
med_stack[:,:,i], fullname = TWS_median(im, sig)
fullnames.append(fullname)
return med_stack, fullnames
In [3]:
def TWS_feature_stack(im, sigmas, feat_select):
feat_names = []
stack_list = []
#TODO: allow ticking off features
#gaussian filters
if feat_select['Gaussian']:
g_stack, gfeat = TWS_gaussian_stack(im, sigmas)
stack_list.append(g_stack)
feat_names = feat_names + gfeat
#sobel filter on every gaussian sigma
if feat_select['Sobel']:
s_stack, sfeat = TWS_sobel_stack(g_stack, sigmas)
stack_list.append(s_stack)
feat_names = feat_names + sfeat
#stack of hessian stacks for every sigma
if feat_select['Hessian']:
h_stack, hfeat = TWS_hessian_stack(g_stack, sigmas)
stack_list.append(h_stack)
feat_names = feat_names + hfeat
#diff of gaussians
if feat_select['Diff of Gaussians']:
d_stack, dfeat = TWS_diff_of_gaussians(g_stack, sigmas)
stack_list.append(d_stack)
feat_names = feat_names + dfeat
#minimum filters
if feat_select['minimum']:
min_stack, minfeat = TWS_minimum_stack(im, sigmas)
stack_list.append(min_stack)
feat_names = feat_names + minfeat
#maximum filters
if feat_select['maximum']:
max_stack, maxfeat = TWS_maximum_stack(im, sigmas)
stack_list.append(max_stack)
feat_names = feat_names + maxfeat
#median filters
if feat_select['median']:
med_stack, medfeat = TWS_median_stack(im, sigmas)
stack_list.append(med_stack)
feat_names = feat_names + medfeat
feat_stack = np.dstack(stack_list)
return feat_stack, feat_names
In [4]:
def label_data_slice(im, truth, sigmas, feat_select, feat_stack=None):
#TODO: automatically detect phases in truth image and aovid overlap
#TODO: define format of truth image
phase1 = truth==1
phase2 = truth==2
phase3 = truth==4
if feat_stack is None:
feat_stack, feat_names = TWS_feature_stack(im, sigmas, feat_select)
X1 = feat_stack[phase1]
y1 = np.zeros(X1.shape[0])
X2 = feat_stack[phase2]
y2 = np.ones(X2.shape[0])
X3 = feat_stack[phase3]
y3 = 2*np.ones(X3.shape[0])
y = np.concatenate([y1,y2,y3])
X = np.concatenate([X1,X2,X3])
return X,y, feat_stack
In [5]:
def classify_and_plot(X,y,im, feat_stack, plot=True):
# TODO: allow choice and manipulation of ML method
clf = RandomForestClassifier(n_estimators = 300, n_jobs=-1, random_state = 42, max_features=None)
clf.fit(X, y)
num_feat = feat_stack.shape[2]
ypred = clf.predict(feat_stack.reshape(-1,num_feat))
result = ypred.reshape(im.shape).astype(np.uint8)
if plot:
fig, (ax1, ax2)= plt.subplots(1,2,figsize=(12,7))
ax1.imshow(im, cmap='Greys_r')
ax2.imshow(result)
return result, clfIn [6]:
def slicewise_classify_for_training(im, slice_name,sigmas, feat_select, plot=True, feat_stack=None, truth=None, training_dict=None): #, training_path, XTM_data_path
#consider training data from other slices but do not simpliy append to avoid duplicates
flag = False #TODO: get rid of flag
if training_dict is not None:
slices = list(training_dict.keys())
if slice_name in slices:
slices.remove(slice_name)
if len(slices)>0:
flag = True
Xall = training_dict[slices[0]][0]
yall = training_dict[slices[0]][1]
for i in range(1,len(slices)):
Xall = np.concatenate([Xall, training_dict[slices[i]][0]])
yall = np.concatenate([yall, training_dict[slices[i]][1]])
if feat_stack is None:
print('creating feature stack')
X,y, feat_stack = label_data_slice(im, truth, sigmas, feat_select)
else:
X,y, feat_stack = label_data_slice(im, truth, sigmas, feat_select, feat_stack=feat_stack)
print('training and classifying')
if training_dict is not None and flag:
Xt = np.concatenate([Xall,X])
yt = np.concatenate([yall,y])
Xall = None
yall = None
else:
Xt = X
yt = y
result, clf = classify_and_plot(Xt,yt,im, feat_stack, plot)
# print('save slice result, retrain if needed')
# imageio.imsave(os.path.join(training_path,''.join([slice_name,'_classified.tif'])), result)
return X, y, feat_stack, clf, resultIn [9]:
sigmas = [0, 2,4,6,8] #hard-coded for now, sobel and hessian require that first sigma is 0, diff, gaussian(sig=0) = 0
# default feature choice
feat_select = {'Gaussian': True,
'Sobel': True,
'Hessian': True,
'Diff of Gaussians': True
}
In [10]:
slice_name = 'test'
training_path = r"U:\01_Python\00_playground\test_pytorch\Dataset\test_tomcat"In [10]:
im = io.imread(r"U:\01_Python\00_playground\test_pytorch\Dataset\test_tomcat\test_im.tif")
air = io.imread(r"U:\01_Python\00_playground\test_pytorch\Dataset\test_tomcat\air_truth.tif")>0
water = io.imread(r"U:\01_Python\00_playground\test_pytorch\Dataset\test_tomcat\water_truth.tif")>0
fiber = io.imread(r"U:\01_Python\00_playground\test_pytorch\Dataset\test_tomcat\fiber_truth.tif")>0
truth = air+water*2+fiber*4In [12]:
X,y, feat_stack, clf = slicewise_classify_for_training(im, slice_name, truth=truth,training_path = r"U:\01_Python\00_playground\test_pytorch\Dataset\test_tomcat", XTM_data_path = r"U:\01_Python\00_playground\test_pytorch\Dataset\test_tomcat")creating feature stack training and classifying save slice result
In [13]:
training_dict = {}
training_dict[slice_name] = (X,y, feat_stack)In [14]:
XTM_data_path = r"D:\TOMCAT_2\01_intcorrect_med_leg_0"
training_path = r"U:\01_Python\00_playground\test_pytorch\Dataset\test_tomcat\training"
time_folder = os.listdir(XTM_data_path)
timestep_folder = time_folder[0]
images_first = os.listdir(os.path.join(XTM_data_path, timestep_folder))In [37]:
# randomly suggest slice for training
num_ts = len(time_folder)
num_slices = len(images_first)
ts = np.random.choice(range(num_ts))+1
print('try time step ',ts )
sn = np.random.choice(range(num_slices))+1
print('try slice number ', sn)
slice_name= ''.join(['ts_',str(ts),'_slice_',str(sn)])
watername = ''.join([slice_name, '_water.tif'])
waterpath = os.path.join(training_path, watername)
if not os.path.exists(waterpath):
print('create missing training set with ImageJ-script!')try time step 9 try slice number 326 create missing training set with ImageJ-script!
In [27]:
time_step = 15
slice_number = 519
time_folder = os.listdir(XTM_data_path)
timestep_folder = time_folder[time_step]
images = os.listdir(os.path.join(XTM_data_path, timestep_folder))
image_name = images[slice_number]
im = io.imread(os.path.join(XTM_data_path, timestep_folder, image_name))
slice_name= ''.join(['ts_',str(time_step),'_slice_',str(slice_number)])
watername = ''.join([slice_name, '_water.tif'])
waterpath = os.path.join(training_path, watername)
airname = ''.join([slice_name, '_air.tif'])
airpath = os.path.join(training_path, airname)
fibername = ''.join([slice_name, '_fiber.tif'])
fiberpath = os.path.join(training_path, fibername)
air = io.imread(airpath)>0
water = io.imread(waterpath)>0
fiber = io.imread(fiberpath)>0
truth = air+water*2+fiber*4
if slice_name in training_dict.keys():
X,y, feat_stack, clf = slicewise_classify_for_training(im, slice_name, XTM_data_path=XTM_data_path, training_path=training_path, feat_stack=training_dict[slice_name][2], truth=truth, training_dict=training_dict)
else:
X,y, feat_stack, clf = slicewise_classify_for_training(im, slice_name, XTM_data_path=XTM_data_path, training_path=training_path, truth=truth, training_dict=training_dict)
training_dict[slice_name] = (X,y, feat_stack)
print('training dict contains ',len(training_dict.keys()),'entries, keep track of memory')
training and classifying save slice result
In [31]:
### make test feature_stack and names
_, feat_names = TWS_feature_stack(im, sigmas)In [32]:
plt.figure( figsize=(16,9))
plt.plot(feat_names,clf.feature_importances_,'x')
plt.xticks(rotation=90)Out [32]:
([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], [Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, '')])
In [7]:
XTM_data_path = r"C:\Zwischenlager\wood_time_slices\00_raw"
training_path = r"C:\Zwischenlager\wood_time_slices\training_data"
time_folder = os.listdir(XTM_data_path)
timestep_folder = time_folder[0]
images_first = os.listdir(os.path.join(XTM_data_path, timestep_folder))In [55]:
sigmas = [0, 2,4] #hard-coded for now, sobel and hessian require that first sigma is 0, diff, gaussian(sig=0) = 0
# default feature choice
feat_select = {'Gaussian': True,
'Sobel': True,
'Hessian': True,
'Diff of Gaussians': True,
'maximum': True,
'minimum': True,
'median': True
}
In [27]:
feat_selectOut [27]:
{'Gaussian': True,
'Sobel': True,
'Hessian': True,
'Diff of Gaussians': True,
'maximum': True,
'minimum': True,
'median': True}In [56]:
training_dict = {}In [11]:
# randomly suggest slice for training
num_ts = len(time_folder)
num_slices = len(images_first)
ts = np.random.choice(range(num_ts))+1
print('try time step ',ts )
sn = np.random.choice(range(num_slices))+1
print('try slice number ', sn)
slice_name= ''.join(['ts_',str(ts),'_slice_',str(sn)])
watername = ''.join([slice_name, '_water.tif'])
waterpath = os.path.join(training_path, watername)
if not os.path.exists(waterpath):
print('create missing training set with ImageJ-script!')try time step 6 try slice number 87 create missing training set with ImageJ-script!
In [57]:
time_step = 5
slice_number = 54
time_folder = os.listdir(XTM_data_path)
timestep_folder = time_folder[time_step]
images = os.listdir(os.path.join(XTM_data_path, timestep_folder))
image_name = images[slice_number]
im = io.imread(os.path.join(XTM_data_path, timestep_folder, image_name))
slice_name= ''.join(['ts_',str(time_step),'_slice_',str(slice_number)])
watername = ''.join([slice_name, '_water.tif'])
waterpath = os.path.join(training_path, watername)
airname = ''.join([slice_name, '_air.tif'])
airpath = os.path.join(training_path, airname)
fibername = ''.join([slice_name, '_fiber.tif'])
fiberpath = os.path.join(training_path, fibername)
air = io.imread(airpath)>0
water = io.imread(waterpath)>0
fiber = io.imread(fiberpath)>0
truth = air+water*2+fiber*4
if slice_name in training_dict.keys():
X,y, feat_stack, clf = slicewise_classify_for_training(im, slice_name,sigmas,XTM_data_path, training_path, feat_select, feat_stack=training_dict[slice_name][2], truth=truth, training_dict=training_dict)
else:
X,y, feat_stack, clf = slicewise_classify_for_training(im, slice_name,sigmas, XTM_data_path, training_path, feat_select, truth=truth, training_dict=training_dict)
training_dict[slice_name] = (X,y, feat_stack)
print('training dict contains ',len(training_dict.keys()),'entries, keep track of memory')
creating feature stack
C:\Users\fische_r\Miniconda3\envs\pyweka\lib\site-packages\skimage\filters\rank\generic.py:262: UserWarning: Bad rank filter performance is expected due to a large number of bins (38360), equivalent to an approximate bitdepth of 15.2. image, footprint, out, mask, n_bins = _preprocess_input(image, footprint,
training and classifying save slice result, retrain if needed training dict contains 1 entries, keep track of memory
In [58]:
### make test feature_stack and names
_, feat_names = TWS_feature_stack(im, sigmas, feat_select)C:\Users\fische_r\Miniconda3\envs\pyweka\lib\site-packages\skimage\filters\rank\generic.py:262: UserWarning: Bad rank filter performance is expected due to a large number of bins (38360), equivalent to an approximate bitdepth of 15.2. image, footprint, out, mask, n_bins = _preprocess_input(image, footprint,
In [29]:
len(feat_names)Out [29]:
55
In [59]:
plt.figure( figsize=(16,9))
plt.stem(feat_names,clf.feature_importances_,'x')
plt.xticks(rotation=90)
plt.ylabel('importance')Out [59]:
C:\Users\fische_r\AppData\Local\Temp\ipykernel_12928\1483009324.py:2: MatplotlibDeprecationWarning: Passing the linefmt parameter positionally is deprecated since Matplotlib 3.5; the parameter will become keyword-only two minor releases later. plt.stem(feat_names,clf.feature_importances_,'x')
Text(0, 0.5, 'importance')
In [40]:
import robpylibIn [68]:
feat_files = []
for feat in feat_names:
feat_files.append(feat+'.tif')In [69]:
robpylib.CommonFunctions.ImportExport.WriteStackNew(r"C:\Zwischenlager\wood_time_slices\pywekastack", feat_files, feat_stack)In [44]:
feat_names[0]Out [44]:
'gaussian_0.0'
In [7]:
from ipywidgets import Image
from ipywidgets import ColorPicker, IntSlider, link, AppLayout, HBox
from ipycanvas import RoughCanvas, hold_canvas, Canvas, MultiCanvasIn [8]:
import os
from skimage import io
import matplotlib.pyplot as plt
import numpy as np
im8 = io.imread(r"C:\Zwischenlager\wood_time_slices\8bit_test.tif")
im = io.imread(r"C:\Zwischenlager\wood_time_slices\16bit_test.tif")
truthpath = r"C:\Zwischenlager\wood_time_slices\tst_truth.tif"
plt.imshow(im8)Out [8]:
<matplotlib.image.AxesImage at 0x13550e06620>
In [9]:
resultim = np.zeros(im.shape, dtype=np.uint8)
if os.path.exists(truthpath):
truth = io.imread(truthpath)
print('existing label set loaded')
else:
truth = resultim.copy()
slice_name = 'test'In [10]:
sigmas = [0, 2,4, 8] #hard-coded for now, sobel and hessian require that first sigma is 0, diff, gaussian(sig=0) = 0
# default feature choice
feat_select = {'Gaussian': True,
'Sobel': True,
'Hessian': True,
'Diff of Gaussians': True,
'maximum': True,
'minimum': True,
'median': True
}
training_dict = {}In [14]:
width = im8.shape[1]
height = im8.shape[0]
Mcanvas = MultiCanvas(4, width=width, height=height)
background = Mcanvas[0]
resultdisplay = Mcanvas[2]
truthdisplay = Mcanvas[1]
canvas = Mcanvas[3]
canvas.sync_image_data = True
drawing = False
position = None
shape = []
def on_mouse_down(x, y):
global drawing
global position
global shape
drawing = True
position = (x, y)
shape = [position]
def on_mouse_move(x, y):
global drawing
global position
global shape
if not drawing:
return
with hold_canvas():
canvas.stroke_line(position[0], position[1], x, y)
position = (x, y)
shape.append(position)
def on_mouse_up(x, y):
global drawing
global position
global shape
drawing = False
with hold_canvas():
canvas.stroke_line(position[0], position[1], x, y)
canvas.fill_polygon(shape)
shape = []
image_data = np.stack((im8, im8, im8), axis=2)
background.put_image_data(image_data, 0, 0)
# alpha = 0.15
resultdisplay.global_alpha = 0.15
# result_data = np.stack((255*(resultim==0), 255*(resultim==1), 255*(resultim==2)), axis=2)
if np.any(resultim>0):
result_data = np.stack((255*(resultim==0), 255*(resultim==1), 255*(resultim==2)), axis=2)
else:
result_data = np.stack((0*resultim, 0*resultim, 0*resultim), axis=2)
resultdisplay.put_image_data(result_data, 0, 0)
# truth_data = np.stack((255*(truth==1), 2555*(truth==2), 2555*(truth==4)), axis=2)
# truthdisplay.put_image_data(truth_data, 0, 0)
# truthdisplay.global_alpha = 0.05
canvas.on_mouse_down(on_mouse_down)
canvas.on_mouse_move(on_mouse_move)
canvas.on_mouse_up(on_mouse_up)
# canvas.stroke_style = "#749cb8"
# canvas.global_alpha = 0.75
picker = ColorPicker(description="Color:", value="#ff0000")
slidealpha = IntSlider(description="Result overlay", value=0.15)
link((picker, "value"), (canvas, "stroke_style"))
link((picker, "value"), (canvas, "fill_style"))
# link((slidealpha, "value"), (resultdisplay, "global_alpha"))
HBox((Mcanvas, picker, slidealpha))
#print('paint image with #ff0000 for air, #00ff00 for water and #0000ff for fiber')HBox(children=(MultiCanvas(height=690, width=744), ColorPicker(value='#ff0000', description='Color:'), IntSlid…
In [12]:
#create truth image from image, save to file
label_set = canvas.get_image_data()
truth[label_set[:,:,0]>0] = 1
truth[label_set[:,:,1]>0] = 2
truth[label_set[:,:,2]>0] = 4
imageio.imsave(truthpath, truth)In [13]:
if slice_name in training_dict.keys():
X,y, feat_stack, clf, resultim = slicewise_classify_for_training(im, slice_name,sigmas, feat_select, feat_stack=training_dict[slice_name][2], truth=truth, training_dict=training_dict)
else:
X,y, feat_stack, clf, resultim = slicewise_classify_for_training(im, slice_name,sigmas, feat_select, truth=truth, training_dict=training_dict) #XTM_data_path, training_path,
training_dict[slice_name] = (X,y, feat_stack)
print('training dict contains ',len(training_dict.keys()),'entries, keep track of memory')creating feature stack
C:\Users\fische_r\Miniconda3\envs\pyweka\lib\site-packages\skimage\filters\rank\generic.py:262: UserWarning: Bad rank filter performance is expected due to a large number of bins (40107), equivalent to an approximate bitdepth of 15.3. image, footprint, out, mask, n_bins = _preprocess_input(image, footprint,
training and classifying training dict contains 1 entries, keep track of memory
In [61]:
### make test feature_stack and names
_, feat_names = TWS_feature_stack(im, sigmas, feat_select)C:\Users\fische_r\Miniconda3\envs\pyweka\lib\site-packages\skimage\filters\rank\generic.py:262: UserWarning: Bad rank filter performance is expected due to a large number of bins (40107), equivalent to an approximate bitdepth of 15.3. image, footprint, out, mask, n_bins = _preprocess_input(image, footprint,
In [84]:
plt.figure( figsize=(16,9))
plt.stem(feat_names,clf.feature_importances_,'x')
plt.xticks(rotation=90)
plt.ylabel('importance')Out [84]:
C:\Users\fische_r\AppData\Local\Temp\ipykernel_13852\1483009324.py:2: MatplotlibDeprecationWarning: Passing the linefmt parameter positionally is deprecated since Matplotlib 3.5; the parameter will become keyword-only two minor releases later. plt.stem(feat_names,clf.feature_importances_,'x')
Text(0, 0.5, 'importance')
In [3]:
from skimage import io
import numpy as np
import matplotlib.pyplot as plt
from skimage import filters
from skimage import feature
from skimage.morphology import disk,ball
# from sklearn.ensemble import RandomForestClassifier
from scipy import ndimage
import os
import imageio
import sysIn [4]:
import dask
import dask.array
# import cupy as cp
# import cucim
import numpy as np
import matplotlib.pyplot as plt
from itertools import combinations_with_replacement
import xarray as xrIn [5]:
array_4D = None
gauss_4D = None
AS = 200
# array_4D = cp.random.random((AS,AS,AS,AS))
array_4Dnp = np.random.random((AS,AS,AS,AS))Cell:
[Cell type raw - unsupported, skipped]
Cell:
[Cell type raw - unsupported, skipped]
In [7]:
# shows order of hessian elements
axes = range(array_4Dnp.ndim)
for ax0, ax1 in combinations_with_replacement(axes, 2):
print(ax0, ax1)0 0 0 1 0 2 0 3 1 1 1 2 1 3 2 2 2 3 3 3
In [8]:
# functions take chunked dask-array as input
def nd_gaussian(da, sig = 0):
if np.abs(sig-0)<0.1:
G = np.array(da)
else:
G = da.map_overlap(filters.gaussian, depth=4*sig+1, sigma = sig).compute()
fullname = ''.join(['gaussian_',f'{sig:.1f}'])
return G, fullname
#TODO create a class that makes the feature stacks
def nd_gaussian_stack(da, sigmas):
fullnames = []
gstack = np.zeros(list(da.shape) + [len(sigmas)])
for sig,i in zip(sigmas, range(len(sigmas))):
gstack[...,i], name = nd_gaussian(da, sig)
fullnames.append(name)
return gstack, fullnamesIn [9]:
def nd_diff_of_gaussian(gstack, sigmas):
# #creates a stack of {size} (see below)
n = len(sigmas)
size = int(n*(n-1)/2)
dstack = np.zeros(list(da.shape) + [size])
fullnames = []
cc = 0
for i in range(1,n):
for j in range(i):
dstack[...,cc] = gstack[...,i] - gstack[...,j]
name = ''.join(['diff_of_gauss_',f'{sigmas[i]:.1f}','_',f'{sigmas[j]:.1f}'])
fullnames.append(name)
cc = cc + 1
return dstack, fullnamesIn [10]:
def ball_4d(sig):
bnd = np.zeros((sig*2+1,sig*2+1,sig*2+1,sig*2+1), dtype = bool)
bnd[sig,sig,sig,sig] = True
ecd = ndimage.distance_transform_edt(~bnd)
bnd = (ecd<sig+0.01).astype(int)
return bndIn [11]:
def nd_rank_like_filter(da, sigma, option):
"""
input
da - chunked das array up to 4D
sigma - kernel size, scalar
option, str ('minimum', 'maximum', 'median')
"""
if da.ndim == 2:
fp = disk(sigma)
if da.ndim == 3:
fp = ball(sigma)
if da.ndim == 4:
fp = ball_4d(sigma)
if option == 'minimum':
fun = ndimage.minimum_filter
elif option == 'maximum':
fun = ndimage.maximum_filter
elif option == 'median':
fun = ndimage.median_filter
else:
print(option+' not available')
M = da.map_overlap(fun, depth=sigma+1, footprint=fp).compute()
fullname = ''.join([option,'_',f'{sigma:.1f}'])
return M, fullname
def nd_rank_like_stack(da, sigmas, option):
fullnames = []
mstack = np.zeros(list(da.shape) + [len(sigmas)-1])
for sig,i in zip(sigmas[1:], range(len(sigmas)-1)):
mstack[...,i], name = nd_rank_like_filter(da, sig, option)
fullnames.append(name)
return mstack, fullnames
In [12]:
def nd_Hessian_matrix(G):
"""
copied from skimage.feature.hessian_matrix
just directly using Gaussian fitered arrays and dask
"""
daG = dask.array.from_array(G)
gradients = dask.array.gradient(daG)
axes = range(G.ndim)
H_elems = [dask.array.gradient(gradients[ax0], axis=ax1).compute() for ax0, ax1 in combinations_with_replacement(axes, 2)]
elems = [(ax0,ax1) for ax0, ax1 in combinations_with_replacement(axes, 2)]
return H_elems, elems
def nd_Hessian_stack(G, sigma):
H_elems, elems = nd_Hessian_matrix(G)
hstack = np.zeros(list(G.shape)+[len(elems)])
#TODO: this is slow, find some better numpy function
for i in range(len(elems)):
hstack[...,i] = H_elems[i]
# print('got Hessian matrices, now doing the eigs')
# eigs = feature.hessian_matrix_eigvals(H_elems)
# for now ignore the eigenvalues (too computationally expensive and H_elems already contains the image curvature
fullnames = []
for i,j in elems:
fullname = ''.join(['hessian_',str(i),str(j),'_',f'{sigma:.1f}'])
fullnames.append(fullname)
return hstack, fullnames
def nd_Hessian_stacks(gstack, sigmas):
flag = True
fullnames = []
for (i, sigma) in zip(range(gstack.shape[-1]), sigmas):
a, b = nd_Hessian_stack(gstack[...,i], sigma)
asize = a.shape[-1]
if flag:
flag = False
hstacks = np.zeros(list(gstack[...,-1].shape)+[len(sigmas)*asize])
hstacks[...,i*asize:i*asize+asize] = a
fullnames = fullnames + b
return hstacks, fullnamesIn [13]:
def nd_feature_Stack(da, sigmas, feat_select):
# TODO: make more elegant
fstack = []
featnames = []
print('apply Gaussian filters anyway')
gstack, gnames = nd_gaussian_stack(da, sigmas)
if feat_select['Gaussian']:
featnames = featnames + gnames
fstack.append(gstack)
if feat_select['Hessian']:
print('get Hessian matrices')
hstack, hnames = nd_Hessian_stacks(gstack, sigmas)
featnames = featnames + hnames
fstack.append(hstack)
if feat_select['Diff of Gaussians']:
print('get differences of Gaussians')
dstack, dnames = nd_diff_of_gaussian(gstack, sigmas)
featnames = featnames + dnames
fstack.append(dstack)
if feat_select['maximum']:
print('apply maximum filters')
maxstack, maxnames = nd_rank_like_stack(da, sigmas, option='maximum')
featnames = featnames + maxnames
fstack.append(maxstack)
if feat_select['median']:
print('apply median filters')
medstack, mednames = nd_rank_like_stack(da, sigmas, option='median')
featnames = featnames + mednames
fstack.append(medstack)
if feat_select['minimum']:
print('apply minimum filters')
minstack, minnames = nd_rank_like_stack(da, sigmas, option='minimum')
featnames = featnames + minnames
fstack.append(minstack)
return np.concatenate(fstack, axis=-1), featnamesIn [26]:
def feat_stack_to_nc(fstack, featnames, path = None):
#TODO: include metadata and
data = xr.Dataset({'feature_stack': (['x','y','z','time', 'feature'], fstack)},
coords = {'x': np.arange(fstack.shape[0]),
'y': np.arange(fstack.shape[1]),
'z': np.arange(fstack.shape[2]),
'time': np.arange(fstack.shape[3]),
'feature': featnames},
attrs = {'name': 'test'})
if path is not None:
data.to_netcdf(path)
return data
In [15]:
sigmas = [0, 2,4, 8] #hard-coded for now, sobel and hessian require that first sigma is 0, diff, gaussian(sig=0) = 0
# default feature choice
feat_select = {'Gaussian': True,
# 'Sobel': True,
'Hessian': True,
'Diff of Gaussians': True,
'maximum': True,
'minimum': True,
'median': True
}
training_dict = {}In [22]:
AS = 75
# array_4D = cp.random.random((AS,AS,AS,AS))
array_4Dnp = np.random.random((AS,AS,AS,AS))
In [23]:
da = dask.array.from_array(array_4Dnp, chunks = '100 MiB')In [24]:
daOut [24]:
|
In [25]:
fstack, featnames = nd_feature_Stack(da, sigmas, feat_select)apply Gaussian filters anyway get Hessian matrices get differences of Gaussians apply maximum filters apply median filters
IOStream.flush timed out IOStream.flush timed out
apply minimum filters
In [1]:
path = '/home/fische_r/NAS/testing/test_data.nc'In [30]:
1000/128Out [30]:
7.8125