insituTEM 0.1.6__py3-none-any.whl → 0.1.8__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.
insituTEM/insitu_IO.py CHANGED
@@ -15,30 +15,28 @@ Update 20200303:
15
15
  Add stroke to scalebar and text
16
16
  """
17
17
 
18
- import moviepy.editor as mp
19
- #from moviepy.editor import concatenate_videoclips,ImageClip,VideoFileClip,vfx
18
+
20
19
  import cv2
21
20
  import tifffile
22
21
  import tqdm #not necessary just provides a progress bar and timer
23
22
  import numpy as np
24
23
 
25
24
 
26
- def tiff2mp4(path):
25
+ def tiff2mp4(path,fps):
27
26
  """
28
27
  function to convert any input file to H264 High quality mp4 using openCV
29
28
  Inputs: filepath
30
29
  Output: file in the same folder named '..._fps.mp4'
31
30
  """
32
31
  video = tifffile.imread(path)
33
- nFrames, h,w = video.shape
34
- fps = int(input('Input desired output fps:'))
32
+ nFrames, h,w = video.shape[:3]
35
33
  # dur=1/fps
36
34
  pathout =path[:-4]+'_'+str(fps)+'.mp4'
37
35
  # pathout2 =path[:-4]+'_St.tif'
38
36
  codec = cv2.VideoWriter_fourcc(*'H264')
39
37
  out = cv2.VideoWriter(pathout, codec , fps, (w, h))
40
38
  print("---------------------------------------------")
41
- print('Converting Tiff stack to the movie')
39
+ print('Converting Tiff stack to mp4')
42
40
  for i in tqdm.tqdm(range(nFrames)):
43
41
  img=video[i]
44
42
  out.write(img)
@@ -47,89 +45,133 @@ def tiff2mp4(path):
47
45
  print("==============================================")
48
46
  print("MP4 convertion Done!")
49
47
 
48
+ def tiff2avi(path,fps,is_color=False):
49
+ #convert tiff stack to movie
50
+ import tifffile
51
+ import cv2
52
+
53
+ # path =
54
+ stack = tifffile.imread(path)
55
+ nFrames,h,w = stack.shape[:3]
56
+
57
+ # # fps = int(input('Input desired output fps:'))
58
+ # # dur=1/fps
59
+ # pathout =path[:-4]+'_'+str(fps)+'.avi'
60
+
61
+
62
+ # codec = cv2.VideoWriter_fourcc(*'MJPG')
63
+
64
+ # video_out = cv2.VideoWriter(pathout, codec , fps, (w, h))
65
+ # print("---------------------------------------------")
66
+ # print('Converting Tiff stack to avi')
67
+ # for i in tqdm.tqdm(range(nFrames)):
68
+ # img=stack[i]
69
+ # video_out.write(img)
70
+
71
+ # video_out.release()
72
+ # cv2.destroyAllWindows()
73
+ # print("==============================================")
74
+ # print("AVI convertion Done!")
75
+ size=(int(w),int(h))
50
76
 
51
77
 
52
- # print("---------------------------------------------")
53
- # print('Done! Enjoy~')
54
- # def f2mp4(path,fps,is_gray=1):
55
- # """
56
- # function to convert any input file to H264 High quality mp4
57
- # Inputs: filepath, output fps,is_gray: 1 for grayscale, 0 for rgb
58
- # Output: file in the same folder named '..._cv.mp4'
59
- # """
60
-
61
- # print("==============================================")
62
- # print("Convert file to MP4!")
63
- # pathout = path[:-4]+'_'+str(fps)+'.mp4'
64
- # if path.endswith('.tif'):
65
- # # import tifffile
66
- # im = tifffile.imread(path)
67
- # if is_gray == 1:
68
- # nFrames, h,w = im.shape
69
- # else:
70
- # nFrames, h,w,c = im.shape
71
- # fps=int(input("Enter desired fps: "))
72
- # dur=1/fps
73
- # clip = []
74
- # print("---------------------")
75
- # print("Read TIF file!")
76
- # for i in tqdm.tqdm(range(nFrames)):
77
- # if is_gray ==1:
78
- # fr = cv2.cvtColor(im[i],cv2.COLOR_GRAY2RGB)
79
- # else:
80
- # fr=im[i]
81
- # clip.append(mp.ImageClip(fr).set_duration(dur))
82
- # video = mp.concatenate_videoclips(clip, method="compose",ismask=False)#ismask=True to make grayscale
83
-
84
- # else:
85
- # video = mp.VideoFileClip(path)
86
- # fpsIn = int(video.fps)
87
- # if fps != fpsIn:
88
- # print("Conflict in fps! \n", "[0] Use fps of input file;\n", "[1] Use desired fps w/o speedup;\n",
89
- # "[2] Use desired fps w/ speedup:")
90
- # k = input('Input your selection: ')
91
- # if k == 2:
92
- # sf = fps/fpsIn
93
- # video =video.fx(mp.vfx.speedx, sf)
94
- # elif k == 0:
95
- # fps = fpsIn
96
- # video.reader.close()# To fix handel error problem
97
- # print("---------------------")
98
-
99
- # print("Save to mp4!")
100
- # video.write_videofile(pathout, fps=fps,codec='libx264', bitrate='32 M',preset='ultrafast')
101
-
102
- # print("==============================================")
103
- # print("MP4 convertion Done!")
104
-
105
-
106
- def f2tif(path,is_gray=1):
107
- """
108
- function to convert any input file to tif stack
109
- Inputs: filepath, is_gray: 1 for grayscale, 0 for rgb
78
+ pathout =path[:-4]+'_'+str(fps)+'.avi'
79
+
80
+ # # Check if the image stack is grayscale or color
81
+ is_color = len(stack.shape) == 4 and stack.shape[3] == 3
82
+
83
+ codec = cv2.VideoWriter_fourcc(*'MJPG')
84
+ video_out = cv2.VideoWriter(pathout, codec , fps, size,isColor=is_color)
85
+ print("---------------------------------------------")
86
+ print('Converting Tiff stack to avi')
87
+ for i in tqdm.tqdm(range(nFrames)):
88
+ img=stack[i]
89
+
90
+ # Ensure the image is in 8-bit format
91
+
92
+ if img.dtype != np.uint8:
93
+ img = cv2.normalize(img, None, 0, 255, cv2.NORM_MINMAX)
94
+ img = np.uint8(img)
95
+ # Convert RGB to BGR if the image is in color
96
+ if is_color ==True:
97
+ img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
98
+ # else:
99
+ # img = cv2.normalize(img, None, 0, 255, cv2.NORM_MINMAX)
100
+ # img = np.uint8(img)
101
+ # Convert RGB to BGR if the image is in color
102
+
103
+
104
+ video_out.write(img)
105
+
106
+ video_out.release()
107
+ cv2.destroyAllWindows()
108
+ print("==============================================")
109
+ print("AVI convertion Done!")
110
+
111
+ def movie2tif(path,is_gray=1,exp_time=0.2):
112
+ """
113
+ function to convert any input movie file to tif stack
114
+ Inputs: filepath of movie, is_gray: 1 for grayscale, 0 for rgb
115
+ exp_time= exposure time of real movie, remove dup frame if fps > exp_time
110
116
 
