1
+ import numpy as np
2
+ import numpy .matlib
3
+ from tifffile import imread , imsave
4
+ import matplotlib .pyplot as plt
5
+ import matplotlib .image as mpimg
6
+ import pretty_errors
7
+
8
+ def getDcorrMax (d ):
9
+ '''
10
+ # ---------------------------------------
11
+ #
12
+ # Return the local maxima of the decorrelation function d
13
+ #
14
+ # Inputs:
15
+ # d Decorrelation function
16
+ #
17
+ # Outputs:
18
+ # ind Position of the local maxima
19
+ # A Amplitude of the local maxima
20
+ #
21
+ # ---------------------------------------
22
+ '''
23
+
24
+ ind = np .argmax (d )
25
+ A = d [ind ]
26
+ t = d ;
27
+ # arbitrary peak significance parameter imposed by numerical noise
28
+ # this becomes relevant especially when working with post-processed data
29
+ dt = 0.001 ;
30
+
31
+ while ind == np .shape (t )[0 ]:
32
+ t [- 1 ] = []
33
+ if np .isempty (t ):
34
+ A = 0
35
+ ind = 1
36
+ else :
37
+ ind = np .argmax (t )
38
+ A = t [ind ]
39
+ # check if the peak is significantly larger than the former minimum
40
+ if t [ind ] - np .min (d [ind :- 1 ]) > dt :
41
+ break
42
+ else :
43
+ t [ind ] = np .min (d [ind :- 1 ])
44
+ ind = np .shape (t )[0 ]
45
+
46
+ return ind , A
47
+
48
+ def getDcorrLocalMax (d ):
49
+ '''
50
+ # [ind,A] = getDcorrLocalMax(d)
51
+ # ---------------------------------------
52
+ #
53
+ # Return the local maxima of the decorrelation function d
54
+ #
55
+ # Inputs:
56
+ # d Decorrelation function
57
+ #
58
+ # Outputs:
59
+ # ind Position of the local maxima
60
+ # A Amplitude of the local maxima
61
+ #
62
+ # ---------------------------------------
63
+ '''
64
+ numel = np .shape (d )
65
+ numel = numel [0 ]
66
+
67
+ if numel < 1 :
68
+ ind = 0
69
+ A = d [0 ]
70
+ else :
71
+ ind = np .argmax (d )
72
+ A = d [ind ]
73
+ while numel > 1 :
74
+ # if the last indexed position
75
+ if ind == numel :
76
+ d [- 1 ] = []
77
+ ind = np .argmax (d )
78
+ A = d [ind ]
79
+
80
+ # If the first indexed position
81
+ elif ind == 0 :
82
+ break
83
+
84
+ # If the minimum amplitude between ind and the last index is above a threshold
85
+ elif (A - np .min (d [ind :- 1 ])) >= 0.0005 :
86
+ break
87
+
88
+ # If the threshold is not met.
89
+ else :
90
+ d [- 1 ] = []
91
+ ind = np .argmax (d )
92
+ A = d [ind ]
93
+
94
+ if ind .size == 0 :
95
+ ind = 0
96
+ A = d [0 ]
97
+
98
+ else :
99
+ A = d [ind ]
100
+
101
+ return ind , A
102
+
103
+ def linear_map (val , valMin , valMax ):
104
+ '''
105
+ # rsc = linear_map(val,valMin,valMax,mapMin,mapMax)
106
+ # ---------------------------------------
107
+ #
108
+ # Performs a linear mapping of val from the range [valMin,valMax] to the range [mapMin,mapMax]
109
+ #
110
+ # Inputs:
111
+ # val Input value
112
+ # valMin Minimum value of the range of val
113
+ # valMax Maximum value of the range of val
114
+ # mapMin Minimum value of the new range of val
115
+ # mapMax Maximum value of the new range of val
116
+ #
117
+ # Outputs:
118
+ # rsc Rescaled value
119
+ #
120
+ # Example : rsc = linear_map(val,0,255,0,1); # map the uint8 val to the range [0,1]
121
+ #
122
+ # ---------------------------------------
123
+ '''
124
+
125
+ mapMin = valMin
126
+ mapMax = valMax
127
+ valMin = np .min (val )
128
+ valMax = np .max (val )
129
+
130
+ # convert the input value between 0 and 1
131
+ tempVal = (val - valMin )/ (valMax - valMin )
132
+
133
+ # clamp the value between 0 and 1
134
+ map0 = tempVal < 0
135
+ map1 = tempVal > 1
136
+ tempVal [map0 ] = 0
137
+ tempVal [map1 ] = 1
138
+
139
+ # rescale and return
140
+ rsc = np .multiply (tempVal , (mapMax - mapMin )) + mapMin
141
+ return rsc
142
+
143
+ def apod_im_rect (image , N ):
144
+ '''
145
+ # [out,mask] = apodImRect(in,N)
146
+ # ---------------------------------------
147
+ #
148
+ # Apodize the edges of a 2D image
149
+ #
150
+ # Inputs:
151
+ # in Input image
152
+ # N Number of pixels of the apodization
153
+ #
154
+ # Outputs:
155
+ # out Apodized image
156
+ # mask Mask used to apodize the image
157
+ #
158
+ # ---------------------------------------
159
+ '''
160
+
161
+ number_x , number_y = np .shape (image )
162
+
163
+ x = np .abs (np .linspace (- number_x / 2 , number_x / 2 , number_x ))
164
+ y = np .abs (np .linspace (- number_y / 2 , number_y / 2 , number_y ))
165
+ mapx = x > (number_x / 2 - N )
166
+ mapy = y > (number_y / 2 - N )
167
+
168
+ val = np .mean (image )
169
+
170
+ d = np .multiply ((- np .abs (x ) - np .mean (- np .abs (x [mapx ]))), mapx )
171
+ d = linear_map (d , - np .pi / 2 , np .pi / 2 )
172
+ d [mapx == False ] = np .pi / 2
173
+ maskx = (np .sin (d )+ 1 )/ 2
174
+
175
+ d = np .multiply ((- np .abs (y ) - np .mean (- np .abs (y [mapy ]))), mapy )
176
+ d = linear_map (d , - np .pi / 2 , np .pi / 2 )
177
+ d [mapy == False ] = np .pi / 2
178
+ masky = (np .sin (d )+ 1 )/ 2
179
+
180
+ # Make it 2D
181
+ # np.matlib.repmat(a, m, n). a: array/matrix. m,n: int - number of times a is repeated on first and second axes.
182
+ mask_1 = np .matlib .repmat (masky , number_x , 1 )
183
+ mask_2 = np .matlib .repmat (maskx , number_y , 1 )
184
+ mask_2 = np .transpose (mask_2 )
185
+ mask = np .multiply (mask_1 , mask_2 )
186
+
187
+ out = np .multiply ((image - val ), mask ) + val
188
+
189
+ return out
190
+
191
+ def getCorrcoef (I1 , I2 , c1 = None , c2 = None ):
192
+ '''
193
+ # cc = getCorrcoef(I1,I2,c1,c2)
194
+ # ---------------------------------------
195
+ #
196
+ # Return the normalized correlation coefficient expressed in Fourier space
197
+ #
198
+ # Inputs:
199
+ # I1 Complex Fourier transfom of image 1
200
+ # I2 Complex Fourier transfom of image 2
201
+ #
202
+ # Outputs:
203
+ # cc Normalized cross-correlation coefficient
204
+ '''
205
+
206
+ if c1 == None :
207
+ c1 = np .square (np .sqrt (np .sum (np .sum (np .abs (I1 )))))
208
+
209
+ if c2 == None :
210
+ c2 = np .square (np .sqrt (np .sum (np .sum (np .abs (I2 )))))
211
+ import warnings
212
+ warnings .simplefilter ("ignore" , np .ComplexWarning )
213
+ a = np .sum (np .real (np .multiply (I1 , np .conjugate (I2 ))))
214
+ b = c1 * c2
215
+ np .seterr (invalid = 'ignore' )
216
+ cc = np .divide (a , b )
217
+ cc = np .double (cc )
218
+ cc = np .floor (1000 * cc )/ 1000
219
+ return cc
220
+
221
+ def getDCorr (im , r = None , Ng = 10 , figID = 0 ):
222
+ verbose = True
223
+ if r is None :
224
+ r = np .linspace (0 , 1 , 50 )
225
+
226
+ if np .shape (r )[0 ] < 30 :
227
+ r = np .linspace (np .min (r ), np .max (r ), 30 )
228
+
229
+ if Ng < 5 :
230
+ Ng = 5
231
+
232
+ im = np .single (im )
233
+
234
+ # Make size odd numbers only.
235
+ number_x , number_y = np .shape (im )
236
+ if np .mod (number_x , 2 ) == 0 :
237
+ im = np .delete (im , 0 , 0 )
238
+ if np .mod (number_y , 2 ) == 0 :
239
+ im = np .delete (im , 0 , 1 )
240
+
241
+ number_x , number_y = np .shape (im )
242
+
243
+ x = np .linspace (- 1 , 1 , number_x )
244
+ y = np .linspace (- 1 , 1 , number_y )
245
+ x , y = np .meshgrid (x , y )
246
+ R = np .sqrt (x ** 2 + y ** 2 )
247
+ Nr = np .shape (r )[0 ]
248
+
249
+ # In = Fourier Normalized Image
250
+ In = np .fft .fftshift (np .fft .fft2 (np .fft .fftshift (im )))
251
+ In = np .divide (In , np .abs (In ))
252
+ In [np .isinf (In )] = 0
253
+ In [np .isnan (In )] = 0
254
+ mask0 = R ** 2 < 1 ** 2
255
+ In = np .multiply (np .transpose (mask0 ), In )
256
+
257
+ # Ik = Fourier Transform of Image
258
+ Ik = np .multiply (np .transpose (mask0 ), np .fft .fftshift (np .fft .fft2 (np .fft .fftshift (im ))))
259
+ c = np .sqrt (np .sum (np .multiply (Ik , np .conjugate (Ik ))))
260
+ r0 = np .linspace (r [0 ], r [- 1 ], Nr )
261
+
262
+ d0 = np .zeros (np .shape (r )[0 ])
263
+ for k in range (np .shape (r )[0 ], 0 , - 1 ):
264
+ cc = getCorrcoef (Ik , np .transpose (np .square (R )) < np .multiply (r0 [k - 1 ]** 2 , In ), c )
265
+ if np .isnan (cc ):
266
+ cc = 0
267
+ d0 [k - 1 ] = cc
268
+
269
+ ind0 , snr0 = getDcorrLocalMax (d0 )
270
+
271
+ k0 = r [ind0 ]
272
+ gMax = 2 / r0 [ind0 ]
273
+
274
+ if np .isinf (gMax ):
275
+ gMax = max (np .shape (im )[0 ], np .shape (im )[1 ])/ 2
276
+
277
+ # Search for the Highest Frequency Peak
278
+ g = np .hstack ((np .shape (im )[0 ]/ 4 , np .exp (np .linspace (np .log (gMax ), np .log (0.15 ), Ng ))))
279
+ d = np .zeros ((Nr , 2 * Ng ))
280
+
281
+ number_iterations = 2
282
+ kc = np .zeros (np .shape (g )[0 ]* number_iterations )
283
+ kc [0 ] = k0
284
+
285
+ SNR = np .zeros (np .shape (g )[0 ]* number_iterations )
286
+ SNR [0 ] = snr0
287
+
288
+ ind0 = 0
289
+
290
+
291
+ # Two Step Refinement
292
+ for refin in range (number_iterations ): # 0, 1.
293
+ for h in range (np .shape (g )[0 ]): # 0..10
294
+
295
+ # Fourier Gaussian Filtering
296
+ Ir = np .multiply (np .transpose (Ik ), (1 - np .exp (- 2 * g [h ]* g [h ]* R ** 2 )))
297
+ c = np .sqrt (np .sum (np .abs (Ir )** 2 ))
298
+
299
+ for k in range (np .shape (r )[0 ]- 1 , ind0 - 1 , - 1 ): # 49...0
300
+ mask = R ** 2 < r [k ]** 2
301
+ cc = getCorrcoef (Ir [mask ], In [np .transpose (mask )], c )
302
+ if np .isnan (cc ):
303
+ cc = 0
304
+ d [k , h + (Ng * refin ) - 1 ] = cc
305
+
306
+ ind , amp = getDcorrLocalMax (d [k :- 1 , h + (Ng * refin ) - 1 ])
307
+
308
+ snr = d [ind , h + (Ng * refin ) - 1 ]
309
+ ind = ind + k
310
+
311
+ kc [h + Ng * refin + 1 ] = r [ind ]
312
+ SNR [h + Ng * refin + 1 ] = snr
313
+
314
+ print ("kc :" , kc )
315
+ print ("SNR :" , SNR )
316
+
317
+
318
+ return 5 , 5
319
+
320
+ def main_image_decorr ():
321
+ '''
322
+ https://github.com/Ades91/ImDecorr/blob/master/main_imageDecorr.m
323
+ '''
324
+ # Load the Data
325
+ raw_image = np .array (imread ('/Users/S155475/Local/Publication materials/2020-SOLS/Data/MV3Membrane/LateralInsets/DetailVesicleTimepoint30.tif' ))
326
+ raw_image = np .double (raw_image )
327
+
328
+ # projected pixel size
329
+ pps = 5
330
+
331
+ Nr = 50
332
+ Ng = 10
333
+ r = np .linspace (0 , 1 , Nr )
334
+
335
+ GPU = False
336
+
337
+ # Apodize Image Edges with a Cosine Function over 20 pixels
338
+ image = apod_im_rect (raw_image , 20 )
339
+
340
+ # Compute Resolution
341
+ figID = 100
342
+ if GPU :
343
+ pass # [kcMax,A0] = getDcorr(gpuArray(image),r,Ng,figID); gpuDevice(1);
344
+ else :
345
+ kcMax , A0 = getDCorr (image , r , Ng , figID )
346
+
347
+ print ("kcMax :" , kcMax , "A0 :" , A0 )
348
+
349
+ # sectorial resolution
350
+ Na = 8 # number of sectors
351
+ figID = 101
352
+ if GPU :
353
+ pass # [kcMax,A0] = getDcorrSect(gpuArray(image),r,Ng,Na,figID); gpuDevice(1);
354
+ else :
355
+ pass #kcMax, A0 = getDcorrSect(image,r,Ng,Na,figID)
356
+
357
+ # Local resolution map
358
+ tileSize = 200 # in pixels
359
+ tileOverlap = 0 # in pixels
360
+ figId = 103
361
+
362
+ if GPU :
363
+ pass # [kcMap,A0Map] = getLocalDcorr(gpuArray(image),tileSize,tileOverlap,r,Ng,figID);gpuDevice(1);
364
+ else :
365
+ pass # kcMap, A0Map = getLocalDcorr(image,tileSize,tileOverlap,r,Ng,figID)
366
+
367
+ return kcMax , A0
368
+
369
+
370
+ if (__name__ == '__main__' ):
371
+ kcMax , AO = main_image_decorr ()
372
+
373
+
374
+
375
+
376
+
377
+
378
+ print ("Guess we are done here" )
0 commit comments