insituTEM 0.1.6__py3-none-any.whl → 0.1.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,8 +2,8 @@
2
2
  """
3
3
 
4
4
  in-situ TEM Toolbox - PreProcess
5
- By: Meng and Michael
6
- Assembles of functions related to movie preprocess
5
+ By: Meng Li and Michael
6
+ Assembles of functions related to movie preprocess
7
7
  Example:
8
8
 
9
9
  import insitu_Preprocess as PP
@@ -18,7 +18,8 @@ import cv2
18
18
  from scipy import signal
19
19
  from PIL import Image
20
20
  import matplotlib.pyplot as plt
21
-
21
+ import tifffile
22
+ import tqdm
22
23
 
23
24
  def estimate_dup(A,B,threshold=1):
24
25
  """
@@ -66,44 +67,76 @@ def median_blur (score_list, i,thrs=150,wid=21):
66
67
  def detect_blur_fft(image, size=20, thresh=15,vis=False):
67
68
  """
68
69
  Function to detect if one frame is blurred using FFT
70
+ Example:
71
+ score,is_blur = PP.detect_blur_fft(image, size=20, thresh=15,vis=False)
72
+ Input:
69
73
  image: grayscale image, default size: 128*128 px
70
- size: filter size to get the background of FFT
74
+ size: filter size to get the background of FFT
71
75
  thresh: threshold value for blur scores, smaller score, more blurry
72
-
76
+ Output:
77
+ mean: mean value of the frame
78
+ is_blur: whether the frame is blur
73
79
  """
80
+ from insituTEM import insitu_DP as DP
74
81
  # grab the dimensions of the image and use the dimensions to derive the center (x, y)-coordinates
75
- (h, w) = image.shape
76
- (cX, cY) = (int(w / 2.0), int(h / 2.0))
77
- # compute the FFT to find the frequency transform, then shift
78
- # the zero frequency component (i.e., DC component located at
79
- # the top-left corner) to the center where it will be more
80
- # easy to analyze
81
- fft = np.fft.fft2(image)
82
- fftShift = np.fft.fftshift(fft)
83
- magnitude = 20 * np.log(np.abs(fftShift))
82
+ # h, w = image.shape
83
+
84
+
85
+ magnitude=DP.getFFT(image)
86
+ h,w = magnitude.shape
87
+ cX, cY = w //2, h//2
88
+ bar=int(h/100)
89
+ center=bar*10
90
+ #use only the center of the FFT
91
+ crop_h,crop_w=(h-cX)//2, (w-cY)//2
92
+
93
+
84
94
  # compute the background of FFT to make the diffraaction spots more obvious
85
95
  bg = cv2.blur(magnitude,(size,size))
86
96
 
87
97
  enhanced =cv2.subtract(magnitude, bg)
98
+ #remove noise by mean
99
+ # enhanced=enhanced[crop_h:(crop_h+cY),crop_w:(crop_w+cX)]
100
+
88
101
  #remove white noise from the substracted image
89
- enhanced[enhanced<30]=0
90
- #remove center spot
91
- enhanced[cY - 10:cY + 10, cX - 10:cX + 10]=0
102
+ enhanced[enhanced<20]=0
103
+
104
+ # Check the data type and convert if necessary
105
+ if enhanced.dtype != np.uint8:
106
+ # Normalize the image to the range [0, 255] if it has a different range
107
+ enhanced = cv2.normalize(enhanced, None, 0, 255, cv2.NORM_MINMAX)
108
+ # Convert the image to uint8
109
+ enhanced = enhanced.astype(np.uint8)
110
+
111
+ # Apply median filter
112
+ enhanced = cv2.medianBlur(enhanced, 3)
113
+
114
+ # enhanced = cv2.medianBlur(enhanced, 3)
115
+ # #remove center spot
116
+ enhanced[(cY - center): (cY + center), cX - center:cX + center] =0
117
+ enhanced[(cY - bar): (cY + bar), :]=0
118
+ enhanced[:, (cX - bar): (cX + bar)]=0
119
+ # enhanced[
120
+
121
+
122
+ croppedFFT=enhanced[crop_h:(crop_h+cY),crop_w:(crop_w+cX)]
92
123
 