111
117
  Output: file in the same folder named '..._cv.tif'
112
118
  """
113
- # import tifffile
119
+ import moviepy.editor as mp
120
+ import tifffile
114
121
  import tqdm
115
122
  print("==============================================")
116
123
  print("Convert file to tif stack!")
117
124
  pathout = path[:-4]+'_'+str(is_gray)+'.tif'
118
125
  video = mp.VideoFileClip(path)
119
- i=0
120
- for fr in tqdm.tqdm(video.iter_frames()):
121
- if is_gray == 1:
122
- fr= cv2.cvtColor(fr, cv2.COLOR_BGR2GRAY)
123
- if i == 0:
124
- tifffile.imwrite(pathout,fr, append=False)
125
- else:
126
- tifffile.imwrite(pathout,fr, append=True)
127
- i += 1
126
+ fps = int(video.fps)
127
+ w = int(video.w)
128
+ h = int(video.h)
129
+ nFrames = int(fps*video.duration)
130
+ dup= fps*exp_time
131
+ nFramesOut=int(nFrames/dup)
132
+ with tifffile.TiffWriter(pathout,bigtiff=True) as tif:
133
+ for j in tqdm.tqdm(range(nFramesOut)):
134
+ i=int(j*dup)
135
+ fr = video.get_frame(mp.cvsecs(i/fps))
136
+ if is_gray==1:
137
+ fr = cv2.cvtColor(fr, cv2.COLOR_BGR2GRAY)
138
+ tif.write(fr, contiguous=True)
139
+
140
+
141
+ video.reader.close()
142
+ # for fr in tqdm.tqdm(video.iter_frames()):
143
+ # if is_gray==1:
144
+ # fr = cv2.cvtColor(fr, cv2.COLOR_BGR2GRAY)
145
+ # tif.write(fr,continuous=True)
146
+
128
147
  print("==============================================")
129
148
  print("TIF convertion Done!")
130
- print("nFrames="+str(i))
131
149
  video.reader.close()# To fix handel error problem
132
150
 
151
+ def folder2tif(path,isGray=True):
152
+ """
153
+ Function to convert folder of single images into tif stack
154
+ Input: path: folder path
155
+ Output: tif stack with the same name as the folder in the parent folder.
156
+ """
157
+ import tifffile
158
+ img_name=os.listdir(path)
159
+ nFrames= len(img_name)
160
+ pathout=path+'.tif'
161
+ if movieout == True:
162
+ video_out.write(img)
163
+
164
+ with tifffile.TiffWriter(pathout,bigtiff=True) as tif:
165
+ for i in tqdm.tqdm(range(nFrames)):
166
+ # img_name = f'{i:03d}.tif'
167
+ compare_path=os.path.join(path,f'{i:03d}.tif')
168
+ overlay =cv2.imread(compare_path)
169
+ if isGray==True:
170
+ overlay = cv2.cvtColor(overlay,cv2.COLOR_BGR2GRAY)
171
+ else:
172
+ overlay = cv2.cvtColor(overlay, cv2.COLOR_BGR2RGB) #tifffile usedRGB, cv2 used BGR
173
+
174
+ tif.write(overlay, contiguous=True)
133
175
 
134
176
  def f2gif(path,fps):
135
177
  """
