Commit a69fee9dc89a6dab5b4bf4a28b23d945e8182504
1 parent
08ada8c2
added python script for 3D phantom creation for 2D images
Showing
2 changed files
with
78 additions
and
5 deletions
Show diff stats
1 | +# -*- coding: utf-8 -*- | ||
2 | +""" | ||
3 | +Created on Thu May 18 15:56:20 2017 | ||
4 | + | ||
5 | +@author: david | ||
6 | +""" | ||
7 | + | ||
8 | +import numpy as np | ||
9 | +import scipy as sp | ||
10 | +import scipy.misc | ||
11 | +import scipy.ndimage | ||
12 | +import matplotlib.pyplot as plt | ||
13 | +import os | ||
14 | + | ||
15 | +#calculate a 3D image from a 2D binary mask | ||
16 | +def binary(infile, sigma=2): | ||
17 | + | ||
18 | + I = sp.misc.imread(infile).astype(np.bool) | ||
19 | + | ||
20 | + #if the image has more than one channel, just keep the first one | ||
21 | + if(I.ndim == 3): | ||
22 | + I = I[:, :, 0] | ||
23 | + | ||
24 | + L = [] | ||
25 | + while np.count_nonzero(I) != 0: | ||
26 | + L.append(I) | ||
27 | + I = sp.ndimage.binary_erosion(I) | ||
28 | + | ||
29 | + #create a 3D image representing the new stack | ||
30 | + S = np.zeros( (I.shape[0], I.shape[1], len(L) * 2 - 1) ) | ||
31 | + | ||
32 | + #for each image in the list | ||
33 | + for i in range(0, len(L)): | ||
34 | + if(i == 0): | ||
35 | + S[:, :, len(L) - 1] = L[0] | ||
36 | + else: | ||
37 | + S[:, :, len(L) - 1 + i] = L[i] | ||
38 | + S[:, :, len(L) - 1 - i] = L[i] | ||
39 | + | ||
40 | + S = sp.ndimage.filters.gaussian_filter(S, sigma) | ||
41 | + return S | ||
42 | + | ||
43 | +#generate a 3D image stack from a 2D binary mask | ||
44 | +def binary_stack(infile, outdir, sigma=2): | ||
45 | + outfile_base = os.path.basename(infile) | ||
46 | + outfile_prefix, outfile_ext = os.path.splitext(outfile_base) | ||
47 | + | ||
48 | + S = binary(infile, sigma) | ||
49 | + | ||
50 | + zcount = len(str(S.shape[2])) | ||
51 | + for f in range(0, S.shape[2]): | ||
52 | + fname = outdir + "/" + outfile_prefix + str(f).zfill(zcount) + outfile_ext | ||
53 | + | ||
54 | + sp.misc.imsave(fname, S[:, :, f]) | ||
55 | + | ||
56 | + | ||
57 | + | ||
58 | + |
python/structen.py
@@ -17,9 +17,7 @@ def st2(I, s=1, dtype=np.float32): | @@ -17,9 +17,7 @@ def st2(I, s=1, dtype=np.float32): | ||
17 | 17 | ||
18 | #calculate the gradient | 18 | #calculate the gradient |
19 | dI = np.gradient(I.astype(dtype)) | 19 | dI = np.gradient(I.astype(dtype)) |
20 | - | ||
21 | - #print(dI[1][20, 164]) | ||
22 | - | 20 | + |
23 | #calculate the dimensions of the tensor field | 21 | #calculate the dimensions of the tensor field |
24 | field_dims = [dI[0].shape[0], dI[0].shape[1], 3] | 22 | field_dims = [dI[0].shape[0], dI[0].shape[1], 3] |
25 | 23 | ||
@@ -33,6 +31,10 @@ def st2(I, s=1, dtype=np.float32): | @@ -33,6 +31,10 @@ def st2(I, s=1, dtype=np.float32): | ||
33 | Tg[:, :, ti] = dI[j] * dI[i] | 31 | Tg[:, :, ti] = dI[j] * dI[i] |
34 | ti = ti + 1 | 32 | ti = ti + 1 |
35 | 33 | ||
34 | + #if the user does not want a blurred field | ||
35 | + if(s == 0): | ||
36 | + return Tg | ||
37 | + | ||
36 | #blur the tensor field | 38 | #blur the tensor field |
37 | T = np.zeros(field_dims, dtype=dtype) | 39 | T = np.zeros(field_dims, dtype=dtype) |
38 | 40 | ||
@@ -125,7 +127,7 @@ def sym2mat(T): | @@ -125,7 +127,7 @@ def sym2mat(T): | ||
125 | 127 | ||
126 | return R | 128 | return R |
127 | 129 | ||
128 | -def st2vec(S, vector=0): | 130 | +def vec(S, vector=0): |
129 | 131 | ||
130 | if(S.ndim != 3): | 132 | if(S.ndim != 3): |
131 | print("ERROR: a 2D slice is expected") | 133 | print("ERROR: a 2D slice is expected") |
@@ -238,7 +240,20 @@ def fa(S): | @@ -238,7 +240,20 @@ def fa(S): | ||
238 | FA = np.sqrt(3./2.) * np.sqrt(fa_num) / np.sqrt(fa_den) | 240 | FA = np.sqrt(3./2.) * np.sqrt(fa_num) / np.sqrt(fa_den) |
239 | return FA | 241 | return FA |
240 | 242 | ||
241 | -def st2amira(filename, T): | 243 | +#calculate the specified eigenvalue for the tensor field |
244 | +def eigenval(S, ev): | ||
245 | + Sf = sym2mat(S) | ||
246 | + | ||
247 | + #calculate the eigenvectors and eigenvalues | ||
248 | + l, v = np.linalg.eig(Sf) | ||
249 | + | ||
250 | + #store the sorted eigenvalues | ||
251 | + ls = np.sort(l) | ||
252 | + evals = ls[:, :, ev] | ||
253 | + | ||
254 | + return evals | ||
255 | + | ||
256 | +def amira(filename, T): | ||
242 | #generates a tensor field that can be imported into Amira | 257 | #generates a tensor field that can be imported into Amira |
243 | 258 | ||
244 | # 0 dx dx ----> 0 | 259 | # 0 dx dx ----> 0 |