93
124
  if vis:
94
- (fig, ax) = plt.subplots(1, 2, )
125
+ (fig, ax) = plt.subplots(1, 2,figsize=(10, 5) )
95
126
  ax[0].imshow(image, cmap="gray")
96
127
  ax[0].set_title("Input")
97
- ax[0].set_xticks([])
98
- ax[0].set_yticks([])
128
+ # ax[0].set_xticks([])
129
+ # ax[0].set_yticks([])
99
130
  # display the magnitude image
100
- ax[1].imshow(enhanced,cmap="viridis")
131
+ ax[1].imshow(croppedFFT,cmap="viridis")
101
132
  ax[1].set_title("Filtered FFT")
102
- ax[1].set_xticks([])
103
- ax[1].set_yticks([])
133
+ # ax[1].set_xticks([])
134
+ # ax[1].set_yticks([])
135
+
104
136
  # show our plots
105
137
  plt.show()
106
- mean = np.mean(enhanced)*1000
138
+ # mean = np.mean(enhanced)*1000
139
+ mean = np.mean(croppedFFT)*1000
107
140
  # print(mean)
108
141
  # the image will be considered "blurry" if the mean value of the magnitudes is less than the threshold value
109
142
  return (mean,mean<thresh)
@@ -198,4 +231,175 @@ def removeDPs(img,DP):
198
231
  else:
199
232
  for j in range(nDP):
200
233
  position=DP[j]