@@ -165,8 +207,8 @@ def f2gif(path,fps):
165
207
  elif k == 0:
166
208
  fps = fpsIn
167
209
 
168
- video.write_gif(pathout,fps=fps)
169
- video.reader.close()# To fix handel error problem
210
+ video.write_gif(pathout,fps=fps)
211
+ video.reader.close()# To fix handel error problem
170
212
  # if path.endswith('.gif'):
171
213
  # clip.write_videofile(pathout,fps=fps,codec='libx264', bitrate='32 M',preset='ultrafast')
172
214
  print("==============================================")
@@ -295,22 +337,96 @@ def ExtractFrame(path,framelist,is_gray=1):
295
337
  if path.endswith('.tif')==0:
296
338
  video.reader.close()
297
339
 
298
-
299
340
  def writeCSV(pathout,data,fmt='%1.1d'):
300
341
  # import csv
301
342
  import numpy as np
302
343
  # (length,width)=np.shape(data)
303
344
  np.savetxt(pathout, data, fmt=fmt, delimiter=",")
304
-
305
- #
306
- #def Time2List()
345
+
307
346
  def showFr(im):
308
347
  from PIL import Image
309
348
  img = Image. fromarray(im)
310
349
  img.show()
350
+
351
+ #functions for scalebar
352
+ def readscale(path,dy=5):
353
+ """
354
+ Function to measure scale from movie first frame
355
+ Input: path - movie path; dy: shift from the bottom in px
356
+ scalebarcolr- 0 for black, 255 for white
357
+ """
358
+ import os
359
+ os.environ["IMAGEIO_FFMPEG_EXE"] = "/opt/homebrew/bin/ffmpeg"
360
+ import moviepy.editor as mp
361
+ import cv2
311
362
 
