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