201
- removeDP(img,position)
234
+ removeDP(img,position)
235
+
236
+
237
+ def BlurDetection(path,wid=31):
238
+ """
239
+ Function to remove blurry frames based on the blur score
240
+ Input: tif file path
241
+ Output: deblurred tif stack
242
+ """
243
+ from insituTEM import insitu_IO as IO
244
+
245
+ indexout=path[:-4]+'_DB-index.csv'
246
+ DBout=path[:-4]+'_DB.csv'
247
+ DBout2=path[:-4]+'_Blur.csv'
248
+
249
+ stack = tifffile.imread(path)
250
+ nFrames,h,w = stack.shape #make sure the order of h and w!
251
+ index = []#index of remaining frames
252
+ score = []
253
+
254
+ print("------------------------------------------")
255
+ print("Calculating blur scores!")
256
+
257
+ for i in tqdm.tqdm(range(nFrames)):
258
+ fr=stack[i]
259
+ s = blur_score(fr)
260
+ score.append(s)
261
+ index.append(i)
262
+
263
+ length = len(score)
264
+ Blur=np.zeros((length,3))#[i,blur_score,blur_th]
265
+ Blur[:,0]=index
266
+ Blur[:,1]=score
267
+
268
+ plt.plot(score,'gray')
269
+ plt.show()
270
+
271
+ print("------------------------------------------")
272
+ print("Check blur detection!")
273
+
274
+ thrs=int(input( 'Input blur threshold(default: 70): '))
275
+ while thrs!=0:
276
+ index2=[]
277
+
278
+ for i in tqdm.tqdm(range(len(score))):
279
+ medthres,is_blur=median_blur (score, i,thrs,wid=wid)#wid must be odd
280
+ # DB[index[i],3]=is_blur
281
+ Blur[i,2]=medthres
282
+ if is_blur == 0:
283
+ index2.append(index[i])
284
+
285
+ plt.plot(Blur[:,0],Blur[:,1],'gray',Blur[:,0],Blur[:,2]-thrs,'r',Blur[:,0],Blur[:,2]+thrs,'r')
286
+ plt.show()
287
+ thrs=int(input( 'Press 0 if you are satisfied, press corrected threshold if you want to change: '))
288
+
289
+ IO.writeCSV(DBout2,Blur)
290
+
291
+ result= np.zeros((len(index2),2))
292
+ for i in range(len(index2)):
293
+ result[i,0]=i
294
+ result[i,1]=index2[i]
295
+
296
+ IO.writeCSV(indexout,result)
297
+
298
+ print("------------------------------------------")
299
+ print("Save blur removed file")
300
+ pathout2=path[:-4]+'_DBlur.tif'
301
+
302
+ with tifffile.TiffWriter(pathout2,bigtiff=True) as tif:
303
+ for j in tqdm.tqdm(range(len(index2))):
304
+ i=int(result[j,1])
305
+ fr=stack[i]
306
+
307
+ tif.write(fr, contiguous=True)
308
+ print("------------------------------------------")
309
+ print("Blur removed!")
310
+ print("==========================================")
311
+
312
+
313
+ def movie_preprocess(path,remove_DP=True,DP=[[0, 0, 1, 1],[0,0,2,2]],Crop=True,cropboarder=[0,0,0,0],Trim=False,start_time_mmss="00:00",end_time_mmss="00:00",grayscale=True,exp_time=0):
314
+ """
315
+ Function to preprocess the raw TEM movie to tiff
316
+ Input:
317
+ path: file path of the movie
318
+ remove DP: if there are constant dead point in the movie to remove,
319
+ if so, input the DP value.
320
+ Crop: if crop the movie to remove the boarders
321
+ if so, input the cropboarder: [left, top, right, bottom]
322
+ Trim: if trim the movie length
323
+ if so, input the start and end time in mm:ss
324
+ grayscale: if convert the movie to grayscale
325
+ exp_time: if remove the duplicated frame based on the real exposure time.
326
+ if no need to remove duplicates, put exp_time = 0
327
+ """
328
+ # print("=========================================")
329
+ print("ETEM movie preprocessor start!")
330
+
331
+ import moviepy.editor as mp
332
+ import moviepy.video.fx.all as vfx
333
+ from insituTEM import insitu_IO as IO
334
+
335
+
336
+ video = mp.VideoFileClip(path)
337
+ if Trim == True:
338
+ # Convert mm:ss to seconds
339
+ start_time_seconds = sum(x * int(t) for x, t in zip([60, 1], start_time_mmss.split(":")))
340
+ end_time_seconds = sum(x * int(t) for x, t in zip([60, 1], end_time_mmss.split(":")))
341
+
342
+ video = video.subclip(start_time_seconds, end_time_seconds)# cut the clip between t=0 and 28 secs.
343
+
344
+ fps = int(video.fps)
345
+ # fps= 15
346
+ w = int(video.w)
347
+ h = int(video.h)
348
+ nFrames = int(fps*video.duration)
349
+
350
+ print("fps=", fps, " w =",w, " h=", h, "duration= ",video.duration)
351
+ print("Total number of Frames=", nFrames)
352
+
353
+
354
+
355
+ #Preview first frame
356
+ print("------------------------------------------")
357
+ print("Preview the processed frame: press 0 if you want to continue: ")
358
+
359
+ if Crop == True:
360
+ video = video.fx(vfx.crop, x1=cropboarder[0], y1=cropboarder[1], x2=w-cropboarder[2], y2=h-cropboarder[3])#crop movie snapshot
361
+
362
+ fr = video.get_frame(mp.cvsecs(1/fps))
363
+
364
+ if grayscale==True:
365
+ fr = cv2.cvtColor(fr, cv2.COLOR_BGR2GRAY)
366
+
367
+ if remove_DP==True:
368
+ removeDPs(fr,DP)
369
+
370
+ IO.showFr(fr)
371
+ prompt = input("Input 0 if you want to continue, other keys to break :")
372
+
373
+ if prompt != "0":
374
+ print("Stopped by user. Modify the cropboarder values and restart.")
375
+ return
376
+ else:
377
+ #continue to apply to the full movie
378
+ #remove duplicate frames with known fps conversion
379
+ if exp_time==0:
380
+ dup=1
381
+ else:
382
+ dup= fps*exp_time
383
+
384
+ nFramesOut=int(nFrames/dup)
385
+ print ('nFramesOut= ', nFramesOut)
386
+ print('nFramesIn= ',nFrames)
387
+
388
+
389
+ pathout=path[:-4]+'_CutDB.tif'
390
+
391
+ print("------------------------------------------")
392
+ print("Saving duplicate removed processed frames~")
393
+
394
+
395
+ with tifffile.TiffWriter(pathout,bigtiff=True) as tif:
396
+ for j in tqdm.tqdm(range(nFramesOut)):
397
+ i=j*dup
398
+ fr = video.get_frame(mp.cvsecs(i/fps))
399
+ if grayscale==True:
400
+ fr = cv2.cvtColor(fr, cv2.COLOR_BGR2GRAY)
401
+ if remove_DP==True:
402
+ removeDPs(fr,DP)
403
+ tif.write(fr, contiguous=True)
404
+
405
+ print("Conversion done!")
@@ -10,7 +10,7 @@ Example:
10
10
  Al.get_matrix()
