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