root / bin / image2geometry / bib_sepals.py @ 16
Historique | Voir | Annoter | Télécharger (17,46 ko)
1 |
import numpy as np |
---|---|
2 |
import matplotlib.pyplot as plt |
3 |
import math |
4 |
from scipy import optimize |
5 |
from scipy.ndimage import binary_dilation |
6 |
|
7 |
from titk_tools.io import imread, imsave, SpatialImage |
8 |
|
9 |
def center_on_point(img, cm): |
10 |
'''
|
11 |
Centers the image img on the point cm
|
12 |
'''
|
13 |
x = np.array(np.where(img > 0) )
|
14 |
xp=np.zeros_like(x) |
15 |
img1=np.zeros_like(img) |
16 |
s=img.shape |
17 |
center_img=np.array(s)/2
|
18 |
for i in [0, 1, 2]: |
19 |
xp[i]=x[i]+center_img[i]-cm[i] |
20 |
for i in range(0, len(x[0])): |
21 |
if ((xp[0][i]>=0) and (xp[0][i]<s[0]) and (xp[1][i]>=0) and (xp[1][i]<s[1]) and (xp[2][i]>=0) and (xp[2][i]<s[2])): |
22 |
img1[xp[0][i],xp[1][i],xp[2][i]]=img[x[0][i],x[1][i],x[2][i]] |
23 |
img1=SpatialImage(img1) |
24 |
img1.resolution=img.resolution |
25 |
return img1
|
26 |
|
27 |
|
28 |
def center_on_cm(img, volumic=True): |
29 |
'''
|
30 |
Centers the image img on the point cm
|
31 |
'''
|
32 |
s=img.shape |
33 |
res=img.voxelsize |
34 |
if volumic:
|
35 |
obj=img |
36 |
else :
|
37 |
obj=binary_dilation(img)-img |
38 |
x = np.array(np.where(obj > 0) )
|
39 |
cm = np.array([np.mean(x[i]) for i in [0,1,2]]) |
40 |
x = np.array(np.where(img > 0) )
|
41 |
xp=np.zeros_like(x) |
42 |
img1=np.zeros_like(img) |
43 |
center_img=np.array(s)/2
|
44 |
for i in [0, 1, 2]: |
45 |
xp[i]=x[i]+center_img[i]-cm[i] |
46 |
for i in range(0, len(x[0])): |
47 |
if ((xp[0][i]>=0) and (xp[0][i]<s[0]) and (xp[1][i]>=0) and (xp[1][i]<s[1]) and (xp[2][i]>=0) and (xp[2][i]<s[2])): |
48 |
img1[xp[0][i],xp[1][i],xp[2][i]]=img[x[0][i],x[1][i],x[2][i]] |
49 |
img1=SpatialImage(img1) |
50 |
img1.voxelsize=res |
51 |
return img1
|
52 |
|
53 |
|
54 |
def principal_directions(img, threshold=10, volumic=True): |
55 |
'''
|
56 |
Returns the first two principal eigen vectors of an input image
|
57 |
Fixed threshold of 10 for a 8 bit image
|
58 |
It suppposes an isotropic sampling of the image.
|
59 |
'''
|
60 |
if volumic:
|
61 |
obj=img |
62 |
else :
|
63 |
obj=binary_dilation(img)-img |
64 |
x,y,z = np.where(obj*255 > threshold) ## appropriate thresholding |
65 |
x = x - np.mean(x) |
66 |
y = y - np.mean(y) |
67 |
z = z - np.mean(z) |
68 |
coords = np.vstack([x,y,z]) |
69 |
cov = np.cov(coords) |
70 |
evals,evecs = np.linalg.eig(cov) |
71 |
sort_indices = np.argsort(evals)[::-1]
|
72 |
return list(evecs[:,sort_indices][0:2]) |
73 |
|
74 |
def direct_frame(pv): |
75 |
'''
|
76 |
Constructs a direct frame with first two unitvectors v0 and v1
|
77 |
'''
|
78 |
return np.array([pv[0], pv[1], np.cross(pv[0], pv[1])]) |
79 |
|
80 |
|
81 |
def write_transformation(T, trsf_file): |
82 |
'''
|
83 |
writes the affine transformation T (4x4 matrix) in
|
84 |
a textfile read by blockmatching.
|
85 |
'''
|
86 |
f = open(trsf_file,'w') |
87 |
f.write("( "+"\n") |
88 |
f.write("08 "+"\n") |
89 |
for i in T: |
90 |
for j in i: |
91 |
f.write(" "+str(j)+" ") |
92 |
f.write("\n")
|
93 |
f.write(") ")
|
94 |
return
|
95 |
|
96 |
|
97 |
|
98 |
def write_rigid(trsf_file, R, a): |
99 |
'''
|
100 |
write a rigid transformation with rotation matrix R and translation a
|
101 |
'''
|
102 |
T = np.identity(4)
|
103 |
T[0:3,0:3] = R |
104 |
T = np.transpose(T) |
105 |
T[0:3,3] = a |
106 |
#write_transformation(T, trsf_file)
|
107 |
np.savetxt(trsf_file, T, delimiter=";")
|
108 |
return
|
109 |
|
110 |
|
111 |
|
112 |
def write_superposing_transfo(pv_flo, pv_ref, img, trsf_file): |
113 |
'''
|
114 |
- pv_flo and pv-ref are lists of the first two principal vectors of the floating and the reference images respectively
|
115 |
- img is the floating image
|
116 |
'''
|
117 |
# compute the rotation matrix R
|
118 |
pframe_ref = direct_frame(pv_ref) |
119 |
pframe_flo = direct_frame(pv_flo) |
120 |
F = np.transpose(pframe_ref) |
121 |
G = np.transpose(pframe_flo) |
122 |
R = np.matmul(G, np.linalg.inv(F)) |
123 |
# blockmatching rotates arround the origin,
|
124 |
# so a rotation arround the middle of the image contains an additional translation t
|
125 |
s = img.shape |
126 |
res = img.voxelsize |
127 |
com = np.array(res)*np.array(s)/2
|
128 |
i = np.identity(3)
|
129 |
t = np.dot((i-R),np.array(com)) |
130 |
R = np.transpose(R) |
131 |
write_rigid(trsf_file, R, t) |
132 |
return
|
133 |
|
134 |
|
135 |
def add_side_slices(Img, x0, x1, y0, y1, z0, z1): |
136 |
"""
|
137 |
adds 0 value slices on different sides of the image
|
138 |
"""
|
139 |
s=Img.shape |
140 |
ss=(s[0]+x0+x1,s[1]+y0+y1,s[2]+z0+z1) |
141 |
Img_new = (SpatialImage(np.zeros(ss))).astype('uint8')
|
142 |
Img_new[x0:ss[0]-x1,y0:ss[1]-y1,z0:ss[2]-z1]=Img |
143 |
Img_new.voxelsize = Img.voxelsize |
144 |
return Img_new
|
145 |
|
146 |
|
147 |
def remove_side_slices(Img, x0, x1, y0, y1, z0, z1): |
148 |
"""
|
149 |
removes slices on different sides of the image
|
150 |
"""
|
151 |
ss=Img.shape |
152 |
Img_new=Img[x0:ss[0]-x1,y0:ss[1]-y1,z0:ss[2]-z1] |
153 |
#Img_new.resolution = Img.resolution
|
154 |
return Img_new
|
155 |
|
156 |
|
157 |
def measure_hight(a): |
158 |
b= np.where(a) |
159 |
height = 0
|
160 |
if b[0].shape[0]>0 : |
161 |
height = b[0][-1] |
162 |
return height
|
163 |
|
164 |
|
165 |
def measure_height(a): |
166 |
b= np.where(a) |
167 |
height = [0,0] |
168 |
if b[0].shape[0]>0 : |
169 |
height = [b[0].min(),b[0].max()] |
170 |
return height
|
171 |
|
172 |
|
173 |
def extract_curve(x_section): |
174 |
sx = x_section.shape |
175 |
xx = np.zeros((sx[0],2)) |
176 |
for i in range(0,sx[0]): |
177 |
xx[i,0] = i
|
178 |
xx[i,1] = measure_hight(x_section[i,:])
|
179 |
return xx
|
180 |
|
181 |
|
182 |
def extract_curves(x_section): |
183 |
sx = x_section.shape |
184 |
xup = np.zeros((sx[0],2)) |
185 |
xdown = np.zeros((sx[0],2)) |
186 |
for i in range(0,sx[0]): |
187 |
xup[i,0] = i
|
188 |
xdown[i,0] = i
|
189 |
xup[i,1] = measure_height(x_section[i,:])[1] |
190 |
xdown[i,1] = measure_height(x_section[i,:])[0] |
191 |
return xup, xdown
|
192 |
|
193 |
|
194 |
def write_curve(y, pixelsize, filename) : |
195 |
FILE = open(filename,"w") |
196 |
FILE.write('# '+str(pixelsize[0])+' '+str(pixelsize[1])+'\n') |
197 |
s = y.shape |
198 |
#FILE.write('# '+str(s[0])+'\n')
|
199 |
for i in range(0,s[0]) : |
200 |
FILE.write(str(y[i,0])+' '+str(y[i,1])+'\n') |
201 |
FILE.close() |
202 |
return
|
203 |
|
204 |
|
205 |
def struct_element_sphere(radius): |
206 |
s=int(2*radius+1) |
207 |
structure=np.zeros((s,s,s)) |
208 |
center = np.array([radius, radius, radius]) |
209 |
Nl=range(s)
|
210 |
for i in Nl: |
211 |
for j in Nl: |
212 |
for k in Nl: |
213 |
p=np.array([i,j,k]) |
214 |
d=p-center |
215 |
dist=np.sqrt(sum(d*d))
|
216 |
if dist<=radius:
|
217 |
structure[i,j,k]=1
|
218 |
return structure
|
219 |
|
220 |
|
221 |
def create_artificial_sepal(AA, RR, resolution): |
222 |
# A = parameters of an ellipse, as projected on xy plane (2d array)
|
223 |
# R = curvature radius in directions x and y (2d array)
|
224 |
# (A and R are given in micrometers)
|
225 |
# resolution = voxelsize of the output stack
|
226 |
A = np.array([AA[i]/resolution[i] for i in [0,1]]) |
227 |
R = np.array([RR[i]/resolution[i] for i in [0,1]]) |
228 |
h = np.array([math.sqrt(R[i]**2-A[i]**2) for i in range(len(A))]) |
229 |
zmax=np.array([R[i]-math.sqrt(R[i]**2-A[i]**2) for i in [0,1]]) |
230 |
#zmax= int(math.sqrt(zmax[0]*zmax[1]))
|
231 |
zmax=zmax.mean() |
232 |
#zmax = 5
|
233 |
print(zmax) |
234 |
marge = 0.2
|
235 |
# creating the stack and the surface
|
236 |
s = (int(A[0]*2*(1+marge)), int(A[1]*2*(1+marge)), int(zmax*(1+2*marge))) |
237 |
cm = np.array(s)/2
|
238 |
x = np.array(range(0,s[0])) |
239 |
y = np.array(range(0,s[1])) |
240 |
xx = x - cm[0]
|
241 |
yy = y - cm[1]
|
242 |
#xgrid, ygrid = np.meshgrid(xx, yy, sparse=True) # make sparse output arrays
|
243 |
#mask=(((xgrid**2)/float(A[0])**2+(ygrid**2)/float(A[1])**2)<1).astype('uint8')
|
244 |
z = np.zeros((s[0],s[1])) |
245 |
stack= np.zeros(s).astype('uint8')
|
246 |
for i in x: |
247 |
for j in range(0,s[1]): |
248 |
if xx[i]**2/float(A[0])**2+yy[j]**2/float(A[1])**2<=1 : |
249 |
zx = (math.sqrt(R[0]**2-xx[i]**2)-h[0])*(1-abs(yy[j])/A[1]) |
250 |
zy = (math.sqrt(R[1]**2-yy[j]**2)-h[1])*(1-abs(xx[i])/A[0]) |
251 |
z[i,j] = math.sqrt(zx*zy) |
252 |
#z[i,j] = (zx+zy)/2
|
253 |
#z[i,j] = 5
|
254 |
stack[i,j,int(zmax*marge+z[i,j])]=1 |
255 |
stack = SpatialImage(stack) |
256 |
stack.resolution = resolution |
257 |
return z, stack
|
258 |
|
259 |
|
260 |
|
261 |
def create_artificial_sepal_ellipse(AA, H, resolution): |
262 |
'''
|
263 |
# A = parameters of an ellipse, as projected on xy plane (2d array)
|
264 |
# R = curvature radius in directions x and y (2d array)
|
265 |
# (A and R are given in micrometers)
|
266 |
# resolution = voxelsize of the output stack
|
267 |
'''
|
268 |
A = np.array([AA[i]/resolution[i] for i in [0,1]]) |
269 |
h = H/resolution[2]
|
270 |
zmax=h |
271 |
marge = 0.2
|
272 |
# creating the stack and the surface
|
273 |
s = (int(A[0]*2*(1+marge)), int(A[1]*2*(1+marge)), int(zmax*(1+5*marge))) |
274 |
cm = np.array(s)/2
|
275 |
x = np.array(range(0,s[0])) |
276 |
y = np.array(range(0,s[1])) |
277 |
xx = x - cm[0]
|
278 |
yy = y - cm[1]
|
279 |
#xgrid, ygrid = np.meshgrid(xx, yy, sparse=True) # make sparse output arrays
|
280 |
#mask=(((xgrid**2)/float(A[0])**2+(ygrid**2)/float(A[1])**2)<1).astype('uint8')
|
281 |
z = np.zeros((s[0],s[1])) |
282 |
#z = -h*((xgrid**2)/float(A[0])**2+(ygrid**2)/float(A[1])**2)
|
283 |
stack= np.zeros(s).astype('uint8')
|
284 |
for i in x: |
285 |
for j in y: |
286 |
if xx[i]**2/float(A[0])**2+yy[j]**2/float(A[1])**2<=1 : |
287 |
z[i,j] = -h*((xx[i]**2)/float(A[0])**2+(yy[j]**2)/float(A[1])**2-1) |
288 |
stack[i,j,int(zmax*4*marge+z[i,j])]=1 |
289 |
stack = SpatialImage(stack) |
290 |
stack.voxelsize = resolution |
291 |
return z, stack
|
292 |
|
293 |
# -------------------------------------------------------------------
|
294 |
|
295 |
def read_curve(filename) : |
296 |
"""
|
297 |
Reads the coordinates of the point-list defining a 2D curve.
|
298 |
**Returns**
|
299 |
y : 2-column array
|
300 |
defines a curve as an ordered list of points,
|
301 |
each row of the array represents a point on the curve and contains
|
302 |
its 2D cartesian coordinates
|
303 |
pixelsize : tuple (res0, res1) in micrometers
|
304 |
"""
|
305 |
x0 = [] |
306 |
pixelsize = (1.0,1.0) |
307 |
for line in file(filename): |
308 |
if line[0] == "#" : |
309 |
line = line.lstrip('# ')
|
310 |
line = line.rstrip('\n')
|
311 |
line_list = [float(x) for x in line.split(' ')] |
312 |
pixelsize = (line_list[0], line_list[1]) |
313 |
else :
|
314 |
line = line.rstrip('\n')
|
315 |
line_list = [float(x) for x in line.split(' ')] |
316 |
x0.append(line_list) |
317 |
y = np.array(x0) |
318 |
return y, pixelsize
|
319 |
|
320 |
|
321 |
|
322 |
def distance(p1, p2): |
323 |
return np.sqrt((p1[0]-p2[0])**2+(p1[1]-p2[1])**2) |
324 |
|
325 |
def distance_to_line(p1, p2, p0): |
326 |
'''
|
327 |
gives the distance of point p0 to the line defined by points p1 and p2 (in 2d)
|
328 |
'''
|
329 |
return abs((p2[1]-p1[1])*p0[0]-(p2[0]-p1[0])*p0[1]+p2[0]*p1[1]-p2[1]*p1[0])/distance(p1,p2) |
330 |
|
331 |
def curvature(p1,p2,p3): |
332 |
t1 = (p3[0]**2-p2[0]**2+p3[1]**2-p2[1]**2)/(2.0*(p3[1]-p2[1])) |
333 |
t2 = (p2[0]**2-p1[0]**2+p2[1]**2-p1[1]**2)/(2.0*(p2[1]-p1[1])) |
334 |
n1 = (p3[0]-p2[0])/(p3[1]-p2[1]) |
335 |
n2 = (p2[0]-p1[0])/(p2[1]-p1[1]) |
336 |
pcx = (t1-t2+p3[1]-p1[1])/(n1-n2) |
337 |
pc = [pcx, -n1*pcx+t1/2+p3[1]/2+p1[1]/2] |
338 |
R = distance(p1, pc) |
339 |
return 1.0/R, pc |
340 |
|
341 |
|
342 |
def curvature2(p1,p2,p3): |
343 |
# http://www.ambrsoft.com/TrigoCalc/Circle3D.htm
|
344 |
A = p1[0]*(p2[1]-p3[1])-p1[1]*(p2[0]-p3[0])+p2[0]*p3[1]-p3[0]*p2[1] |
345 |
B = (p1[0]**2+p1[1]**2)*(p3[1]-p2[1])+(p2[0]**2+p2[1]**2)*(p1[1]-p3[1])+(p3[0]**2+p3[1]**2)*(p2[1]-p1[1]) |
346 |
C = (p1[0]**2+p1[1]**2)*(p3[0]-p2[0])+(p2[0]**2+p2[1]**2)*(p1[0]-p3[0])+(p3[0]**2+p3[1]**2)*(p2[0]-p1[0]) |
347 |
D = (p1[0]**2+p1[1]**2)*(p3[0]*p2[1]-p2[0]*p3[1])+(p2[0]**2+p2[1]**2)*(p1[0]*p3[1]-p3[0]*p1[1])+(p3[0]**2+p3[1]**2)*(p2[0]*p1[1]-p1[0]*p2[1]) |
348 |
x = -B/(2*A)
|
349 |
y = C/(2*A)
|
350 |
pc = [x, y] |
351 |
R = distance(p1, pc) |
352 |
return 1.0/R, pc |
353 |
|
354 |
|
355 |
def curve_perle(y, first, last, step): |
356 |
yy=[] |
357 |
for i in range(first, last, step): |
358 |
if y[i][1]>0: |
359 |
yy.append(y[i]) |
360 |
if i<last:
|
361 |
yy.append(y[last]) |
362 |
return np.array(yy)
|
363 |
|
364 |
|
365 |
|
366 |
def compute_curvature_radius(x,y): |
367 |
# coordinates of the barycenter
|
368 |
x_m = np.mean(x) |
369 |
y_m = np.mean(y) |
370 |
def calc_R(c): |
371 |
""" calculate the distance of each 2D points from the center c=(xc, yc) """
|
372 |
return np.sqrt((x-c[0])**2 + (y-c[1])**2) |
373 |
#
|
374 |
def calc_ecart(c): |
375 |
""" calculate the algebraic distance between the 2D points and the mean circle centered at c=(xc, yc) """
|
376 |
Ri = calc_R(c) |
377 |
return Ri - Ri.mean()
|
378 |
#
|
379 |
center_estimate = x_m, y_m |
380 |
center_2, ier = optimize.leastsq(calc_ecart, center_estimate) |
381 |
#
|
382 |
xc_2, yc_2 = center_2 |
383 |
Ri_2 = calc_R(center_2) |
384 |
R_2 = Ri_2.mean() |
385 |
residu_2 = sum((Ri_2 - R_2)**2) |
386 |
pc=[xc_2, yc_2] |
387 |
return R_2, pc
|
388 |
|
389 |
|
390 |
def circle(R, c): |
391 |
phi=np.linspace(np.pi/6., 5*np.pi/6., 51) |
392 |
x=c[0]+R*np.cos(phi)
|
393 |
y=c[1]+R*np.sin(phi)
|
394 |
return x,y
|
395 |
|
396 |
|
397 |
|
398 |
def analyze_curve1(name, y, pixelsize, outfilename, title, graph_name='graph.png'): |
399 |
# isotropic pixels
|
400 |
y[:,0] = y[:,0]*pixelsize[0] |
401 |
y[:,1] = y[:,1]*pixelsize[1] |
402 |
maxv = [y[:,i].max() for i in [0,1]] |
403 |
# find first and last points on the curve
|
404 |
step = 5
|
405 |
sep_indices = np.where(y[:,1])[0] |
406 |
first = sep_indices[0]#+step/2 |
407 |
last = sep_indices[-1]#-step/2 |
408 |
# compute flat length
|
409 |
flatlength = distance(y[first],y[last]) |
410 |
print("flat length =", flatlength," um") |
411 |
# compute curved length and height (maximal distance to the base)
|
412 |
yy = curve_perle(y, first, last, step) |
413 |
length = 0
|
414 |
height = 0
|
415 |
height_index = 0
|
416 |
p1 = yy[0]
|
417 |
p2 = yy[-1]
|
418 |
for i in range(0, len(yy)-1): |
419 |
length = length + distance(yy[i+1],yy[i])
|
420 |
d = distance_to_line(p1, p2, yy[i]) |
421 |
if d>height :
|
422 |
height = d |
423 |
height_index = i |
424 |
print("length = ",length," um") |
425 |
print("height = ",height," um") |
426 |
middle_point = yy[int(len(yy)/2)] |
427 |
# compute curvature radius by fitting the sepal section to a circle
|
428 |
yyy=y[first:last] |
429 |
R, pcR = compute_curvature_radius(yyy[:,0],yyy[:,1]) |
430 |
print("R=",R," um") |
431 |
# cutting curve in pieces in order to estimate curvature radius on portions of the curve
|
432 |
slength=len(yyy)
|
433 |
y21=yyy[0:int(slength/2)] |
434 |
y22=yyy[int(slength/2):slength] |
435 |
y41=yyy[0:int(slength/4)] |
436 |
y423=yyy[int(slength/4):3*int(slength/4)] |
437 |
y44=yyy[3*int(slength/4):slength] |
438 |
# and computing the curvature radius for each portion
|
439 |
R21, pc21 = compute_curvature_radius(y21[:,0],y21[:,1]) |
440 |
R22, pc22 = compute_curvature_radius(y22[:,0],y22[:,1]) |
441 |
R41, pc41 = compute_curvature_radius(y41[:,0],y41[:,1]) |
442 |
R423, pc423 = compute_curvature_radius(y423[:,0],y423[:,1]) |
443 |
R44, pc44 = compute_curvature_radius(y44[:,0],y44[:,1]) |
444 |
fig = plt.figure(figsize=(12, 5)) |
445 |
plt.plot(yy[:,0], yy[:,1], color='lightgreen', linewidth=10, label='length='+"{:.0f}".format(length)+" um") |
446 |
#plt.plot(y[:,0], y[:,1], '--')
|
447 |
#plt.plot(y[first][0], y[first][1], 'ro')
|
448 |
#plt.plot(middle_point[0], middle_point[1], 'ro')
|
449 |
#plt.plot(y[last][0], y[last][1], 'ro')
|
450 |
#plt.plot(yy[height_index][0], yy[height_index][1], 'go')
|
451 |
plt.plot(pcR[0], pcR[1], 'ro', color='royalblue') |
452 |
plt.plot(pc423[0], pc423[1], 'ro', color='tomato') |
453 |
xR,yR = circle(R, pcR) |
454 |
plt.plot(xR, yR, "--",color='royalblue', linewidth=3, label='R='+"{:.0f}".format(R)+" um") |
455 |
xR,yR = circle(R423, pc423) |
456 |
plt.plot(xR, yR, "--", color='tomato', linewidth=3, label='R423='+"{:.0f}".format(R423)+" um") |
457 |
plt.gca().set_aspect('equal', adjustable='box') |
458 |
plt.xlabel('x (um)')
|
459 |
plt.ylabel('z (um)')
|
460 |
plt.ylim([0,1000]) |
461 |
plt.xlim([0,3000]) |
462 |
plt.legend() |
463 |
plt.grid(True)
|
464 |
plt.title(title) |
465 |
#plt.show()
|
466 |
fig.savefig(graph_name) |
467 |
#plt.close()
|
468 |
# write the data into a file
|
469 |
FILE = open(outfilename,"a") |
470 |
FILE.write(name+';'+str(length)+';'+str(R)+';'+str(flatlength)+';'+str(height)+'\n') |
471 |
FILE.close() |
472 |
return length, flatlength, height, R, R21, R22, R41, R423, R44
|
473 |
|
474 |
def imsave2D(filename, matrix): |
475 |
fig = plt.figure() |
476 |
plt.gca().imshow(np.transpose(matrix), interpolation='none')
|
477 |
fig.savefig(filename) |
478 |
return
|
479 |
|
480 |
|
481 |
|
482 |
def register_objects(img_flo, img_ref, preregisterd=True, ph=6, pl=2, es=5, fs=3, save_files=True, iterations=2): |
483 |
# -- "Specify paths to image files" --
|
484 |
# ------------------------------------------------
|
485 |
sequence_name = "register_"
|
486 |
file_times = [1, 2] |
487 |
filenames = [sequence_name + str(t).zfill(2) for t in file_times] |
488 |
list_images = [img_flo, img_ref] |
489 |
|
490 |
images = {} |
491 |
for i in [0,1]: |
492 |
images[filenames[i]] = list_images[i] |
493 |
|
494 |
rigid_images = {} |
495 |
rigid_transformations = {} |
496 |
affine_images = {} |
497 |
affine_transformations = {} |
498 |
registered_images = {} |
499 |
non_linear_transformations = {} |
500 |
[reference_filename, floating_filename, reference_time, floating_time] = [ filenames[0], filenames[1], file_times[0], file_times[1]] |
501 |
#for reference_filename, floating_filename, reference_time, floating_time, in zip(filenames[1:],filenames[:-1],file_times[1:],file_times[:-1]):
|
502 |
print("================================")
|
503 |
print("Registering ", floating_time, " on ", reference_time) |
504 |
print("================================")
|
505 |
|
506 |
###################################################
|
507 |
# Output structure
|
508 |
###################################################
|
509 |
|
510 |
namestring = "_ph"+str(ph)+"_pl"+str(pl)+"_es"+str(es)+"_fs"+str(fs) |
511 |
|
512 |
output_dirname = dirname + '/' + sequence_name + "_" + str(floating_time).zfill(2) + "_on_" + str(reference_time).zfill(2) + "" + namestring |
513 |
if not os.path.exists(output_dirname): |
514 |
os.makedirs(output_dirname) |
515 |
|
516 |
reference_img = images[reference_filename] |
517 |
floating_img = images[floating_filename] |
518 |
|
519 |
####################################################################
|
520 |
|
521 |
# Registration of the floating images on ref
|
522 |
# -----------------------------------------------------
|
523 |
|
524 |
if (not preregistered) : |
525 |
# A. Find optimised rigid transformations
|
526 |
rigid_img, rigid_trsf = find_rigid_transfo2(reference_img, floating_img) |
527 |
rigid_images[floating_filename] = rigid_img |
528 |
rigid_transformations[floating_filename] = rigid_trsf |
529 |
|
530 |
if save_files:
|
531 |
# rigid-registered images
|
532 |
rigid_filename = output_dirname + '/' + floating_filename + "_rigid_on_" + str(reference_time).zfill(2) + ".inr.gz" |
533 |
imsave(rigid_filename, rigid_img) |
534 |
|
535 |
# optimised (with block-matching) rigid transformations
|
536 |
rigid_trsf_filename = output_dirname + '/tr_' + floating_filename + '_rigid.txt' |
537 |
tfsave(rigid_trsf_filename, rigid_trsf) |
538 |
|
539 |
# B. Find optimised affine transformations (initialised by the rigid tfs computed above)
|
540 |
affine_img, affine_trsf = find_affine_transfo(reference_img, floating_img, init_trsf=rigid_trsf) |
541 |
affine_images[floating_filename] = affine_img |
542 |
affine_transformations[floating_filename] = affine_trsf |
543 |
|
544 |
if save_files:
|
545 |
# affine-registered images
|
546 |
affine_filename = output_dirname + '/' + floating_filename + "_affine_on_" + str(reference_time).zfill(2) + ".inr.gz" |
547 |
imsave(affine_filename, affine_img) |
548 |
|
549 |
# optimised (with block-matching) affine transformations
|
550 |
affine_trsf_filename = output_dirname + '/tr_' + floating_filename + '_affine.txt' |
551 |
tfsave(affine_filename, affine_trsf) |
552 |
floating_img0=affine_img |
553 |
else :
|
554 |
floating_img0=floating_img |
555 |
# C. Find nonlinear transformations which register the affine-transformed images
|
556 |
#registered_img, nl_trsf = find_nl_transfo(reference_img, affine_img, ph=ph, pl=pl, es=es, fs=fs)
|
557 |
for it in range(iterations): |
558 |
registered_img, nl_trsf = find_nl_transfo(reference_img, floating_img0, ph=ph, pl=pl, es=es, fs=fs) |
559 |
registered_images[floating_filename] = registered_img |
560 |
non_linear_transformations[floating_filename] = nl_trsf |
561 |
|
562 |
# paths to nonlinearly registered images
|
563 |
registered_filename = output_dirname + '/' + floating_filename + "_registered_on_" + str(reference_time).zfill(2) + "_it"+str(it)+".inr.gz" |
564 |
imsave(registered_filename, registered_img) |
565 |
floating_img0=registered_img |
566 |
|
567 |
if save_files:
|
568 |
# non-linear transformations
|
569 |
nl_trsf_filename = output_dirname + '/' + floating_filename + "_it"+str(it)+"_vectorfield.inr.gz" |
570 |
save_trsf(nl_trsf, nl_trsf_filename, compress=True)
|
571 |
return registered_img
|
572 |
|