11
11
 
12
12
  Created on Tue Jun 11 17:22:45 2019
13
- By: Michael and Meng
13
+ By: Meng Li and Michel
14
14
  """
15
15
 
16
16
 
@@ -20,9 +20,9 @@ import cv2
20
20
  from skimage import io #package for TIFF stack reading
21
21
  import tifffile
22
22
  from scipy import signal
23
- from tqdm import tqdm
24
-
25
-
23
+ import tqdm
24
+ import matplotlib.pyplot as plt
25
+ from insituTEM import insitu_IO as IO
26
26
 
27
27
 
28
28
  def get_path():
@@ -59,7 +59,7 @@ Please choose the csv you want to use
59
59
  return dx, dy, csvpath
60
60
 
61
61
 
62
- def Adaptive_template_match(path, NOF, csvout=True, TMout=True, TMdenoise=True, TMdenoise_window=5,extend=True, bg = 150):
62
+ def Adaptive_template_match(path, NOF = 50, csvout=True, TMout=True, TMdenoise=True, TMdenoise_window=5,extend=True, bg = 150):
63
63
  '''
64
64
  Function to produce adaptive template matching on tiff image stack based on ROI selection
65
65
  input:
@@ -85,8 +85,8 @@ def Adaptive_template_match(path, NOF, csvout=True, TMout=True, TMdenoise=True,
85
85
  import tifffile
86
86
  import easygui
87
87
  import tqdm
88
- import insitu_IO as IO
89
- import insitu_alignment as AL
88
+ from insituTEM import insitu_IO as IO
89
+ # from insituTEM import insitu_alignment as AL
90
90
 
91
91
  ###############################################################
92
92
  ## 1. Inital settings
@@ -109,7 +109,10 @@ def Adaptive_template_match(path, NOF, csvout=True, TMout=True, TMdenoise=True,
109
109
  # Display cropped image
110
110
  cv2.imshow("Template, press ENTER to confirm", template)
111
111
  cv2.waitKey(0)
112
- cv2.destroyWindow("Template, press ENTER to confirm")
112
+ # cv2.destroyWindow("Template, press ENTER to confirm")
113
+ cv2.destroyAllWindows()
114
+ for _ in range(5):
115
+ cv2.waitKey(1)
113
116
 
114
117
 
115
118
 
@@ -118,30 +121,28 @@ def Adaptive_template_match(path, NOF, csvout=True, TMout=True, TMdenoise=True,
118
121
  meth='cv2.TM_CCOEFF_NORMED'
119
122
  method = eval(meth)
120
123
  w, h = template.shape[::-1]
121
-
122
- for i in tqdm.tqdm(range(nFrames)):
123
- fr=stack[i]
124
- # Apply template Matching
125
- res = cv2.matchTemplate(fr,template,method)
126
- min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
127
- top_left = max_loc
128
- TM[i,0]=i
129
- TM[i,1]=top_left[0]
130
- TM[i,2]=top_left[1]
131
- bottom_right = (top_left[0] + w, top_left[1] + h)
132
- cv2.rectangle(fr,top_left, bottom_right, 255, 2)
133
- # plt.imshow(fr,cmap = 'gray')
134
- # plt.title('Frame' +str(i)+' Detected Point')
135
- if i%NOF==NOF-1:
136
- template = fr[int(top_left[1]):int(top_left[1] + h), int(top_left[0]):int(top_left[0] + w)]#opencv coordinate: Y,x , from upper left corner of the image
137
- if TMout==True:
138
- if i == 0:
139
- tifffile.imwrite(pathout2,fr, append=False,bigtiff=True)
140
- else:
141
- # tiffile.imsave(pathout2,fr, append=True,bigtiff=True)
142
- tifffile.imwrite(pathout2,fr, append=True,bigtiff=True)
143
-
144
-
124
+
125
+ print("------------------------------------------")
126
+ print("Calculating drift~")
127
+ with tifffile.TiffWriter(pathout2,bigtiff=True) as tif:
128
+ for i in tqdm.tqdm(range(nFrames)):
129
+ fr=stack[i]
130
+ # Apply template Matching
131
+ res = cv2.matchTemplate(fr,template,method)
132
+ min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
133
+ top_left = max_loc
134
+ TM[i,0]=i
135
+ TM[i,1]=top_left[0]
136
+ TM[i,2]=top_left[1]
137
+ bottom_right = (top_left[0] + w, top_left[1] + h)
138
+ cv2.rectangle(fr,top_left, bottom_right, 255, 2)
139
+
140
+ if i%NOF==NOF-1:
141
+ template = fr[int(top_left[1]):int(top_left[1] + h), int(top_left[0]):int(top_left[0] + w)]#opencv coordinate: Y,x , from upper left corner of the image
142
+ if TMout==True:
143
+ tif.write(fr, contiguous=True)
144
+
145
+
145
146
  TM[:,1]=TM[0,1]-TM[:,1]
146
147
  TM[:,2]=TM[0,2]-TM[:,2]
147
148
 
@@ -149,7 +150,7 @@ def Adaptive_template_match(path, NOF, csvout=True, TMout=True, TMdenoise=True,
149
150
  #4. Apply TM to movie
150
151
  if TMdenoise==True:
151
152
  #Get average to minimize total movement
152
- TM=AL.denoiseTM(TM,TMdenoise_window)
153
+ TM=denoiseTM(TM,TMdenoise_window)
153
154
  Mx=int(np.mean(TM[:,1]))
154
155
  My=int(np.mean(TM[:,2]))
155
156
  TM[:,1]=TM[:,1]-Mx
@@ -162,9 +163,13 @@ def Adaptive_template_match(path, NOF, csvout=True, TMout=True, TMdenoise=True,
162
163
  if csvout==True:
163
164
  IO.writeCSV(pathout3,TM,fmt='%1.1d')
164
165
 
165
- AL.TranslateStack(path,TM,bg=bg, extend = extend)
166
+ TranslateStack(path,TM,bg=bg, extend = extend)
166
167
  print("Adaptive template matching done!")
167
- plt.show()
168
+ plt.show(block=False)
169
+ plt.pause(0.1)
170
+ plt.close()
171
+
172
+
168
173
 
169
174
 
170
175
  def TranslateStack(movie_path,matrix,bg=150,extend=True):
@@ -201,7 +206,7 @@ def TranslateStack(movie_path,matrix,bg=150,extend=True):
201
206
 
202
207
  #2d matrix flipped order of width and height to work with warpaffine method
203
208
  print("\nApplying translation to stack\n")
204
- with tifffile.TiffWriter(movie_pathout) as tif:
209
+ with tifffile.TiffWriter(movie_pathout,bigtiff=True) as tif:
205
210
 
206
211
  for num in tqdm(range(nframes)):
207
212
  temparray = img[num,:,:]
@@ -211,13 +216,6 @@ def TranslateStack(movie_path,matrix,bg=150,extend=True):
211
216
 
212
217
  extend_img = cv2.copyMakeBorder(temparray, top, bottom, left, right, cv2.BORDER_CONSTANT, value=bg)
213
218
  translated_img = cv2.warpAffine(extend_img,TM,(width,height),borderValue =bg)#fill with gray
214
- #Generates an image translated by dx and dy
215
- # if num == 0:
216
- # tifffile.imwrite(movie_pathout, translated_img, append=False, bigtiff=True)
217
- # #Overrides any previous files saved to the same path
218
- # else:
219
- # tifffile.imwrite(movie_pathout, translated_img, append=True, bigtiff=True)
220
- # #appends onto the tiff stack
221
219
  tif.write(translated_img, contiguous=True)
222
220
 
223
221
 
@@ -357,4 +355,181 @@ def template_match(imgpath, w=24):
357
355
  for num in iterate:
358
356
  TM[num,0] = dx[num]
359
357
  TM[num,1] = dy[num]
360
- IO.writeCSV(csvpathout,TM)
358
+ IO.writeCSV(csvpathout,TM)
359
+
360
+
361
+ def ATM_locglobal(path, NOF=50, csvout=True, TMout=True, TMdenoise=True, TMdenoise_window=5, extend=True, bg=150,search_margin_local=1, match_threshold=0.8):
362
+ '''
363
+ Function to produce adaptive template matching on TIFF image stack based on ROI selection with local and global selections
364
+
365
+ Input:
366
+ path: Image path for grayscale TIFF stack
367
+ NOF: Number of frames for template to grow
368
+ csvout: Whether to write the translation matrix
369
+ TMout: Whether to write the template match found feature
370
+ TMdenoise: Whether to denoise the measured matrix to remove sudden change
371
+ TMdenoise_window: Window size for TMdenoise
372
+ bg: Background color (0-255)
373
+ extend: Whether to extend the image for the translation (avoid crop)
374
+ match_threshold: Threshold for considering the new ROI position close to the previous one
375
+
376
+ Output:
377
+ Translated image stack
378
+ CSV file of translation matrix
379
+ Captured ROI location
380
+
381
+ Written by Meng Li (mona.mengli@gmail.com) 2024.07.06
382
+ '''
383
+
384
+ ###############################################################
385
+ # 1. Initial settings
386
+
387
+
388
+ import sys
389
+
390
+ try:
391
+ stack = tifffile.imread(path)
392
+ except OSError as e:
393
+ print(f"Error reading the TIFF file: {e}")
394
+ sys.exit(1)
395
+
396
+ # stack = tifffile.imread(path)
397
+ nFrames, h, w = stack.shape
398
+
399
+ TM = np.zeros((nFrames, 3)) # frame, TX, TY, max_val
400
+ pathout3 = path[:-4] + '_TM.csv'
401
+ pathout2 = path[:-4] + '_TM.tif'
402
+
403
+ ###############################################################
404
+ # 2. Open the first frame and select ROI for template matching
405
+ img = stack[0]
406
+
407
+ # Select ROI for template matching, returns x1,y1,w,h
408
+ r = cv2.selectROI("Select ROI, press ENTER to confirm", img, fromCenter=False, showCrosshair=False)
409
+ x1,y1,template_w,template_h=int(r[0]),int(r[1]),int(r[2]),int(r[3])
410
+ x2=x1+template_w
411
+ y2=y1+template_h
412
+
413
+ cv2.destroyWindow("Select ROI, press ENTER to confirm")
414
+
415
+ # Crop image to get the template
416
+ # template = img[int(r[1]):int(r[1] + r[3]), int(r[0]):int(r[0] + r[2])]
417
+ template=img[y1:y2,x1:x2]
418
+ # template_h, template_w = template.shape
419
+
420
+ # Display cropped image
421
+ cv2.imshow("Template, press ENTER to confirm", template)
422
+ cv2.waitKey(0)
423
+ cv2.destroyAllWindows()
424
+ cv2.waitKey(1)
425
+
426
+ ###############################################################
427
+ # 3. Apply template matching
428
+ method = cv2.TM_CCOEFF_NORMED
429
+
430
+ print("------------------------------------------")
431
+ print("Calculating drift~")
432
+
433
+ last_top_left = (x1,y1)
434
+
435
+ last_max_val = None
436
+
437
+
438
+
439
+ with tifffile.TiffWriter(pathout2, bigtiff=True) as tif:
440
+ for i in tqdm.tqdm(range(nFrames)):
441
+ fr = stack[i]
442
+
443
+ search_area_global=fr
444
+
445
+ # Apply global template matching
446
+ res_global = cv2.matchTemplate(search_area_global, template, method)
447
+ min_val_global, max_val_global, min_loc_global, max_loc_global = cv2.minMaxLoc(res_global)
448
+
449
+ global_top_left = max_loc_global
450
+
451
+
452
+ # Define the local search area around the last known ROI position
453
+ # search_margin_local = 1 # Local search margin
454
+ x1_local=int(x1-search_margin_local)
455
+ y1_local=int(y1-search_margin_local)
456
+ x2_local=int(x1+template_w+search_margin_local)
457
+ y2_local=int(y1+template_h+search_margin_local)
458
+ search_area_local = fr[y1_local:y2_local, x1_local:x2_local]
459
+ # Apply local template matching
460
+ res_local = cv2.matchTemplate(search_area_local, template, method)
461
+ min_val_local, max_val_local, min_loc_local, max_loc_local = cv2.minMaxLoc(res_local)
462
+
463
+ local_top_left = (x1_local + max_loc_local[0], y1_local + max_loc_local[1])
464
+
465
+
466
+
467
+ # # start_x_local = max(last_top_left[0] - search_margin_local, 0)
468
+ # # start_y_local = max(last_top_left[1] - search_margin_local, 0)
469
+ # # end_x_local=last_top_left[0]+template_w+search_margin_local
470
+ # # end_y_local = last_top_left[1] +template_h + search_margin_local
471
+ # # # end_x_local = min(last_top_left[0]+template_w + search_margin_local, w)
472
+ # # # end_y_local = min(last_top_left[1] +template_h + search_margin_local, h])
473
+
474
+ # # search_area_local = fr[start_y_local:end_y_local, start_x_local:end_x_local]
475
+
476
+ # # Apply local template matching
477
+ # res_local = cv2.matchTemplate(search_area_local, template, method)
478
+ # min_val_local, max_val_local, min_loc_local, max_loc_local = cv2.minMaxLoc(res_local)
479
+
480
+ # local_top_left = (start_x_local + max_loc_local[0], start_y_local + max_loc_local[1])
481
+
482
+ # Use the local match if the match value is within the threshold of the previous match
483
+ if last_max_val is not None and max_val_local >= max_val_global * match_threshold:
484
+ top_left = (local_top_left[0] , local_top_left[1])
485
+ max_val = max_val_local
486
+ else:
487
+ top_left = (global_top_left[0], global_top_left[1])
488
+ max_val = max_val_global
489
+
490
+ TM[i, 0] = i
491
+ TM[i, 1] = top_left[0]
492
+ TM[i, 2] = top_left[1]
493
+
494
+ # Update the last known position and match value
495
+ last_top_left = top_left
496
+ last_max_val = max_val
497
+
498
+ # Draw rectangle for visualization
499
+ bottom_right = (top_left[0] + template_w, top_left[1] + template_h)
500
+ cv2.rectangle(fr, top_left, bottom_right, 255, 2)
501
+
502
+ # Periodically update the template
503
+ if i % NOF == NOF - 1:
504
+ template = fr[top_left[1]:bottom_right[1], top_left[0]:bottom_right[0]]
505
+ template_h, template_w = template.shape
506
+
507
+ if TMout:
508
+ tif.write(fr, contiguous=True)
509
+
510
+ TM[:, 1] = TM[0, 1] - TM[:, 1]
511
+ TM[:, 2] = TM[0, 2] - TM[:, 2]
512
+
513
+ ###############################################################
514
+ # 4. Apply translation matrix to movie
515
+ if TMdenoise:
516
+ TM = denoiseTM(TM, TMdenoise_window)
517
+ Mx = int(np.mean(TM[:, 1]))
518
+ My = int(np.mean(TM[:, 2]))
519
+ TM[:, 1] -= Mx
520
+ TM[:, 2] -= My
521
+
522
+ print("------------------------------------------")
523
+ print("Saving files~")
524
+
525
+ plt.plot(TM[:, 0], TM[:, 1], 'b', TM[:, 0], TM[:, 2], 'r')
526
+
527
+ if csvout:
528
+ IO.writeCSV(pathout3, TM, fmt='%1.1d')
529
+
530
+ TranslateStack(path, TM, bg=bg, extend=extend)
531
+
532
+ print("Adaptive template matching done!")
533
+ plt.show()
534
+
535
+
@@ -0,0 +1,20 @@
1
+ Metadata-Version: 2.4
2
+ Name: insituTEM
3
+ Version: 0.1.7
4
+ Author: Meng Li
5
+ Requires-Python: >=3.9
6
+ Requires-Dist: numpy
7
+ Requires-Dist: scipy
8
+ Requires-Dist: matplotlib
9
+ Requires-Dist: pandas
10
+ Requires-Dist: tifffile
11
+ Requires-Dist: tqdm
12
+ Requires-Dist: opencv-python
13
+ Requires-Dist: pillow
14
+ Requires-Dist: scikit-image
15
+ Requires-Dist: moviepy
16
+ Requires-Dist: ncempy
17
+ Requires-Dist: easygui
18
+ Requires-Dist: pystackreg
19
+ Requires-Dist: pyside6
20
+ Dynamic: author
@@ -0,0 +1,12 @@
1
+ insituTEM/__ init __.py,sha256=L4AFZSmHZkQu6J-tlqBoTJaBFltRFZ5PArhk8pmDmco,283
2
+ insituTEM/insitu_DENS.py,sha256=q2ZGbAoPPfsWbG8XlQqTdJa5_VNUNvjR9FzG2J3KkP4,10865
3
+ insituTEM/insitu_DP.py,sha256=0HMGT7j9ndpYPAgXCNGHkZeg9yJ4KI4SMCim2kiG6C0,10930
4
+ insituTEM/insitu_Diff.py,sha256=EpCMuprigdJKXaFbg9kIGZi_msKRqIDmdqvA1yofTco,11951
5
+ insituTEM/insitu_EMraw.py,sha256=O7rwdQW4STkQlYr3yImnpJX_VqjIExHgFqFIoKblYYE,15347
6
+ insituTEM/insitu_IO.py,sha256=za4ow7DPnv_YgroD_3fH12neXwYjw717w8jPzCRQvqg,25554
7
+ insituTEM/insitu_Preprocess.py,sha256=xKnHnv8dc0gTHzzEPW_DivzzEJHNFSNGRD_r7UM2l6U,12779
8
+ insituTEM/insitu_alignment.py,sha256=duH383I-jSStKhy6l7mzy9yijSl7Elf4JDFfV8ilFzM,19595
9
+ insitutem-0.1.7.dist-info/METADATA,sha256=J88Jc0obYHWJp7-89Xab0ZdsSNkDRvWIc9v-RtKTgbs,438
10
+ insitutem-0.1.7.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
11
+ insitutem-0.1.7.dist-info/top_level.txt,sha256=DEgrwrdz6iV62_cukvjFXu4dnZYupwvS41QyvTfcqjs,10
12
+ insitutem-0.1.7.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.35.1)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,13 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: insituTEM
3
- Version: 0.1.6
4
- Summary: A package of tools for processing in situ TEM data
5
- Author: Meng Li
6
- Requires-Dist: tifffile
7
- Requires-Dist: moviepy
8
- Requires-Dist: tqdm
9
- Requires-Dist: numpy
10
- Requires-Dist: opencv-python
11
- Requires-Dist: scipy
12
- Requires-Dist: matplotlib
13
-