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