Statistiques
| Révision :

root / src / lsm_cells.cpp @ 4

Historique | Voir | Annoter | Télécharger (16,73 ko)

1 1 akiss
/*
2 1 akiss
Level-set Method to detect cell's contours
3 1 akiss
- Parallel standard version -
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_cells lsm_cells.cpp -O2 -L/usr/X11R6/lib -lm -lpthread -lX11 -fopenmp
13 1 akiss
 Needs CImg.h and lsm_lib.h
14 1 akiss

15 1 akiss
To execute :
16 1 akiss
 ./lsm_cells img img_wat img_contour erosion a b gamma smooth type
17 1 akiss

18 1 akiss
 image in .inr or .inr.gz, save in .inr.gz
19 1 akiss
 img : grayscale image of cells (unsigned char)
20 1 akiss
 img_wat : watershed 16bits image (unsigned short) with background label 1 and cells labels >1
21 1 akiss
 img_contour : binary image with background=1, all cells=0 (unsigned char)
22 1 akiss
 erosion : amount of erosion for each cell in watershed image (int)
23 1 akiss
 a : area term (float) --> 0 or 0.5 or 1 (the default is 0.5)
24 1 akiss
             if negative, the object retracts
25 1 akiss
             if positive, the object inflates
26 1 akiss
 b : curvature term (float) --> 0 or 1 (the default is 0)
27 1 akiss
 gamma : scale parameter (float>0) --> 0.5 or 1 (the default is 1)
28 1 akiss
 smooth : gaussian blur to apply to the image (int) --> 0 or 1 (the default is 0)
29 1 akiss
 lsm_type : image, gradient or hessien based evolution --> 'i', 'g' or 'h' (the default is g)
30 1 akiss
*/
31 1 akiss
32 1 akiss
#include <iostream>
33 1 akiss
#include <math.h>
34 1 akiss
#include <sstream>
35 1 akiss
#include <vector>
36 1 akiss
#include <fstream>
37 1 akiss
#include <omp.h>
38 1 akiss
39 1 akiss
#include "CImg.h"
40 1 akiss
#include "lsm_lib.h"
41 1 akiss
42 1 akiss
using namespace cimg_library;
43 1 akiss
using namespace std;
44 1 akiss
45 1 akiss
46 1 akiss
//Return list of cell label
47 1 akiss
//---------------------------------------------------------------------
48 1 akiss
vector<int> index(const CImg<unsigned short> & wat, int nbcells)
49 1 akiss
{
50 1 akiss
  vector<int> list;
51 1 akiss
  vector<bool> test(nbcells,false);
52 1 akiss
  cimg_forXYZ(wat,x,y,z)
53 1 akiss
    {
54 1 akiss
      int ind=wat(x,y,z);
55 1 akiss
      if((test[ind]==false)and(ind!=1)and(ind!=0))
56 1 akiss
        {
57 1 akiss
          list.push_back(ind);
58 1 akiss
          test[ind]=true;
59 1 akiss
        }
60 1 akiss
    }
61 1 akiss
  return list;
62 1 akiss
}
63 1 akiss
64 1 akiss
//Return crop psi image and it's min coordinates for one cell
65 1 akiss
//--------------------------------------------------------------------
66 1 akiss
CImg<float> box_cell(const CImg<unsigned short> & wat, int marge,int erosion, int c0,int indice, int &xmin, int &ymin, int &zmin)
67 1 akiss
{
68 1 akiss
  //search box (min and max coordinates with a marge)
69 1 akiss
  xmin=wat._width;
70 1 akiss
  ymin=wat._height;
71 1 akiss
  zmin=wat._depth;
72 1 akiss
  int xmax=0;
73 1 akiss
  int ymax=0;
74 1 akiss
  int zmax=0;
75 1 akiss
  cimg_forXYZ(wat,x,y,z)
76 1 akiss
    {
77 1 akiss
      if(wat(x,y,z)==indice)
78 1 akiss
        {
79 1 akiss
          if(x>xmax){xmax=x;}else if(x<xmin){xmin=x;}
80 1 akiss
          if(y>ymax){ymax=y;}else if(y<ymin){ymin=y;}
81 1 akiss
          if(z>zmax){zmax=z;}else if(z<zmin){zmin=z;}
82 1 akiss
        }
83 1 akiss
    }
84 1 akiss
  //marge and border conditions
85 1 akiss
  xmin=xmin-marge;
86 1 akiss
  if(xmin<0){xmin=0;}
87 1 akiss
  ymin=ymin-marge;
88 1 akiss
  if(ymin<0){ymin=0;}
89 1 akiss
  zmin=zmin-marge;
90 1 akiss
  if(zmin<0){zmin=0;}
91 1 akiss
  xmax=xmax+marge;
92 1 akiss
  if(xmax>=wat._width){xmax=wat._width-1;}
93 1 akiss
  ymax=ymax+marge;
94 1 akiss
  if(ymax>=wat._height){ymax=wat._height-1;}
95 1 akiss
  zmax=zmax+marge;
96 1 akiss
  if(zmax>=wat._depth){zmax=wat._depth-1;}
97 1 akiss
98 1 akiss
  //crop wat image to the size of box, make binary
99 1 akiss
  CImg<unsigned short>binary=wat.get_crop(xmin,ymin,zmin,0,xmax,ymax,zmax,0);
100 1 akiss
  cimg_forXYZ(binary,x,y,z)
101 1 akiss
    {
102 1 akiss
      if(binary(x,y,z)==indice){binary(x,y,z)=1;}
103 1 akiss
      else {binary(x,y,z)=0;}
104 1 akiss
    }
105 1 akiss
106 1 akiss
  //erode binary but not completely (vol stay >0)
107 1 akiss
  int vol=binary.sum();
108 1 akiss
  int nb_ero=0;
109 1 akiss
  while((vol>0)and(nb_ero<abs(erosion)))
110 1 akiss
  {
111 1 akiss
    CImg<unsigned char> binary_erode=binary.get_erode(3,3,3);
112 1 akiss
        if (erosion<0)
113 1 akiss
        {
114 1 akiss
                for(int i=0;i<3;i++)
115 1 akiss
                {
116 1 akiss
                binary=binary.get_dilate(2,2,2);
117 1 akiss
                }
118 1 akiss
                binary_erode=binary;
119 1 akiss
        }
120 1 akiss
      vol=binary_erode.sum();
121 1 akiss
      if(vol>0)
122 1 akiss
        {
123 1 akiss
          binary=binary_erode;
124 1 akiss
          nb_ero+=1;
125 1 akiss
        }
126 1 akiss
    }
127 1 akiss
128 1 akiss
  //initalize psi
129 1 akiss
  CImg<float>psi=binary;
130 1 akiss
  cimg_forXYZ(psi,x,y,z)
131 1 akiss
    {
132 1 akiss
      if(binary(x,y,z)==0){psi(x,y,z)=c0;}
133 1 akiss
      else {psi(x,y,z)=-c0;}
134 1 akiss
    }
135 1 akiss
  return psi;
136 1 akiss
}
137 1 akiss
138 1 akiss
139 1 akiss
//LSM segment : edge detection
140 1 akiss
//---------------------------------------------------------------------
141 1 akiss
CImg<float> lsm_segment2(CImg<float> psi,CImg<float> const & g,CImgList<float> const & gg,CImg<float> const & h, int lam, float mu,float alf, float beta, float epsilon, int dt, vector<int> min_list)
142 1 akiss
{
143 1 akiss
  int timestep_max=2000;
144 1 akiss
  int evolution_min=1;
145 1 akiss
  //int evolution_max=-1;
146 1 akiss
  int it=0;
147 1 akiss
  int it_stop=0;
148 1 akiss
  bool contour_evolve=true;
149 1 akiss
  int backsegm=0;
150 1 akiss
  CImg<float> psi_old=psi;
151 1 akiss
  cimg_forXYZ(psi,x,y,z)
152 1 akiss
    {
153 1 akiss
      if(psi(x,y,z)>=0){backsegm+=1;}
154 1 akiss
    }
155 1 akiss
156 1 akiss
  while((it<timestep_max)and(contour_evolve==true)and(backsegm>30))
157 1 akiss
    {
158 1 akiss
      psi_old=psi;
159 1 akiss
      //evolution
160 1 akiss
      psi=evolution_AK2_contour_cells(psi,g,gg,h,lam,mu,alf,beta,epsilon,dt,min_list);
161 1 akiss
      //new segmentation
162 1 akiss
      int new_backsegm=0;
163 1 akiss
      cimg_forXYZ(psi,x,y,z)
164 1 akiss
        {
165 1 akiss
          if(psi(x,y,z)>=0){new_backsegm+=1;}
166 1 akiss
        }
167 1 akiss
168 1 akiss
      //Stop criteria
169 1 akiss
      // * if the cell would disappear, we stop
170 1 akiss
      if(new_backsegm==0)
171 1 akiss
                        {psi=psi_old;
172 1 akiss
                     contour_evolve=false;}
173 1 akiss
174 1 akiss
      int bg_evolution=abs(new_backsegm-backsegm);
175 1 akiss
176 1 akiss
      // * if the evolution is less then evolution_min 3 consecutive times
177 1 akiss
      if((it>10) and (bg_evolution<=evolution_min) )
178 1 akiss
        {
179 1 akiss
          it_stop+=1;
180 1 akiss
          if(it_stop>3)
181 1 akiss
            {contour_evolve=false;}
182 1 akiss
        }
183 1 akiss
      else
184 1 akiss
        {
185 1 akiss
          it_stop=0;
186 1 akiss
        }
187 1 akiss
188 1 akiss
189 1 akiss
      it+=1;
190 1 akiss
      backsegm=new_backsegm;
191 1 akiss
    }
192 1 akiss
  return psi;
193 1 akiss
}
194 1 akiss
195 1 akiss
196 1 akiss
//Reconstruct full segmented image from cell's images
197 1 akiss
//---------------------------------------------------------------
198 1 akiss
CImg<unsigned short> reconstruct(const CImg<unsigned char> & background,const vector<CImg<float> > & psi_list, const vector< vector<int> > & min_list, int nbcells,const vector<int> & list)
199 1 akiss
{
200 1 akiss
  CImg<unsigned short> res=background;
201 1 akiss
  for(int i=0;i<nbcells;i++)
202 1 akiss
    {
203 1 akiss
      cimg_forXYZ(psi_list[i],xb,yb,zb)
204 1 akiss
        {
205 1 akiss
          int x=xb+min_list[i][0];
206 1 akiss
          int y=yb+min_list[i][1];
207 1 akiss
          int z=zb+min_list[i][2];
208 1 akiss
          if(psi_list[i](xb,yb,zb)>=0)
209 1 akiss
            {res(x,y,z)=list[i];}
210 1 akiss
        }
211 1 akiss
    }
212 1 akiss
  return res;
213 1 akiss
}
214 1 akiss
215 1 akiss
//Reconstruct segmented image from cell's images and treat overlap
216 1 akiss
//---------------------------------------------------------------
217 1 akiss
CImg<unsigned short> reconstruct_overlap(CImg<unsigned char> const &  background,const vector<CImg<float> > & psi_list, const vector< vector<int> > & min_list, int nbcells, CImg<unsigned char> &free, const vector<int> & list)
218 1 akiss
{
219 1 akiss
  CImg<unsigned short> res=background;
220 1 akiss
  free=background;
221 1 akiss
  for(int i=0;i<nbcells;i++)
222 1 akiss
    {
223 1 akiss
      cimg_forXYZ(psi_list[i],xb,yb,zb)
224 1 akiss
        {
225 1 akiss
          int x=xb+min_list[i][0];
226 1 akiss
          int y=yb+min_list[i][1];
227 1 akiss
          int z=zb+min_list[i][2];
228 1 akiss
          if(psi_list[i](xb,yb,zb)>=0)
229 1 akiss
            {
230 1 akiss
              res(x,y,z)=list[i];
231 1 akiss
              free(x,y,z)+=1;
232 1 akiss
            }
233 1 akiss
        }
234 1 akiss
    }
235 1 akiss
  cimg_forXYZ(free,x,y,z)
236 1 akiss
    {
237 1 akiss
      if(free(x,y,z)>1)
238 1 akiss
        {
239 1 akiss
          if(background(x,y,z)==1)
240 1 akiss
            {
241 1 akiss
              free(x,y,z)=1;
242 1 akiss
              res(x,y,z)=1;
243 1 akiss
            }
244 1 akiss
          else
245 1 akiss
            {
246 1 akiss
              free(x,y,z)=0;
247 1 akiss
              res(x,y,z)=0;
248 1 akiss
            }
249 1 akiss
        }
250 1 akiss
    }
251 1 akiss
  return res;
252 1 akiss
}
253 1 akiss
254 1 akiss
255 1 akiss
//-----------------------------------------------------------------------------------------------
256 1 akiss
//******************************************  MAIN **********************************************
257 1 akiss
//-----------------------------------------------------------------------------------------------
258 1 akiss
259 1 akiss
int main (int argc, char* argv[])
260 1 akiss
{
261 1 akiss
  double begin=omp_get_wtime();
262 1 akiss
263 1 akiss
  if(argc<5)
264 1 akiss
    {
265 1 akiss
    cout<<"!! wrong number of arguments ("<<argc<<")"<<endl;
266 1 akiss
    cout<<"Usage : lsm_cells img img_wat img_contour erosion [a b smooth lsm_type]"<<endl;
267 1 akiss
    cout<<"----------------- "<<endl;
268 1 akiss
        cout<<"img : grayscale image of cells, (.inr or .inr.gz)"<<endl;
269 1 akiss
        cout<<"img_wat : image of seeds, (.inr or .inr.gz)"<<endl;
270 1 akiss
        cout<<"img_contour : mask, where cells do not evolve, (.inr or .inr.gz)"<<endl;
271 1 akiss
        cout<<"              if 'None', then cells can evolve on the whole image"<<endl;
272 1 akiss
        cout<<"erosion : amount of erosion of seeds for initialisation (uint8) --> -2, 0, 2"<<endl;
273 1 akiss
        cout<<"              if 0, then no erosion or dilation"<<endl;
274 1 akiss
        cout<<"              if negative, then a dilation is performed"<<endl;
275 1 akiss
        cout<<"a : area term (float) --> 0 or 0.5 or 1 (the default is 0.5)"<<endl;
276 1 akiss
        cout<<"              if negative, the object retracts"<<endl;
277 1 akiss
        cout<<"              if positive, the object inflates"<<endl;
278 1 akiss
        cout<<"b : curvature term (float) --> 0 or 1 (the default is 0)"<<endl;
279 1 akiss
        cout<<"gamma : scale parameter (float>0) --> 0.5 or 1 (the default is 1)"<<endl;
280 1 akiss
        cout<<"smooth : gaussian blur to apply to the image (int) --> 0 or 1 (the default is 0)"<<endl;
281 1 akiss
    cout<<"lsm_type : image, gradient or hessien based evolution --> 'i', 'g' or 'h' (the default is g)"<<endl;
282 1 akiss
      return 0;
283 1 akiss
    }
284 1 akiss
285 1 akiss
  //----------------------------------------------read images and check the names
286 1 akiss
  //Original image
287 1 akiss
  CImg<char> description;
288 1 akiss
  float tailleVoxel[3] = {0}; // resolution initialisation
289 1 akiss
290 1 akiss
  bool gzipped=false;
291 1 akiss
292 1 akiss
  string filename_img=argv[1];
293 1 akiss
  CImg<unsigned char> img_prev;
294 1 akiss
  if(filename_img.compare(filename_img.size()-4,4,".inr")==0)
295 1 akiss
    {
296 1 akiss
      img_prev.load(filename_img.c_str());
297 1 akiss
      img_prev.get_load_inr(filename_img.c_str(),tailleVoxel); // reads resolution
298 1 akiss
    }
299 1 akiss
  else if(filename_img.compare(filename_img.size()-7,7,".inr.gz")==0)
300 1 akiss
    {
301 1 akiss
          gzipped = true;
302 1 akiss
      string oldname = filename_img;
303 1 akiss
      filename_img.erase(filename_img.size()-3);
304 1 akiss
      string zip="gunzip -c "+oldname+" > "+filename_img;
305 1 akiss
      if(system(zip.c_str())); // decompress image file
306 1 akiss
      img_prev.load(filename_img.c_str());
307 1 akiss
      img_prev.get_load_inr(filename_img.c_str(),tailleVoxel); // reads resolution
308 1 akiss
      zip="rm "+filename_img;
309 1 akiss
      if(system(zip.c_str())); //removes decompressed image
310 1 akiss
    }
311 1 akiss
  else
312 1 akiss
    {cout<<"!! wrong file extension : "<<filename_img<<endl;
313 1 akiss
      return 0;}
314 1 akiss
  CImg<float> img=img_prev;
315 1 akiss
  img_prev.assign();
316 1 akiss
  cout<<"original image : "<<filename_img<<endl;
317 1 akiss
  cout<<"size : "<<img.size()<<endl;
318 1 akiss
  cout<<"size of original image : "<< img._width<<' '<< img._height <<' '<< img._depth<<' '<< endl;
319 1 akiss
320 1 akiss
  //Watershed
321 1 akiss
  string filename=argv[2];
322 1 akiss
  CImg<unsigned short> wat;
323 1 akiss
  if(filename.compare(filename.size()-4,4,".inr")==0)
324 1 akiss
    {
325 1 akiss
      wat.load(filename.c_str());
326 1 akiss
    }
327 1 akiss
  else if(filename.compare(filename.size()-7,7,".inr.gz")==0)
328 1 akiss
    {
329 1 akiss
      wat.load_gzip_external(filename.c_str());
330 1 akiss
      filename.erase(filename.size()-3);
331 1 akiss
    }
332 1 akiss
  else
333 1 akiss
    {cout<<"!! wrong file extension : "<<filename<<endl;
334 1 akiss
      return 0;}
335 1 akiss
  cout<<"watershed image : "<<filename<<endl;
336 1 akiss
cout<<"size : "<<wat.size()<<endl;
337 1 akiss
  cout<<"size of original image : "<< wat._width<<' '<< wat._height <<' '<< wat._depth<<' '<< endl;
338 1 akiss
339 1 akiss
  //Background
340 1 akiss
  string filename_bg=argv[3];
341 1 akiss
  CImg<unsigned char> background(img._width, img._height, img._depth,1,0);
342 1 akiss
   if(filename_bg.compare("None")==0)
343 1 akiss
    {
344 1 akiss
       cout<<"!! no background entered !!"<<endl;
345 1 akiss
    }
346 1 akiss
    else if(filename_bg.compare(filename_bg.size()-4,4,".inr")==0)
347 1 akiss
    {
348 1 akiss
      background.load(filename_bg.c_str());
349 1 akiss
    }
350 1 akiss
  else if(filename_bg.compare(filename_bg.size()-7,7,".inr.gz")==0)
351 1 akiss
    {
352 1 akiss
      background.load_gzip_external(filename_bg.c_str());
353 1 akiss
      filename_bg.erase(filename_bg.size()-3);
354 1 akiss
    }
355 1 akiss
  else
356 1 akiss
    {cout<<"!! wrong file extension : "<<filename_bg<<endl;
357 1 akiss
      return 0;}
358 1 akiss
  cout<<"background image : "<<filename_bg<<endl;
359 1 akiss
360 1 akiss
  if((wat.size()!=img.size())or(background.size()!=img.size()))
361 1 akiss
    {
362 1 akiss
      cout<<"!! images are not the same size"<<endl;
363 1 akiss
      return 0;
364 1 akiss
    }
365 1 akiss
  else cout<<"size : "<<img.size()<<endl;
366 1 akiss
367 1 akiss
368 1 akiss
  //---------------------------------------------------------------Parameters
369 1 akiss
  //model parameters
370 1 akiss
371 1 akiss
  int c0=-4;
372 1 akiss
  int erosion=atoi(argv[4]);
373 1 akiss
  int marge=10;
374 1 akiss
375 1 akiss
  int lam=10;
376 1 akiss
  float alf=0.5;
377 1 akiss
  float beta=0;
378 1 akiss
  float gamma=1;
379 1 akiss
  float smooth=0;
380 1 akiss
  string lsm_type="g";
381 1 akiss
382 1 akiss
  string ar=argv[4];
383 1 akiss
  string insert="_cellLSM-d"+ar;
384 1 akiss
  if(argc>5)
385 1 akiss
    {
386 1 akiss
    alf=atof(argv[5]);
387 1 akiss
    ar=argv[5];
388 1 akiss
    insert=insert+"-a"+ar;
389 1 akiss
    }
390 1 akiss
  if(argc>6)
391 1 akiss
    {
392 1 akiss
    beta=atof(argv[6]);
393 1 akiss
    ar=argv[6];
394 1 akiss
    insert+="-b"+ar;
395 1 akiss
    }
396 1 akiss
  if(argc>7)
397 1 akiss
    {
398 1 akiss
    gamma=atof(argv[7]);
399 1 akiss
    ar=argv[7];
400 1 akiss
    insert+="-g"+ar;
401 1 akiss
        }
402 1 akiss
  if(argc>8)
403 1 akiss
    {
404 1 akiss
    smooth=atof(argv[8]);
405 1 akiss
    ar=argv[8];
406 1 akiss
    insert+="-s"+ar;
407 1 akiss
        }
408 1 akiss
  if(argc>9)
409 1 akiss
    {
410 1 akiss
        lsm_type=argv[9];
411 1 akiss
        ar=argv[9];
412 1 akiss
        insert+="-"+ar;
413 1 akiss
        }
414 1 akiss
415 1 akiss
416 1 akiss
417 1 akiss
  //numerical parameters
418 1 akiss
  float epsilon=0.5;
419 1 akiss
  int dt=1;   //it was 50, changed into 1 the 2015/10/16
420 1 akiss
  float mu=0.1/dt;
421 1 akiss
  int timestep_max=10000; // it was 1000, changed into 10000 the 2015/10/16
422 1 akiss
423 1 akiss
424 1 akiss
  //------------------------------------Names and directories
425 1 akiss
  //new name with arguments
426 1 akiss
  filename.insert(filename.size()-4,insert);
427 1 akiss
428 1 akiss
  //create directories and update names
429 1 akiss
  size_t test=filename.rfind("/");
430 1 akiss
  if(test!=filename.npos)
431 1 akiss
    {filename.erase(0,test+1);}
432 1 akiss
  string outputdir=filename;
433 1 akiss
  outputdir.erase(filename.size()-4);
434 1 akiss
  string mkdir="mkdir -p "+outputdir;
435 1 akiss
  if(system(mkdir.c_str()));
436 1 akiss
437 1 akiss
  string filename_txt=outputdir+"/"+filename;
438 1 akiss
  filename_txt.erase(filename_txt.size()-4);
439 1 akiss
  filename=outputdir+"/"+filename;
440 1 akiss
  string wat_eroded_name=filename;
441 1 akiss
  wat_eroded_name.insert(filename.size()-4,"_eroded");
442 1 akiss
  string edge_detection_name=filename;
443 1 akiss
  edge_detection_name.insert(filename.size()-4,"_evoEdge");
444 1 akiss
  string edge_evolve_name=filename;
445 1 akiss
  edge_evolve_name.insert(filename.size()-4,"_final");
446 1 akiss
447 1 akiss
  //txt files
448 1 akiss
  ofstream file;
449 1 akiss
  string txt_name=filename_txt+".txt";
450 1 akiss
  file.open(txt_name.c_str());
451 1 akiss
  file<<argv[0]<<endl;
452 1 akiss
  time_t t;
453 1 akiss
  struct tm * timeinfo;
454 1 akiss
  time(&t);
455 1 akiss
  timeinfo=localtime(&t);
456 1 akiss
  file<<asctime(timeinfo);
457 1 akiss
  file<<"image : "<<argv[1]<<endl;
458 1 akiss
  file<<"watershed : "<<argv[2]<<endl;
459 1 akiss
  file<<"background : "<<argv[3]<<endl;
460 1 akiss
  file<<"_________________________________"<<endl;
461 1 akiss
  file<<"Parameters"<<endl;
462 1 akiss
  file<<"lsm_type : "<<lsm_type<<endl;
463 1 akiss
  file<<"lambda : "<<lam<<endl;
464 1 akiss
  file<<"alpha : "<<alf<<endl;
465 1 akiss
  file<<"beta : "<<beta<<endl;
466 1 akiss
  file<<"gamma :"<<gamma<<endl;
467 1 akiss
  //file<<"alphabis : "<<alfabis<<endl;
468 1 akiss
  //file<<"betabis : "<<betabis<<endl;
469 1 akiss
  file<<"erosion : "<<erosion<<endl;
470 1 akiss
  file<<"marge : "<<marge<<endl;
471 1 akiss
  file<<"epsilon : "<<epsilon <<endl;
472 1 akiss
  file<<"mu : "<<mu <<endl;
473 1 akiss
  file<<"dt : "<<dt <<endl;
474 1 akiss
  file<<"timestep_max : "<<timestep_max <<endl;
475 1 akiss
476 1 akiss
  //-----------------------------------------Image Pre-processing
477 1 akiss
478 1 akiss
  //smooth image
479 1 akiss
  file<<"smooth : "<<smooth<<endl;
480 1 akiss
  if (smooth>0)
481 1 akiss
  {
482 1 akiss
  img.blur(smooth);
483 1 akiss
  }
484 1 akiss
485 1 akiss
  //-------------------------------------Initialization with erosion
486 1 akiss
  //compute fixed terms
487 1 akiss
  CImg<float> g;
488 1 akiss
  if(lsm_type.compare("g")==0)
489 1 akiss
    {
490 1 akiss
  g=edge_indicator1(img, gamma);
491 1 akiss
    }
492 1 akiss
  else if (lsm_type.compare("h")==0)
493 1 akiss
   {
494 1 akiss
  g=edge_indicator2s(img, gamma);
495 1 akiss
   }
496 1 akiss
  else if (lsm_type.compare("i")==0)
497 1 akiss
   {
498 1 akiss
  g=edge_indicator3(img, gamma);
499 1 akiss
   }
500 1 akiss
  else
501 1 akiss
  cout<<"Wrong lsm type given :'"<<lsm_type<<"'('g' for gradient-based, 'h' for Hessien-based) "<<endl;
502 1 akiss
503 1 akiss
  CImgList<float> gg=gradient(g);
504 1 akiss
  CImg<float> h=g;
505 1 akiss
  img.assign();
506 1 akiss
507 1 akiss
  //initialize psi for every cell
508 1 akiss
  int maxcells=wat.max()+1; //indice maximum
509 1 akiss
  vector<int> list=index(wat,maxcells);
510 1 akiss
  int nbcells=list.size();
511 1 akiss
  cout<<"number of cells : "<<nbcells<<endl;
512 1 akiss
  file<<"number of cells : "<<nbcells<<endl;
513 1 akiss
  vector<CImg<float> > psi_list(nbcells);
514 1 akiss
  vector<vector<int> > min_list(nbcells,vector<int>(3,0));
515 1 akiss
  vector<vector<int> > max_list(nbcells,vector<int>(3,0));
516 1 akiss
517 1 akiss
#pragma omp parallel shared(wat,marge,erosion,c0,psi_list,min_list,list)
518 1 akiss
  {
519 1 akiss
  int xmin=0;
520 1 akiss
  int ymin=0;
521 1 akiss
  int zmin=0;
522 1 akiss
#pragma omp for schedule(dynamic)
523 1 akiss
  for(int i=0;i<nbcells;i++)
524 1 akiss
    {
525 1 akiss
      int ind=list[i];
526 1 akiss
      psi_list[i]=box_cell(wat,marge,erosion,c0,ind,xmin,ymin,zmin);
527 1 akiss
      min_list[i][0]=xmin;
528 1 akiss
      min_list[i][1]=ymin;
529 1 akiss
      min_list[i][2]=zmin;
530 1 akiss
      cout <<"cell "<<ind<<" initialised."<<endl;
531 1 akiss
    }
532 1 akiss
  }
533 1 akiss
  wat.assign();
534 1 akiss
535 1 akiss
  //reconstruct image of eroded cells
536 1 akiss
  CImg<unsigned short> wat_eroded=reconstruct(background,psi_list,min_list,nbcells,list);
537 1 akiss
  cout <<"saving file "<<wat_eroded_name<<"..."<<endl;
538 1 akiss
  wat_eroded.save_inr(wat_eroded_name.c_str(),tailleVoxel);
539 1 akiss
  string zip="gzip -f "+wat_eroded_name;
540 1 akiss
  if(system(zip.c_str()));
541 1 akiss
  cout <<"Eroded watershed segmentation saved in file:"<<wat_eroded_name<<endl;
542 1 akiss
543 1 akiss
  //Segmented inital = background segmentation
544 1 akiss
  CImg<unsigned char> segmented=background;
545 1 akiss
546 1 akiss
  double end1=omp_get_wtime();
547 1 akiss
  double time1=double(end1-begin);
548 1 akiss
  cout<<"Evolving cells..... "<<endl;
549 1 akiss
550 1 akiss
  //---------------------------------------------------------Edge detection
551 1 akiss
  //evolve each cell one by one, attract to maximal gradient
552 1 akiss
#pragma omp parallel shared(psi_list,min_list,g,gg,h,lam,mu,alf,beta,epsilon,dt,list)
553 1 akiss
  {
554 1 akiss
#pragma omp for schedule(dynamic)
555 1 akiss
  for(int i=0;i<nbcells;i++)
556 1 akiss
    {
557 1 akiss
      psi_list[i]=lsm_segment2(psi_list[i],g,gg,h,lam,mu,alf,beta,epsilon,dt,min_list[i]);
558 1 akiss
      cout <<"cell "<<list[i]<<" evolved."<<endl;
559 1 akiss
    }
560 1 akiss
  }
561 1 akiss
562 1 akiss
  //reconstruct image of edge detection, overlap=not segmented
563 1 akiss
  CImg<unsigned char>free=background;
564 1 akiss
  CImg<unsigned short> edge=reconstruct_overlap(background,psi_list,min_list,nbcells,free,list);
565 1 akiss
  edge.save_inr(edge_detection_name.c_str(),tailleVoxel);
566 1 akiss
  zip="gzip -f "+edge_detection_name;
567 1 akiss
  if(system(zip.c_str()));
568 1 akiss
569 1 akiss
// time measurements
570 1 akiss
  double end2=omp_get_wtime();
571 1 akiss
  double time2=double(end2-begin);
572 1 akiss
573 1 akiss
  double end=omp_get_wtime();
574 1 akiss
  double time=double(end-begin);
575 1 akiss
  cout<<"total time : "<<time<<"s"<<" (~"<<time/60<<" mn  ~"<<time/60/60<<" h)"<<endl;
576 1 akiss
  cout<<"-initialization with erosion : "<<time1<<"s"<<endl;
577 1 akiss
  cout<<"-edge detection : "<<time2<<"s"<<endl;
578 1 akiss
  file<<"total time : "<<time<<"s"<<" (~"<<time/60<<" mn  ~"<<time/60/60<<" h)"<<endl;
579 1 akiss
  file<<"-initialization with erosion : "<<time1<<"s"<<endl;
580 1 akiss
  file<<"-edge detection : "<<time2<<"s"<<endl;
581 1 akiss
  file.close();
582 1 akiss
583 1 akiss
  return 0;
584 1 akiss
}