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