1+ """
2+ Created on Sun Jan 23 11:53:00 2020
3+ @author: weisong
4+ """
5+ from imagepy .core .engine import Simple
6+ import numpy as np
7+ from imagepy import IPy
8+ from scipy .optimize import curve_fit
9+ from skimage .exposure import histogram_matching
10+ import matplotlib .pyplot as plt
11+ import pandas as pd
12+
13+ def copy (imgs ):
14+ if isinstance (imgs , list ):
15+ return [np .zeros_like (imgs [0 ])]
16+ else : return np .zeros_like (imgs )
17+
18+ def exponential_func (t , ref , k , offset ):
19+ return ref * np .exp (- k * t ) + offset
20+
21+ def simple_ratio (imgs , back = 0 , inplace = True , out = print ):
22+ if isinstance (back , int ): back = imgs [back ]
23+ buf = imgs if inplace else copy (imgs )
24+ z , (x , y ) = len (imgs ), imgs [0 ].shape
25+ values , k0 = np .zeros (z ), back .sum ()/ x / y
26+ lim = 255 if imgs [0 ].dtype .type == np .uint8 else 65535
27+ for i in range (z ):
28+ values [i ] = imgs [i ].sum ()/ x / y
29+ np .clip (imgs [i ], 0 , lim / (k0 / values [i ]), out = buf [i ])
30+ np .multiply (buf [i ], k0 / values [i ], out = buf [i ], casting = 'unsafe' )
31+ out (i , z )
32+ return buf , values , k0 / values
33+
34+ def exponential_fit (imgs , inplace = True , out = print ):
35+ buf = imgs if inplace else copy (imgs )
36+ z , (x , y ) = len (imgs ), imgs [0 ].shape
37+ intensity = [i .sum ()/ x / y for i in imgs ]
38+ popt , pcov = curve_fit (exponential_func , np .arange (z ), intensity )
39+ k0 = exponential_func (0 , popt [0 ], popt [1 ], popt [2 ])
40+ rst = exponential_func (np .arange (z ), popt [0 ], popt [1 ], popt [2 ])
41+ lim = 255 if imgs [0 ].dtype .type == np .uint8 else 65535
42+ for i in range (z ):
43+ np .clip (imgs [i ], 0 , lim / (rst [i ]/ k0 ), out = buf [i ])
44+ np .multiply (buf [i ], rst [i ]/ k0 , out = buf [i ], casting = 'unsafe' )
45+ out (i , z )
46+ return buf , popt , intensity , rst
47+
48+ def histogram_match (imgs , back = 0 , inplace = True , out = print ):
49+ if isinstance (back , int ): back = imgs [back ]
50+ buf = imgs if inplace else copy (imgs )
51+ z , (x , y ) = len (imgs ), imgs [0 ].shape
52+ for i in range (z ):
53+ buf [i ] = histogram_matching .match_histograms (imgs [i ], back )
54+ out (i , z )
55+ return buf
56+
57+ def plot (popt , intensity , fitresult ):
58+ t = np .arange (len (intensity ))
59+ plt .plot (t , intensity ,'r.' ,label = 'Experiment' )
60+ plt .plot (t , fitresult ,'k' ,label =
61+ 'Exponential fitted curve\n y=a*exp(-bx)+c\n a=%f\n b=%f\n c=%f' % tuple (popt ))
62+ plt .title ('Exponential fitted result' )
63+ plt .legend ()
64+ plt .show ()
65+
66+ def plot_after (popt , intensity , fitresult ):
67+ import wx
68+ wx .CallAfter (plot , popt , intensity , fitresult )
69+
70+ class Plugin (Simple ):
71+ title = 'Bleach Correction'
72+ note = ['8-bit' ,'16-bit' ,'stack' ]
73+ para = {'method' :'Simple Ratio' , 'new' :True }
74+ view = [(list , 'method' , ['Simple Ratio' ,'Exponential Fit' ,'Histogram Match' ],
75+ str , 'Correction Method' ,'' ),
76+ (bool , 'new' , 'show new window' ),
77+ ('lab' , 'lab' , 'Correct intensity based on your current slice!' )]
78+
79+ def run (self , ips , imgs , para = None ):
80+ if para ['method' ] == 'Simple Ratio' :
81+ rst , value , ratio = simple_ratio (imgs , ips .img , not para ['new' ], self .progress )
82+ body = pd .DataFrame ({'Mean value' : value , 'Ratio' :ratio })
83+ IPy .show_table (body , '%s-simple ratio' % ips .title )
84+ if para ['method' ] == 'Exponential Fit' :
85+ rst , popt , intensity , fitrst = exponential_fit (imgs , not para ['new' ], self .progress )
86+ plot_after (popt , intensity , fitrst )
87+ body = {'Intensity' :intensity , 'Fit' :fitrst }
88+ IPy .show_table (pd .DataFrame (body ), '%s-exp fit' % ips .title )
89+ if para ['method' ] == 'Histogram Match' :
90+ rst = histogram_match (imgs , ips .img , not para ['new' ], self .progress )
91+ if para ['new' ]: IPy .show_img (rst , '%s-corrected' % ips .title )
0 commit comments