root / src / lsm_contour.cpp @ 25
Historique | Voir | Annoter | Télécharger (7,89 ko)
1 | 18 | akiss | /*
|
---|---|---|---|
2 | 18 | akiss | Level-set Method to detect contour (exterior shape)
|
3 | 18 | akiss | Sequential
|
4 | 18 | akiss | Stop criteria parameters in command lines
|
5 | 18 | akiss | |
6 | 18 | akiss | To compile
|
7 | 25 | akiss | g++ -o lsm_contour lsm_contour.cpp -O2 -L/usr/X11R6/lib -lm -lpthread -lX11 -l:libtiff.so.5
|
8 | 18 | akiss | Need CImg.h and lsm_lib.h
|
9 | 18 | akiss | |
10 | 18 | akiss | To execute
|
11 | 25 | akiss | ./lsm_contour img t_up t_down a b smooth perUp perDown
|
12 | 18 | akiss | |
13 | 18 | akiss | img : grayscale image of cells, .inr or .inr.gz
|
14 | 18 | akiss | t_up,t_down : linear threshold value (inr)
|
15 | 18 | akiss | a : area term (float) --> 0.5, 1
|
16 | 18 | akiss | b : curvature term (float)
|
17 | 18 | akiss | smooth : amount of gaussian blur to apply to the image
|
18 | 18 | akiss | perUp, perDown : the algorithm stops when 10 succesive iteration are between perUp and perDown (in % of background growth)
|
19 | 18 | akiss | */
|
20 | 18 | akiss | |
21 | 18 | akiss | #include <iostream> |
22 | 18 | akiss | #include <math.h> |
23 | 18 | akiss | #include <sstream> |
24 | 18 | akiss | #include <vector> |
25 | 18 | akiss | #include <fstream> |
26 | 18 | akiss | |
27 | 18 | akiss | #include "lsm_lib.h" |
28 | 18 | akiss | |
29 | 18 | akiss | using namespace cimg_library; |
30 | 18 | akiss | using namespace std; |
31 | 18 | akiss | |
32 | 18 | akiss | //------------------------------------------------------------------------------
|
33 | 18 | akiss | //Main
|
34 | 18 | akiss | //------------------------------------------------------------------------------
|
35 | 18 | akiss | int main (int argc, char* argv[]) |
36 | 18 | akiss | { |
37 | 18 | akiss | clock_t begin=clock(); |
38 | 18 | akiss | |
39 | 18 | akiss | if(argc!=9) |
40 | 18 | akiss | { |
41 | 18 | akiss | cout<<"!! wrong number of arguments"<<endl;
|
42 | 25 | akiss | cout<<"Usage : lsm_contour img t_up t_down a b smooth perUp perDown"<<endl;
|
43 | 18 | akiss | cout<<"Examples for parameter values:"<<endl;
|
44 | 18 | akiss | cout<<"------------------------------"<<endl;
|
45 | 24 | akiss | cout<<"img : grayscale image of cells, (.inr or .inr.gz)"<<endl;
|
46 | 18 | akiss | cout<<"Upper threshold : t_up = 20"<<endl;
|
47 | 18 | akiss | cout<<"Down threshold : t_down = 5"<<endl;
|
48 | 18 | akiss | cout<<"Area term : a = 0 (0.5, 1)"<<endl;
|
49 | 18 | akiss | cout<<"Curvature term : b = 0 (1)"<<endl;
|
50 | 18 | akiss | cout<<"Gaussian filter : smooth = 1 (0, if image already filtered)"<<endl;
|
51 | 18 | akiss | cout<<"Stop criteria : the contour evolution is in [perDown,perUp] for 10 consecutive iterations"<<endl;
|
52 | 18 | akiss | cout<<" perUp = 0.002, perDown = -0.002"<<endl;
|
53 | 18 | akiss | return 0; |
54 | 18 | akiss | } |
55 | 18 | akiss | |
56 | 18 | akiss | //ckeck filename and read image
|
57 | 18 | akiss | string filename=argv[1]; |
58 | 18 | akiss | CImg<unsigned char> img_prev; |
59 | 18 | akiss | if(filename.compare(filename.size()-4,4,".inr")==0) |
60 | 18 | akiss | { |
61 | 18 | akiss | img_prev.load(filename.c_str()); |
62 | 18 | akiss | } |
63 | 18 | akiss | else if(filename.compare(filename.size()-7,7,".inr.gz")==0) |
64 | 18 | akiss | { |
65 | 18 | akiss | img_prev.load_gzip_external(filename.c_str()); |
66 | 18 | akiss | filename.erase(filename.size()-3);
|
67 | 18 | akiss | } |
68 | 18 | akiss | else
|
69 | 18 | akiss | {cout<<"!! wrong file extension : "<<filename<<endl;
|
70 | 18 | akiss | return 0;} |
71 | 18 | akiss | CImg<float> img=img_prev;
|
72 | 18 | akiss | img_prev.assign(); |
73 | 18 | akiss | cout<<"original image : "<<filename<<endl;
|
74 | 18 | akiss | |
75 | 18 | akiss | //--------------------------------------------Parameters
|
76 | 18 | akiss | //model parameters
|
77 | 18 | akiss | int lam=10; |
78 | 18 | akiss | int alf=atoi(argv[4]); |
79 | 18 | akiss | int beta=atoi(argv[5]); |
80 | 18 | akiss | |
81 | 18 | akiss | //numerical parameters
|
82 | 18 | akiss | float epsilon=1.5; |
83 | 18 | akiss | int dt=100; |
84 | 18 | akiss | float mu=0.1/dt; |
85 | 18 | akiss | int timestep_max=2000; |
86 | 18 | akiss | |
87 | 18 | akiss | //linear threshold
|
88 | 18 | akiss | int t_up=atoi(argv[2]); |
89 | 18 | akiss | int t_down=atoi(argv[3]); |
90 | 18 | akiss | |
91 | 18 | akiss | float smooth=atof(argv[6]); |
92 | 18 | akiss | |
93 | 18 | akiss | float perUp=atof(argv[7]); |
94 | 18 | akiss | float perDown=atof(argv[8]); |
95 | 18 | akiss | |
96 | 18 | akiss | float tailleVoxel[3] = {0.195177,0.195177,0.195177}; |
97 | 21 | akiss | |
98 | 21 | akiss | //other paremeters
|
99 | 21 | akiss | int systout;
|
100 | 18 | akiss | |
101 | 18 | akiss | //-------------------------------------------Names and directories
|
102 | 18 | akiss | //new name with arguments
|
103 | 18 | akiss | string ar2=argv[2]; |
104 | 18 | akiss | string ar3=argv[3]; |
105 | 18 | akiss | string ar4=argv[4]; |
106 | 18 | akiss | string ar5=argv[5]; |
107 | 18 | akiss | string ar6=argv[6]; |
108 | 18 | akiss | string insert="_LSMcont"+ar2+"-"+ar3+"a"+ar4+"b"+ar5+"s"+ar6; |
109 | 18 | akiss | filename.insert(filename.size()-4,insert);
|
110 | 18 | akiss | |
111 | 18 | akiss | //create directories and update names
|
112 | 18 | akiss | size_t test=filename.rfind("/");
|
113 | 18 | akiss | if(test!=filename.npos)
|
114 | 18 | akiss | {filename.erase(0,test+1);} |
115 | 18 | akiss | string outputdir=filename;
|
116 | 18 | akiss | outputdir.erase(filename.size()-4);
|
117 | 18 | akiss | string mkdir="mkdir -p "+outputdir; |
118 | 21 | akiss | systout=system(mkdir.c_str()); |
119 | 18 | akiss | mkdir="mkdir -p "+outputdir+"/evolution"; |
120 | 21 | akiss | systout=system(mkdir.c_str()); |
121 | 18 | akiss | |
122 | 18 | akiss | string filename_cut=outputdir+"/evolution/"+filename; |
123 | 18 | akiss | filename_cut.erase(filename_cut.size()-4);
|
124 | 18 | akiss | filename=outputdir+"/"+filename;
|
125 | 18 | akiss | string result_name=filename;
|
126 | 18 | akiss | |
127 | 18 | akiss | //txt files
|
128 | 18 | akiss | ofstream file; |
129 | 18 | akiss | string txt_name=filename_cut+".txt"; |
130 | 18 | akiss | file.open(txt_name.c_str()); |
131 | 18 | akiss | file<<argv[0]<<endl;
|
132 | 18 | akiss | time_t t; |
133 | 18 | akiss | struct tm * timeinfo;
|
134 | 18 | akiss | time(&t); |
135 | 18 | akiss | timeinfo=localtime(&t); |
136 | 18 | akiss | file<<asctime(timeinfo); |
137 | 18 | akiss | file<<"image : "<<argv[1]<<endl; |
138 | 18 | akiss | file<<"_________________________________"<<endl;
|
139 | 18 | akiss | file<<"Parameters"<<endl;
|
140 | 18 | akiss | file<<"lambda : "<<lam<<endl;
|
141 | 18 | akiss | file<<"alpha : "<<alf<<endl;
|
142 | 18 | akiss | file<<"epsilon : "<<epsilon<<endl;
|
143 | 18 | akiss | file<<"dt : "<<dt<<endl;
|
144 | 18 | akiss | file<<"mu : "<<mu<<endl;
|
145 | 18 | akiss | file<<"timestep_max : "<<timestep_max<<endl;
|
146 | 18 | akiss | file<<"\nthreshold up : "<<t_up<<endl;
|
147 | 18 | akiss | file<<"threshold down : "<<t_down<<endl;
|
148 | 18 | akiss | file<<"beta : "<<beta<<endl;
|
149 | 18 | akiss | file<<"perUp : "<<perUp<<endl;
|
150 | 18 | akiss | file<<"perDown : "<<perDown<<endl;
|
151 | 18 | akiss | |
152 | 18 | akiss | ofstream bg_file; |
153 | 18 | akiss | string bg_name=filename_cut+"_BGgrowth.txt"; |
154 | 18 | akiss | bg_file.open(bg_name.c_str()); |
155 | 18 | akiss | bg_file<<"it\tbg_growth"<<endl;
|
156 | 18 | akiss | |
157 | 18 | akiss | //-----------------------------------------Image Pre-processing
|
158 | 18 | akiss | //add slices
|
159 | 18 | akiss | img=add_side_slices(img,3);
|
160 | 18 | akiss | |
161 | 18 | akiss | //define and save cut
|
162 | 18 | akiss | int cut=img._depth/2; |
163 | 18 | akiss | cout <<"cut z= "<<cut<<endl;
|
164 | 18 | akiss | file <<"\ncut z= "<<cut<<endl;
|
165 | 18 | akiss | CImg<float> imgCut=img.get_crop(0,0,cut,0,img._width,img._height,cut,0); |
166 | 18 | akiss | imgCut.save((filename_cut+".png").c_str());
|
167 | 18 | akiss | |
168 | 18 | akiss | //smooth image
|
169 | 18 | akiss | file<<"smooth : "<<smooth<<endl;
|
170 | 18 | akiss | img.blur(smooth); |
171 | 18 | akiss | |
172 | 18 | akiss | //-------------------------------------------Initialization
|
173 | 18 | akiss | //compute fixed terms
|
174 | 18 | akiss | CImg<float> g=edge_indicator(gradient(img));
|
175 | 18 | akiss | CImgList<float> gg=gradient(g);
|
176 | 18 | akiss | |
177 | 18 | akiss | //initialize level-set
|
178 | 18 | akiss | int c0=-4; |
179 | 18 | akiss | CImg<unsigned char> segmented=threshold_linear_alongZ(img,t_up,t_down); |
180 | 18 | akiss | string segmentedName=filename+".gz"; |
181 | 18 | akiss | segmentedName.insert(filename.size()-4,"_initial"); |
182 | 18 | akiss | segmented.save_gzip_external(segmentedName.c_str()); |
183 | 18 | akiss | |
184 | 18 | akiss | CImg<float> psi=lsm_contour_init(segmented,c0);
|
185 | 18 | akiss | |
186 | 18 | akiss | int it=0; |
187 | 18 | akiss | int it_stop=0; |
188 | 18 | akiss | bool contour_evolves=true; |
189 | 18 | akiss | int nb_pix=img.width()*img.height()*img.depth();
|
190 | 18 | akiss | double prev_backsegm=segmented.sum();
|
191 | 18 | akiss | |
192 | 18 | akiss | //-------------------------------------------Time iterations
|
193 | 18 | akiss | while( (it<timestep_max) and (contour_evolves==true) ) |
194 | 18 | akiss | { |
195 | 18 | akiss | //LSM
|
196 | 18 | akiss | psi=evolution_AK2_contour(psi,g,gg,g,lam,mu,alf,beta,epsilon,dt); |
197 | 18 | akiss | |
198 | 18 | akiss | //Update segmentation
|
199 | 18 | akiss | double backsegm=0; |
200 | 18 | akiss | cimg_forXYZ(segmented,x,y,z) |
201 | 18 | akiss | { |
202 | 18 | akiss | if(psi(x,y,z)>0) |
203 | 18 | akiss | { |
204 | 18 | akiss | segmented(x,y,z)=1;
|
205 | 18 | akiss | backsegm+=1;
|
206 | 18 | akiss | } |
207 | 18 | akiss | else
|
208 | 18 | akiss | {segmented(x,y,z)=0;}
|
209 | 18 | akiss | } |
210 | 18 | akiss | |
211 | 18 | akiss | //Background evolution
|
212 | 18 | akiss | double bg_evolution=backsegm-prev_backsegm;
|
213 | 18 | akiss | double bg100=(bg_evolution*1.0/nb_pix)*100; |
214 | 18 | akiss | prev_backsegm=backsegm; |
215 | 18 | akiss | |
216 | 18 | akiss | cout<<"----------------------------------- it : "<<it<<endl;
|
217 | 18 | akiss | cout<<"bg growth : "<<bg_evolution<<endl;
|
218 | 18 | akiss | cout<<"% of bg growth : "<<bg100<<endl;
|
219 | 18 | akiss | bg_file<<it<<"\t"<<bg_evolution<<endl;
|
220 | 18 | akiss | |
221 | 18 | akiss | |
222 | 18 | akiss | //Stop criteria
|
223 | 18 | akiss | if((it>10) and (bg100<perUp) and (bg100>perDown)) |
224 | 18 | akiss | { |
225 | 18 | akiss | it_stop+=1;
|
226 | 18 | akiss | if(it_stop>9) |
227 | 18 | akiss | {contour_evolves=false;}
|
228 | 18 | akiss | } |
229 | 18 | akiss | else
|
230 | 18 | akiss | { |
231 | 18 | akiss | it_stop=0;
|
232 | 18 | akiss | } |
233 | 18 | akiss | |
234 | 18 | akiss | //Graphics to follow evolution
|
235 | 18 | akiss | if((it%50==0)or(contour_evolves==false)or(it==timestep_max-1)) |
236 | 18 | akiss | { |
237 | 18 | akiss | ostringstream oss; |
238 | 18 | akiss | oss << it; |
239 | 18 | akiss | string iterstring=""; |
240 | 18 | akiss | if(it<10) {iterstring="00"+oss.str();} |
241 | 18 | akiss | else if (it<100) {iterstring="0"+oss.str();} |
242 | 18 | akiss | else {iterstring=oss.str();}
|
243 | 18 | akiss | cout<<"-----------------------------------"<<endl;
|
244 | 18 | akiss | cout<<" *** time step for graphics : "<<iterstring<<endl;
|
245 | 18 | akiss | //Save cut
|
246 | 18 | akiss | CImg<float>segCut=segmented.get_crop(0,0,cut,0,img._width,img._height,cut,0); |
247 | 18 | akiss | string temp_name=filename_cut+"it"+iterstring+".png"; |
248 | 18 | akiss | segCut.normalize(0,255).save(temp_name.c_str()); |
249 | 18 | akiss | } |
250 | 18 | akiss | if((((it%50)==0)and(it!=0))or(contour_evolves==false)or(it==timestep_max-1)) |
251 | 18 | akiss | { |
252 | 18 | akiss | //Save result
|
253 | 18 | akiss | CImg<unsigned char>segSave=remove_side_slices(segmented,3); |
254 | 18 | akiss | segSave.save_inr(result_name.c_str(),tailleVoxel); |
255 | 18 | akiss | segSave.assign(); |
256 | 18 | akiss | string zip="gzip -f "+result_name; |
257 | 21 | akiss | systout=system(zip.c_str()); |
258 | 18 | akiss | } |
259 | 18 | akiss | it+=1;
|
260 | 18 | akiss | } |
261 | 18 | akiss | |
262 | 18 | akiss | clock_t end=clock(); |
263 | 18 | akiss | double time=double(end-begin)/CLOCKS_PER_SEC; |
264 | 18 | akiss | cout <<"elapsed time : "<<time<<" sec ( ~ "<<time/60<<" mn ~ "<<time/60/60<<" h)"<<endl; |
265 | 18 | akiss | file <<"last iteration : "<<it-1<<endl; |
266 | 18 | akiss | file <<"elapsed time : "<<time<<" sec ( ~ "<<time/60<<" mn ~ "<<time/60/60<<" h)"<<endl; |
267 | 18 | akiss | |
268 | 18 | akiss | file<<"width "<<img.width()<<endl;
|
269 | 18 | akiss | file<<"height "<<img.height()<<endl;
|
270 | 18 | akiss | file<<"depth "<<img.depth()<<endl;
|
271 | 18 | akiss | |
272 | 18 | akiss | file<<"number of pixel "<<img._width*img._height*img._depth<<endl;
|
273 | 18 | akiss | |
274 | 18 | akiss | file.close(); |
275 | 18 | akiss | return 0; |
276 | 18 | akiss | } |