363
+ video = mp.VideoFileClip(path)
364
+ fr = video.get_frame(mp.cvsecs(0))
365
+ fr = cv2.cvtColor(fr, cv2.COLOR_BGR2GRAY)
366
+
367
+ # Select ROI using cv2.selectROI()
368
+ roi = cv2.selectROI('Select scalebar ROI, quit with SPACE', fr)
369
+ cv2.waitKey(10)
370
+ cv2.destroyWindow('Select scalebar ROI, quit with SPACE')
371
+
372
+ # Crop the image based on the selected ROI
373
+ cropped_image = fr[int(roi[1]):int(roi[1] + roi[3]), int(roi[0]):int(roi[0] + roi[2])]
374
+
375
+ # # # Display the cropped image
376
+ showFr(cropped_image)
377
+
378
+ import numpy as np
312
379
 
313
- def AddScale(img,barLen =2, scale = 34.5, px=0.02,py=0.96, color = 255,thick=5,lw=1,stroke=1):
380
+ scalebar_color = int(input("Input the scalebar color, 0-black, 255-white: "))
381
+ dy2=dy
382
+ while dy2 != 0:
383
+ print(cropped_image[-dy,:])
384
+ dy2=int(input("input 0 if the crop is correct, otherwise input the estimated distance from bottom to the scalebar: "))
385
+ if dy2 !=0:
386
+ dy=dy2
387
+
388
+ scalebar_px = np.count_nonzero(cropped_image[-dy,:]==scalebar_color)
389
+ print("scalebar_px=", scalebar_px)
390
+ scale_nm = int(input("Input the scalebar in nm: "))
391
+ scale =scalebar_px/scale_nm
392
+ print("==============")
393
+ print("scale=",scale,"px/nm")
394
+ return scale
395
+
396
+ def getScalePix(scale,barLenPix=250):
397
+ """
398
+ Function to convert truescale into str with correct format
399
+ Input:
400
+ barLenPix : pixel length of the scalebar region
401
+ scale: scale: px/nm
402
+ Output:
403
+ text: string of the scalebar text, in the format such as 100, 200, 500 nm .
404
+ scalepix: pixel distance of the realoutput scalebar
405
+ """
406
+ truescale= barLenPix/scale
407
+
408
+ # Find the nearest power of 10 to the truescale
409
+ nearest_power = 10 ** np.floor(np.log10(truescale))
410
+
411
+ # Determine the most appropriate scale bar value
412
+ if truescale >= 5 * nearest_power:
413
+ scalebar = 5 * nearest_power
414
+ elif truescale >= 2 * nearest_power:
415
+ scalebar = 2 * nearest_power
416
+ else:
417
+ scalebar = nearest_power
418
+
419
+ # Calculate the scale in pixels
420
+ scalepix = int(scalebar * scale)
421
+
422
+ # Determine the appropriate unit for the scale bar text
423
+ if scalebar >= 1000:
424
+ text = f"{int(scalebar/1000)} um"
425
+ else:
426
+ text = f"{int(scalebar)} nm"
427
+ return scalepix, text
428
+
429
+ def AddScalePix(img,barLenPix =250, scale = 34.5, px=0.02,py=0.96, barthick=5,lw=1,stroke=True,tscale=1,textThick=4):
314
430
  """
315
431
  Function to add scale to image
316
432
  Input:
@@ -322,54 +438,214 @@ def AddScale(img,barLen =2, scale = 34.5, px=0.02,py=0.96, color = 255,thick=5,l
322
438
  stroke=1: add stroke; stroke=0 No stroke
323
439
 
324
440
  """
441
+ import cv2
325
442
  h,w=img.shape
326
- w_scale=int(scale*barLen)
443
+
444
+ scalepix, text = getScalePix(barLenPix, scale)
445
+
446
+ # w_scale=int(scale*barLen)
327
447
  x1=int(w*px)
328
448
  y1=int(h*py)
329
- x2=x1+w_scale
330
- y2=y1+thick
449
+ x2=x1+scalepix
450
+ y2=y1+barthick
451
+
452
+
453
+ #find bcakground color and make the reverse as scalebar color
454
+ img_bg=img[y1:y2,x1:x2]
455
+ mean_intensity=np.mean(img_bg)
456
+
457
+ if mean_intensity<128:
458
+ color = 255
459
+ else:
460
+ color = 0
461
+
331
462
 
