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