332
463
  bcolor=255-color
333
-
334
-
335
-
336
-
337
- text = str(barLen)+' nm'
464
+
338
465
  font = cv2.FONT_HERSHEY_SIMPLEX#CV_FONT_HERSHEY_SIMPLEX normal size sans-serif font
339
- if stroke == 1:
340
- cv2.putText(img,text,(x1,y1-8), font, 1, bcolor, 3, cv2.LINE_AA) #Stroke
466
+ if stroke == True:
467
+ cv2.putText(img,text,(x1,y1-8), font, tscale, bcolor,int(textThick+lw), cv2.LINE_AA) #Stroke
341
468
  cv2.rectangle(img,(x1,y1),(x2,y2),bcolor,2)#boarder color
342
469
 
343
470
 
344
471
  cv2.rectangle(img,(x1,y1),(x2,y2),color,-1)
345
472
 
346
- cv2.putText(img,text,(x1,y1-8), font, 1, color, 2, cv2.LINE_AA)
473
+ cv2.putText(img,text,(x1,y1-8), font,tscale, color, textThick, cv2.LINE_AA)
474
+
475
+ def AddScale(img,barLen =2, scale = 34.5, px=0.02,py=0.96, color = 255,fontScale=1.5, barthick=5,textthick=2,stroke=1):
476
+ """
477
+ Function to add scale to image
478
+ Input:
479
+ img: greyscale image
480
+ barLen: desired scale length
481
+ scale: scale of the image: px/nm: 1000kX- 49.5; 700kX - 34.5
482
+ (px,py): position of the scale bar: r(0-1)
483
+ color: color of the scalebar
484
+ stroke=1: add stroke with thickness, stroke=0 No stroke
485
+
486
+ fontScale: scale of the text, default is 1.
487
+ barthick: scalebar thickness
488
+ textthick: thickness of the text without stroke
347
489
 
348
- def AddText(img,text, px=0.98,py=0.96, color = 255,s=0.9,lw=1,stroke=1):
490
+ """
491
+ h,w=img.shape
492
+ w_scale=int(scale*barLen)
493
+ x1=int(w*px)
494
+ y1=int(h*py)
495
+ x2=x1+w_scale
496
+ y2=y1+barthick
497
+
498
+ bcolor=255-color
499
+
500
+ text = str(barLen)+' nm'
501
+ font = cv2.FONT_HERSHEY_SIMPLEX#CV_FONT_HERSHEY_SIMPLEX normal size sans-serif font
502
+ shifty=int(8*fontScale)
503
+ if stroke != 0:
504
+ strokethick = int(stroke + textthick)
505
+ rectangle_thickness = max(1, strokethick // 2) # halve it for visual match
506
+ cv2.putText(img, text, (x1, y1 - shifty), font, fontScale, bcolor, strokethick, lineType=cv2.LINE_AA) # Stroke
507
+ cv2.rectangle(img, (x1, y1), (x2, y2), bcolor, rectangle_thickness) # Border color
508
+
509
+ cv2.rectangle(img, (x1, y1), (x2, y2), color, -1)
510
+ cv2.putText(img, text, (x1, y1 - shifty), font, fontScale, color, textthick, cv2.LINE_AA)
511
+
512
+ def AddText(img,text, px=0.98,py=0.96, color = 255,fontScale=0.9,thickness=2,stroke=1):
349
513
  """
350
514
  Function to add text str to image
351
515
  Input:
352
516
  img: greyscale image
353
517
  text: textstr to display
354
518
  (px,py): position of the text: right,middle corner
355
- lw: boarder of the text
356
- stroke=1: add stroke; stroke=0 No stroke
519
+ fontScale: scale of the text
520
+ thickness: line thickness of the text
521
+
522
+ stroke=1: add stroke width of 1; stroke=0 No stroke
357
523
 
358
524
  """
359
525
  h,w=img.shape
360
526
 
361
527
  font = cv2.FONT_HERSHEY_SIMPLEX#CV_FONT_HERSHEY_SIMPLEX normal size sans-serif font
362
- D,sd=cv2.getTextSize(text, font, s, lw)
528
+ D,sd=cv2.getTextSize(text, font, fontScale,thickness)
363
529
  wt=int(D[0])
364
530
  bcolor=255-color #color of stroke
365
- bw =lw+1 #stroke thickness
531
+ # bw =lw+1 #stroke thickness
532
+ strokethick=thickness+stroke
366
533
 
367
534
  x=int(w*px-wt)
368
535
  y=int(h*py)
369
- if stroke == 1:
370
- cv2.putText(img,text,(x,y), font, s, bcolor, bw, cv2.LINE_AA) #Stroke
371
- cv2.putText(img,text,(x,y), font, s, color, lw, cv2.LINE_AA)
536
+ if stroke !=0:
537
+ cv2.putText(img,text,(x,y), font, fontScale, bcolor, strokethick, cv2.LINE_AA) #Stroke
538
+ cv2.putText(img,text,(x,y), font, fontScale, color, thickness, cv2.LINE_AA)
539
+
540
+ def AddScaleTime2Stack(path,bar,Scale,dt=0.2,fps=15,color=255, time_txt_scale=1.2,textthick=2,stroke=1):
541
+ """
542
+ Function to add scalebar and timestamp to stack
543
+ Input:
544
+ path: path to tiff stack
545
+ bar: scale bar to show in nm
546
+ Scale: scale for the image stack: px/nm
547
+ dt: time interval of each frame
548
+ others: parameters for adjusting scalebar text size
549
+ Output:
550
+ Tiff stack and avi movie of the added scale&time
551
+
552
+ Example:
553
+ AddScaleTime2Stack(path,bar=20,Scale=22.2,dt=0.5,fps=15,color=255, time_txt_scale=1.2)
554
+
555
+ """
556
+ stack=tifffile.imread(path)
557
+ nFrames, h,w = stack.shape
558
+
559
+ pathout =path[:-4]+'_St.tif'
560
+
561
+ print("---------------------------------------------")
562
+ print('Testing positions! ')
563
+ fr=stack[0]
564
+ px=0.96
565
+ py=0.96
566
+
567
+ text='0.0 s'
568
+ AddScale(fr,barLen=bar,fontScale=time_txt_scale,scale=Scale,color=color,textthick=textthick,stroke=stroke)
569
+ AddText(fr,text,px=px,py=py,fontScale=time_txt_scale,color=color,thickness=textthick,stroke=stroke)
570
+ showFr(fr)
372
571
 
572
+ prompt = input("Check the position, press 0 if you are satisfied, any other key to exit: ")
573
+ print("---------------------------------------------")
574
+
575
+ if prompt == "0":
576
+ print("Adding scalebar and timestamp to full stack")
577
+ with tifffile.TiffWriter(pathout,bigtiff=True) as tif:
578
+
579
+ for i in tqdm.tqdm(range(nFrames)):
580
+ img=stack[i]
581
+ time = i * dt
582
+ text=str('%02.1f' %time)+' s'
583
+ AddScale(img,barLen=bar,fontScale=time_txt_scale,scale=Scale,color=color,textthick=textthick,stroke=stroke)
584
+ AddText(img,text,px=px,py=py,fontScale=time_txt_scale,color=color,thickness=textthick,stroke=stroke)
585
+
586
+ tif.write(img, contiguous=True)
587
+
588
+
589
+ tiff2avi(pathout,fps=fps)
590
+ print("Done adding scalebar and timestamp to tiff stack! ")
591
+ else:
592
+ print("Exit to change settings")
593
+
594
+ def apply_colormap(image,cmap='viridis'):
595
+ """
596
+ Function to apply false color to grayscale image
597
+ input:
598
+ Image: grayscale image
599
+ camp: colormap string. such as 'viridis'
600
+ """
601
+ import matplotlib.pyplot as plt
602
+ colormap = plt.get_cmap(cmap)
603
+ colored_image = colormap(image / 255.0) # Normalize the image and apply colormap
604
+ colored_image = (colored_image[:, :, :3] * 255).astype(np.uint8) # Convert to 8-bit RGB
605
+ return colored_image
606
+
607
+ def tiff2avi_falsecolor(path,cmap='viridis',fps=15):
608
+ """
609
+ Function to convert tiff to false color avi movie
610
+ input: path : path of tiff stack
611
+ cmap: colormap of the falsecolor
612
+ """
613
+
614
+ import tifffile
615
+ import numpy as np
616
+ import cv2
617
+ import matplotlib.pyplot as plt
618
+ import tqdm
619
+
620
+ print("------------------------------------------")
621
+ print("Convert stack to faulse color avi")
622
+ stack = tifffile.imread(path)
623
+ nFrames,h,w = stack.shape #make sure the order of h and w!
624
+
625
+
626
+ pathout =path[:-4]+'_c_'+str(fps)+'.avi'
627
+
628
+
629
+ #Check the colormap effect
630
+ fr = stack[0]
631
+ fr_color=apply_colormap(fr,cmap)
632
+ plt.imshow(fr_color)
633
+
634
+
635
+ fourcc = cv2.VideoWriter_fourcc(*'MJPG')
636
+
637
+ video_writer = cv2.VideoWriter(pathout, fourcc, fps, (w, h),isColor=True)
638
+
639
+ # Process each frame and write to the video
640
+ for i in tqdm.tqdm(range(nFrames)):
641
+ grayscale_image = stack[i]
642
+ colored_image = apply_colormap(grayscale_image,cmap)
643
+ colored_image = cv2.cvtColor(colored_image, cv2.COLOR_RGB2BGR) # Convert RGB to BGR
644
+
645
+ video_writer.write(colored_image)
646
+
647
+ # Release the video writer
648
+ video_writer.release()
373
649
 
374
650
  def AverageFrame(path,AveN):
375
651
  #Average frames by AveN to increase SNR
@@ -379,14 +655,139 @@ def AverageFrame(path,AveN):
379
655
  pathout = path[:-4]+'_'+str(AveN)+'ave.tif'
380
656
  nFramesOut=math.floor(nFrames/AveN)
381
657
 
382
- for i in tqdm.tqdm(range(nFramesOut)):
383
- AveFr= im[i*AveN]-im[i*AveN]
384
- for m in range(AveN):
385
- fr=im[i*AveN+m]
386
- AveFr=AveFr+fr/AveN
387
- img = AveFr.astype(np.uint8)
388
- if i == 0:
389
- tifffile.imwrite(pathout,img, append=False)
390
- else:
391
- tifffile.imwrite(pathout,img, append=True)
658
+ with tifffile.TiffWriter(pathout,bigtiff=True) as tif:
659
+ for i in tqdm.tqdm(range(nFramesOut)):
660
+ AveFr= im[i*AveN]-im[i*AveN]
661
+ for m in range(AveN):
662
+ fr=im[i*AveN+m]
663
+ AveFr=AveFr+fr/AveN
664
+ img = AveFr.astype(np.uint8)
665
+ tif.write(fr,continuous=True)
666
+
667
+ def apply_colormap(image,cmap='viridis'):
668
+ """
669
+ Function to apply false color to grayscale image
670
+ input:
671
+ Image: grayscale image
672
+ camp: colormap string. such as 'viridis'
673
+ """
674
+ import matplotlib.pyplot as plt
675
+ colormap = plt.get_cmap(cmap)
676
+ colored_image = colormap(image / 255.0) # Normalize the image and apply colormap
677
+ colored_image = (colored_image[:, :, :3] * 255).astype(np.uint8) # Convert to 8-bit RGB
678
+ return colored_image
679
+
680
+ def falsecolorstack(path,cmap='viridis',fps=15):
681
+ import tifffile
682
+ import numpy as np
683
+ import cv2
684
+ import tqdm
685
+ print('Convert tiff stack to false color movie')
686
+
687
+
688
+ stack = tifffile.imread(path)
689
+ nFrames,h,w = stack.shape #make sure the order of h and w!
690
+
691
+ pathout =path[:-4]+'_c_'+str(fps)+'.avi'
692
+
693
+
694
+ fourcc = cv2.VideoWriter_fourcc(*'MJPG')
695
+
696
+ video_writer = cv2.VideoWriter(pathout, fourcc, fps, (w, h),isColor=True)
697
+
698
+ # Process each frame and write to the video
699
+ for i in tqdm.tqdm(range(nFrames)):
700
+ grayscale_image = stack[i]
701
+ colored_image = apply_colormap(grayscale_image,cmap)
702
+ colored_image = cv2.cvtColor(colored_image, cv2.COLOR_RGB2BGR) # Convert RGB to BGR
703
+
704
+ video_writer.write(colored_image)
705
+
706
+ # Release the video writer
707
+ video_writer.release()
708
+ print('Convertion done!')
709
+
710
+ def convertAVIcodec(path,fpsout=0,exp_t=0.2,nFrames=None,isColor=False):
711
+ """
712
+ Function to Directly convert screen recording avi to avi that mac can read
713
+ If fpsout=0, the framerate will not be changed (same as original)
714
+ exp_t: actual exposure time, to remove dupulicate frames
715
+ else fpsout will be changed to set value
716
+ """
717
+
718
+ import moviepy.editor as mp
719
+ print("======================")
720
+ print("Convert AVI codec!")
721
+ video = mp.VideoFileClip(path)
722
+ fps = int(video.fps)
723
+ w = int(video.w)
724
+ h = int(video.h)
725
+ if nFrames==None:
726
+ nFrames = int(fps*video.duration)
727
+ duration =video.duration
728
+ print("fps=", fps, " w =",w, " h=", h)
729
+ print("Total number of Frames=", nFrames)
730
+ #Remove duplic frames
731
+ if fpsout==0:
732
+ fpsout=fps
733
+ nFramesOut=nFrames
734
+ dup=1
735
+ else:
736
+ dup=fps*exp_t
737
+ nFramesOut=int(nFrames/dup)
738
+
739
+ # Export avi
740
+ if nFrames==None:
741
+ pathout2 =path[:-4]+'_'+str(fpsout)+'.avi'
742
+ pathout= path[:-4]+'_DB.tif'
743
+ else:
744
+ pathout2 =path[:-4]+'_Trim_'+str(fpsout)+'.avi'
745
+ pathout= path[:-4]+'_Trim_DB.tif'
746
+ codec = cv2.VideoWriter_fourcc(*'MJPG')
747
+ video_out = cv2.VideoWriter(pathout2, codec , fpsout, (w, h),isColor=isColor)
748
+
749
+ with tifffile.TiffWriter(pathout,bigtiff=True) as tif:
750
+ for j in tqdm.tqdm(range(nFramesOut)):
751
+ i=j*dup
752
+ fr = video.get_frame(mp.cvsecs(i/fps))
753
+ if isColor==False:
754
+ fr = cv2.cvtColor(fr, cv2.COLOR_BGR2GRAY)
755
+
756
+ tif.write(fr, contiguous=True)
757
+ if isColor== True:
758
+ fr = cv2.cvtColor(fr,cv2.COLOR_BGR2RGB)#since open cv uses different color sequence
759
+ video_out.write(fr)
760
+
761
+
762
+ video.reader.close()
763
+ video_out.release()
764
+ print("Conversion done!")
765
+
766
+
767
+ def invertLUT(path):
768
+ import tifffile
769
+ import tqdm
770
+
771
+ video = tifffile.imread(path)
772
+ nFrames, h,w = video.shape[:3]
773
+ pathout =path[:-4]+'_Inv.tiff'
774
+
775
+ with tifffile.TiffWriter(pathout,bigtiff=True) as tif:
776
+
777
+ print("---------------------------------------------")
778
+ print('Inverting Tiff stack LUT')
779
+ for i in tqdm.tqdm(range(nFrames)):
780
+ img=video[i]
781
+ img_IV=255-img
782
+ tif.write(img_IV, contiguous=True)
783
+ print("Invert LUT done!")
784
+
785
+
786
+
787
+
788
+
789
+
790
+
791
+
792
+
392
793