Statistiques
| Révision :

root / src / lsm_lib.h @ 7

Historique | Voir | Annoter | Télécharger (17,91 ko)

1
/*     
2
       Copyright 2016 ENS de Lyon
3

4
       File author(s):
5
           Typhaine Moreau, Annamaria Kiss <annamaria.kiss@ens-lyon.fr.fr>
6

7
       See accompanying file LICENSE.txt
8
*/
9

    
10
#include <iostream>
11
#include <math.h>
12
#include <sstream>
13
#include <vector>
14
#include <fstream>
15
#include <algorithm>
16

    
17
#include "CImg.h"
18

    
19
using namespace cimg_library;
20
using namespace std;
21

    
22

    
23
//**************************************** GLOBAL IMAGE *************************************************************************
24

    
25
//Write an image image
26
//----------------------------------------------------------------------------
27
int imsave(string filename, float tailleVoxel[3], CImg<unsigned char> const & img)
28
{
29
          img.save_inr(filename.c_str(),tailleVoxel);
30
          string zip="gzip -f "+filename;
31
          if(system(zip.c_str()));
32
  cout<<"Image saved in file :"<<filename<<".gz"<<endl;
33
  cout<<" - Voxel size : ("<<tailleVoxel[0]<<","<<tailleVoxel[1]<<","<<tailleVoxel[2]<<")"<<endl;
34
  cout<<" - Image size : ("<<img.width()<<","<<img.height()<<","<<img.depth()<<")"<<endl;
35
  return 1;
36
}
37

    
38
//Read an image image
39
//----------------------------------------------------------------------------
40
CImg<unsigned char> imread(string &filename, float (&tailleVoxel)[3])
41
{
42
        CImg<unsigned char> img_prev;
43
        cout<<"Image read : "<<filename<<endl;
44
    if(filename.compare(filename.size()-4,4,".inr")==0)
45
    {
46
      img_prev.get_load_inr(filename.c_str(),tailleVoxel); // reads resolution
47
    }
48
  else if(filename.compare(filename.size()-7,7,".inr.gz")==0)
49
    {
50
      string oldname = filename;
51
      filename.erase(filename.size()-3);
52
      string zip="gunzip -c "+oldname+" > "+filename;
53
      if(system(zip.c_str())); // decompress image file
54
      img_prev.load(filename.c_str()); //read image
55
      img_prev.get_load_inr(filename.c_str(),tailleVoxel); // read resolution
56
      zip="rm "+filename; 
57
      if(system(zip.c_str())); //removes decompressed image    
58
    }
59
  else
60
    {cout<<"!! wrong file extension : "<<filename<<endl;
61
        }
62
  cout<<" - Voxel size : ("<<tailleVoxel[0]<<","<<tailleVoxel[1]<<","<<tailleVoxel[2]<<")"<<endl;
63
  cout<<" - Image size : ("<<img_prev.width()<<","<<img_prev.height()<<","<<img_prev.depth()<<")"<<endl;
64
  return img_prev;
65
}
66

    
67
//Invert the image
68
//----------------------------------------------------------------------------
69
CImg<unsigned char> invert_image(CImg<unsigned char> const & img)
70
{
71
  CImg<unsigned char> unity(img._width,img._height,img._depth,1,1);
72
  CImg<unsigned char> inverted = unity - img;
73
  return inverted;
74
}
75

    
76
//Add black slices on each side of the image
77
//----------------------------------------------------------------------------
78
CImg<float> add_side_slices(CImg<float> const & img, int side)
79
{
80
  int s=side*2;
81
  CImg<float> newImg(img._width+s,img._height+s,img._depth+s,1,1);
82

    
83
  cimg_forXYZ(img,x,y,z)
84
    {
85
      newImg(x+side,y+side,z+side)=img(x,y,z);   
86
    }
87
  return newImg;
88
}
89

    
90
//Remove slices
91
//----------------------------------------------------------------------------
92
CImg<float> remove_side_slices(CImg<float> const & img, int side)
93
{
94
  int s=side*2;
95
  CImg<float> newImg(img._width-s,img._height-s,img._depth-s,1,0);
96

    
97
  cimg_forXYZ(newImg,x,y,z)
98
    {
99
      newImg(x,y,z)=img(x+side,y+side,z+side);   
100
    }
101
  return newImg;
102
}
103

    
104
//Threshold linear along Z   1:background  0:cells
105
//----------------------------------------------------------------------------
106
CImg<unsigned char> threshold_linear_alongZ(CImg<float> const & img, int t1, int t2)
107
{
108
  CImg<unsigned char> outside(img._width,img._height,img._depth,1,0);
109
  for(int z=0; z<img._depth ; z++)
110
    {
111
      cimg_forXY(outside,x,y)
112
        {
113
          float thresh = t1 + (t2-t1)*(z*1.0/img._depth);
114
          if(img(x,y,z)<thresh)
115
            {outside(x,y,z)=1;}        
116
        }
117
    }
118
  outside.label();
119
  cimg_forXYZ(outside,x,y,z)
120
    {
121
      if(outside(x,y,z)>0) {outside(x,y,z)=0;}
122
      else {outside(x,y,z)=1;}
123
    }
124
  return outside;
125
}
126

    
127
//LSM contour init +c0 background, -c0 cells
128
//--------------------------------------------------------------------------
129
CImg<float> lsm_contour_init(CImg<unsigned char> const & region,int c0)
130
{
131
  CImg<float> initLSM(region._width,region._height,region._depth,1,c0);
132
  initLSM=initLSM-2*c0*region;
133
  return initLSM;
134
}
135

    
136
//Gradient 3D with central finite differences
137
//----------------------------------------------------------------------------
138
CImgList<float> gradient(CImg<float> const & img)
139
{
140
  //List of 3 images the same size as img
141
  CImgList<float> grad(3,img._width,img._height,img._depth,1,0);
142

    
143
  //Image loop with a 3*3*3 neighborhood
144
  CImg_3x3x3(I,float);
145
  cimg_for3x3x3(img,x,y,z,0,I,float)
146
    {
147
      grad(0,x,y,z) = (Incc - Ipcc)/2; //grad x = (img(x+1,y,z)-img(x-1,y,z))/2
148
      grad(1,x,y,z) = (Icnc - Icpc)/2; //grad y
149
      grad(2,x,y,z) = (Iccn - Iccp)/2; //grad z
150
    }
151
  return grad;
152
}
153

    
154
//Norm of the gradient
155
//---------------------------------------------------------------------------
156
CImg<float> gradient_norm(CImg<float> const & img)
157
{
158
  CImgList<float> grad = gradient(img);
159
  CImg<float> res(grad[0]._width,grad[0]._height,grad[0]._depth,1,0);
160
  float f=0;
161
  cimg_forXYZ(res,x,y,z)
162
    {
163
      f=grad(0,x,y,z)*grad(0,x,y,z) + grad(1,x,y,z)*grad(1,x,y,z) + grad(2,x,y,z)*grad(2,x,y,z);
164
      res(x,y,z)=sqrt(f);
165
    }
166
  return res;
167
}
168

    
169

    
170
//Edge indicator
171
//---------------------------------------------------------------------------
172
CImg<float> edge_indicator(CImgList<float> const & grad)
173
{
174
  CImg<float> res(grad[0]._width,grad[0]._height,grad[0]._depth,1,0);
175
  float f=0;
176
  cimg_forXYZ(res,x,y,z)
177
    {
178
      f=grad(0,x,y,z)*grad(0,x,y,z) + grad(1,x,y,z)*grad(1,x,y,z) + grad(2,x,y,z)*grad(2,x,y,z);
179
      res(x,y,z)=1.0/(1.0+f);
180
      //res(x,y,z)=exp(-f);
181
    }
182
  return res;
183
}
184

    
185
//Edge indicator 1 (gradient)
186
//---------------------------------------------------------------------------
187
CImg<float> edge_indicator1(CImg<float> const & img)
188
{
189
  CImgList<float> grad;
190
  grad = gradient(img);
191
  CImg<float> res(img._width,img._height,img._depth,1,0);
192
  float f=0;
193
  cimg_forXYZ(res,x,y,z)
194
    {
195
      f=grad(0,x,y,z)*grad(0,x,y,z) + grad(1,x,y,z)*grad(1,x,y,z) + grad(2,x,y,z)*grad(2,x,y,z);
196
      res(x,y,z)=1.0/(1.0+f);
197
    }
198
  return res;
199
}
200

    
201
CImg<float> edge_indicator1(CImg<float> const & img, float gamma)
202
{
203
  CImgList<float> grad;
204
  grad = gradient(img);
205
  CImg<float> res(img._width,img._height,img._depth,1,0);
206
  float f=0;
207
  cimg_forXYZ(res,x,y,z)
208
    {
209
      f=grad(0,x,y,z)*grad(0,x,y,z) + grad(1,x,y,z)*grad(1,x,y,z) + grad(2,x,y,z)*grad(2,x,y,z);
210
      res(x,y,z)=1.0/(1.0+f/gamma/gamma);
211
    }
212
  return res;
213
}
214

    
215
//Edge indicator 2 (hessienne, computed without smoothing)
216
//---------------------------------------------------------------------------
217
CImg<float> edge_indicator2(CImg<float> const & img)
218
{
219
  CImg<float> res(img._width,img._height,img._depth,1,0); 
220
  float f=0;
221
  cimg_forXYZ(res,x,y,z)
222
    {
223
    int xp=x-1;
224
        if (x==0){xp=x;}
225
        int xn=x+1;
226
        if (x==img._width-1){xn=x;}
227
        int yp=y-1;
228
        if (y==0){yp=y;}
229
        int yn=y+1;
230
        if (y==img._height-1){yn=y;}
231
        int zp=z-1;
232
        if (z==0){zp=z;}
233
        int zn=z+1;
234
        if (z==img._depth-1){zn=z;}
235

    
236
        CImg<float> hess(3,3,1,1,0);
237
        hess(0,0) = img(xp,y,z) + img(xn,y,z) - 2*img(x,y,z);          // Hxx
238
        hess(1,1) = img(x,yp,z) + img(x,yn,z) - 2*img(x,y,z);          // Hyy
239
        hess(2,2) = img(x,y,zp) + img(x,y,zn) - 2*img(x,y,z);          // Hzz
240
        hess(1,0) = hess(0,1) = (img(xp,yp,z) + img(xn,yn,z) - img(xp,yn,z) - img(xn,yp,z))/4; // Hxy = Hyx
241
        hess(2,0) = hess(0,2) = (img(xp,y,zp) + img(xn,y,zn) - img(xp,y,zn) - img(xn,y,zp))/4; // Hxz = Hzx
242
        hess(2,1) = hess(1,2) = (img(x,yp,zp) + img(x,yn,zn) - img(x,yp,zn) - img(x,yn,zp))/4; // Hyz = Hzy
243
        
244
        //val : 3 eigen values as an array, decreasing order
245
        //vec : 3 eigen vectors as a 3*3 image
246
        //have to be double or create NaN
247
        CImg<double> val,vec;
248
        hess.symmetric_eigen(val,vec);
249
        if (val[2]>0) val[2]=0;
250
        val[2]=-val[2];
251
        //res(x,y,z)=1.0/(1.0 +val[2]*(50/3.));  //h=g test4
252
    //res(x,y,z)=1.0/(1.0 +val[2]*val[2]*(50/3.)*(50/3.) );
253
    //res(x,y,z)=1.0/(1.0 +exp(-val[2]));
254
    //res(x,y,z)=exp(-val[2]);
255
    //res(x,y,z)=exp(-val[2]*val[2]);
256
    res(x,y,z)=1.0/(1.0 +val[2]*val[2]);
257
    }
258
  return res;
259
}
260

    
261
//Edge indicator 2 (hessienne, computed with smoothing)
262
//---------------------------------------------------------------------------
263
CImg<float> edge_indicator2s(CImg<float> const & img, float gamma)
264
{
265
  CImg<float> res(img._width,img._height,img._depth,1,0);
266
    
267
  // make a minimal blur before taking derivatives
268
  CImg<float> imgBlur=img.get_blur(2);
269
  
270
  float f=0;
271
  cimg_forXYZ(res,x,y,z)
272
    {
273
    int xp=x-1;
274
        if (x==0){xp=x;}
275
        int xn=x+1;
276
        if (x==img._width-1){xn=x;}
277
        int yp=y-1;
278
        if (y==0){yp=y;}
279
        int yn=y+1;
280
        if (y==img._height-1){yn=y;}
281
        int zp=z-1;
282
        if (z==0){zp=z;}
283
        int zn=z+1;
284
        if (z==img._depth-1){zn=z;}
285

    
286
        CImg<float> hess(3,3,1,1,0);
287
        hess(0,0) = imgBlur(xp,y,z) + imgBlur(xn,y,z) - 2*imgBlur(x,y,z);          // Hxx
288
        hess(1,1) = imgBlur(x,yp,z) + imgBlur(x,yn,z) - 2*imgBlur(x,y,z);          // Hyy
289
        hess(2,2) = imgBlur(x,y,zp) + imgBlur(x,y,zn) - 2*imgBlur(x,y,z);          // Hzz
290
        hess(1,0) = hess(0,1) = (imgBlur(xp,yp,z) + imgBlur(xn,yn,z) - imgBlur(xp,yn,z) - imgBlur(xn,yp,z))/4; // Hxy = Hyx
291
        hess(2,0) = hess(0,2) = (imgBlur(xp,y,zp) + imgBlur(xn,y,zn) - imgBlur(xp,y,zn) - imgBlur(xn,y,zp))/4; // Hxz = Hzx
292
        hess(2,1) = hess(1,2) = (imgBlur(x,yp,zp) + imgBlur(x,yn,zn) - imgBlur(x,yp,zn) - imgBlur(x,yn,zp))/4; // Hyz = Hzy
293
        
294
        //val : 3 eigen values as an array, decreasing order
295
        //vec : 3 eigen vectors as a 3*3 image
296
        //have to be double or create NaN
297
        CImg<double> val,vec;
298
        hess.symmetric_eigen(val,vec);
299
        if (val[2]>0) val[2]=0;
300
        val[2]=-val[2];
301
    res(x,y,z)=1.0/(1.0 +val[2]*val[2]/gamma/gamma);
302
    }
303
  return res;
304
}
305

    
306

    
307
CImg<float> edge_indicator2(CImg<float> const & img, float gamma)
308
{
309
  CImg<float> res(img._width,img._height,img._depth,1,0);
310
  float f=0;
311
  cimg_forXYZ(res,x,y,z)
312
    {
313
    int xp=x-1;
314
        if (x==0){xp=x;}
315
        int xn=x+1;
316
        if (x==img._width-1){xn=x;}
317
        int yp=y-1;
318
        if (y==0){yp=y;}
319
        int yn=y+1;
320
        if (y==img._height-1){yn=y;}
321
        int zp=z-1;
322
        if (z==0){zp=z;}
323
        int zn=z+1;
324
        if (z==img._depth-1){zn=z;}
325

    
326
        CImg<float> hess(3,3,1,1,0);
327
        hess(0,0) = img(xp,y,z) + img(xn,y,z) - 2*img(x,y,z);          // Hxx
328
        hess(1,1) = img(x,yp,z) + img(x,yn,z) - 2*img(x,y,z);          // Hyy
329
        hess(2,2) = img(x,y,zp) + img(x,y,zn) - 2*img(x,y,z);          // Hzz
330
        hess(1,0) = hess(0,1) = (img(xp,yp,z) + img(xn,yn,z) - img(xp,yn,z) - img(xn,yp,z))/4; // Hxy = Hyx
331
        hess(2,0) = hess(0,2) = (img(xp,y,zp) + img(xn,y,zn) - img(xp,y,zn) - img(xn,y,zp))/4; // Hxz = Hzx
332
        hess(2,1) = hess(1,2) = (img(x,yp,zp) + img(x,yn,zn) - img(x,yp,zn) - img(x,yn,zp))/4; // Hyz = Hzy
333
        
334
        //val : 3 eigen values as an array, decreasing order
335
        //vec : 3 eigen vectors as a 3*3 image
336
        //have to be double or create NaN
337
        CImg<double> val,vec;
338
        hess.symmetric_eigen(val,vec);
339
        if (val[2]>0) val[2]=0;
340
        //val[2]=-val[2];
341
    res(x,y,z)=1.0/(1.0 +val[2]*val[2]/gamma/gamma);
342
    }
343
  return res;
344
}
345

    
346
//Edge indicator 3 (image based)
347
//---------------------------------------------------------------------------
348
CImg<float> edge_indicator3(CImg<float> const & img)
349
{
350
  CImg<float> res(img._width,img._height,img._depth,1,0);
351
  cimg_forXYZ(res,x,y,z)
352
    {
353
      res(x,y,z)=1.0/(1.0+img(x,y,z)*img(x,y,z));
354
    }
355
  return res;
356
}
357

    
358
CImg<float> edge_indicator3(CImg<float> const & img, float gamma)
359
{
360
  CImg<float> res(img._width,img._height,img._depth,1,0);
361
  cimg_forXYZ(res,x,y,z)
362
    {
363
                res(x,y,z)=1.0/(1.0+(img(x,y,z)/gamma)*(img(x,y,z)/gamma));
364
    }
365
  return res;
366
}
367

    
368

    
369
CImg<float> edge_indicator3exp(CImg<float> const & img, float gamma)
370
{
371
  CImg<float> res(img._width,img._height,img._depth,1,0);
372
  cimg_forXYZ(res,x,y,z)
373
    {
374
                res(x,y,z)=exp(-(img(x,y,z)/gamma)*(img(x,y,z)/gamma));
375
    }
376
  return res;
377
}
378

    
379
//Edge image (based on lambda3 of the hessien)
380
//---------------------------------------------------------------------------
381
CImg<float> edge_lambda3(CImg<float> const & img)
382
{
383
  CImg<float> res(img._width,img._height,img._depth,1,0);
384
  float f=0;
385
  cimg_forXYZ(res,x,y,z)
386
    {
387
    int xp=x-1;
388
        if (x==0){xp=x;}
389
        int xn=x+1;
390
        if (x==img._width-1){xn=x;}
391
        int yp=y-1;
392
        if (y==0){yp=y;}
393
        int yn=y+1;
394
        if (y==img._height-1){yn=y;}
395
        int zp=z-1;
396
        if (z==0){zp=z;}
397
        int zn=z+1;
398
        if (z==img._depth-1){zn=z;}
399

    
400
        CImg<float> hess(3,3,1,1,0);
401
        hess(0,0) = img(xp,y,z) + img(xn,y,z) - 2*img(x,y,z);          // Hxx
402
        hess(1,1) = img(x,yp,z) + img(x,yn,z) - 2*img(x,y,z);          // Hyy
403
        hess(2,2) = img(x,y,zp) + img(x,y,zn) - 2*img(x,y,z);          // Hzz
404
        hess(1,0) = hess(0,1) = (img(xp,yp,z) + img(xn,yn,z) - img(xp,yn,z) - img(xn,yp,z))/4; // Hxy = Hyx
405
        hess(2,0) = hess(0,2) = (img(xp,y,zp) + img(xn,y,zn) - img(xp,y,zn) - img(xn,y,zp))/4; // Hxz = Hzx
406
        hess(2,1) = hess(1,2) = (img(x,yp,zp) + img(x,yn,zn) - img(x,yp,zn) - img(x,yn,zp))/4; // Hyz = Hzy
407
        
408
        //val : 3 eigen values as an array, decreasing order
409
        //vec : 3 eigen vectors as a 3*3 image
410
        //have to be double or create NaN
411
        CImg<double> val,vec;
412
        hess.symmetric_eigen(val,vec);
413
        if (val[2]>0) val[2]=0;
414
    res(x,y,z)=-val[2];
415
    }
416
  return res;
417
}
418

    
419

    
420
//Wall indicator
421
//---------------------------------------------------------------------------
422
CImg<float> wall_indicator(CImg<float> const & img)
423
{
424
  CImg<float> res(img._width,img._height,img._depth,1,0);
425
  cimg_forXYZ(res,x,y,z)
426
    {
427
      res(x,y,z)=1.0/(1.0+(img(x,y,z)*img(x,y,z)));
428
    }
429
  return res;
430
}
431

    
432
//Dirac function
433
//-------------------------------------------------------------------------
434
CImg<float> Dirac(CImg<float> const & img, float sigma)
435
{
436
  CImg<float> fImg(img._width,img._height,img._depth,1,0);
437
  float f=0;
438
  cimg_forXYZ(img,x,y,z)
439
    {
440
      if(abs(img(x,y,z))<=sigma)
441
        {
442
          f=(1.0/(2*sigma))*(1+cos(M_PI*img(x,y,z)/sigma));
443
        }
444
      else {f=0;}
445
      fImg(x,y,z)=f;
446
    }
447
  return fImg;
448
} 
449

    
450
//Normal vector
451
//------------------------------------------------------------------------
452
CImgList<float> normal_vector(CImg<float> const & img)
453
{
454
  CImgList<float> normal_vector(3,img._width,img._height,img._depth,1,0); 
455

    
456
  CImg_3x3x3(I,float);        
457
  cimg_for3x3x3(img,x,y,z,0,I,float) 
458
    {
459
      float nx = (Incc-Ipcc)/2.0;    
460
      float ny = (Icnc-Icpc)/2.0;   
461
      float nz = (Iccn-Iccp)/2.0;
462
      //border
463
      if((x==0)or(y==0)or(z==0))
464
        {nx=ny=nz=0;}
465
      if((x==img.width()-1)or(y==img.height()-1)or(z==img.depth()-1))
466
        {nx=ny=nz=0;}
467

    
468
      float norm=1;
469
      if((nx!=0)or(ny!=0)or(nz!=0))
470
        {norm = sqrt(nx*nx+ny*ny+nz*nz);}
471
 
472
      normal_vector(0,x,y,z)=nx/norm;
473
      normal_vector(1,x,y,z)=ny/norm;
474
      normal_vector(2,x,y,z)=nz/norm;
475
    }
476
  return normal_vector;
477
}
478

    
479

    
480
//Curvature
481
//------------------------------------------------------------------------
482
CImg<float> curvature2(CImgList<float> const & N)
483
{
484
  CImg<float> K(N[0]._width,N[0]._height,N[0]._depth,1,0);
485
  cimg_forXYZ(N[0],x,y,z)
486
    {
487
      float kx=0;
488
      float ky=0;
489
      float kz=0;
490
      if(x==0)
491
        {kx=N[0](x+1,y,z)-N[0](x,y,z);}
492
      else if(x==N[0]._width-1)
493
        {kx=N[0](x,y,z)-N[0](x-1,y,z);}
494
      else
495
        {kx=(N[0](x+1,y,z)-N[0](x-1,y,z))/2.0;}
496

    
497
     if(y==0)
498
        {ky=N[1](x,y+1,z)-N[1](x,y,z);}
499
      else if(y==N[1]._height-1)
500
        {ky=N[1](x,y,z)-N[1](x,y-1,z);}
501
      else
502
        {ky=(N[1](x,y+1,z)-N[1](x,y-1,z))/2.0;}
503

    
504
     if(z==0)
505
        {kz=N[2](x,y,z+1)-N[2](x,y,z);}
506
      else if(z==N[2]._depth-1)
507
        {kz=N[2](x,y,z)-N[2](x,y,z-1);}
508
      else
509
        {kz=(N[2](x,y,z+1)-N[2](x,y,z-1))/2.0;}
510

    
511
     K(x,y,z)=kx+ky+kz;
512
    }
513
  return K;
514
}
515

    
516
// Compute image laplacian
517
//--------------------------------------------------------------------
518
CImg<float> laplacian(CImg<float> const & img)
519
{
520
  CImg<float> laplacian(img._width,img._height,img._depth,1,0);
521
  CImg_3x3x3(I,float);
522
  cimg_for3x3x3(img,x,y,z,0,I,float)
523
    {
524
      laplacian(x,y,z) =Incc+Ipcc+Icnc+Icpc+Iccn+Iccp - 6*Iccc;
525
    }
526
  return laplacian;
527
}
528

    
529
//Evolution AK2 contour
530
//-------------------------------------------------------------------------
531
CImg<float> evolution_AK2_contour(CImg<float> u, CImg<float> const & g, CImgList<float> const & gg, CImg<float> const & h, int lam, float mu, float alf, float beta, float epsilon, int dt)
532
{
533
  CImg<float> diracU=Dirac(u,epsilon); 
534
  CImgList<float> N=normal_vector(u);
535
  CImg<float> K=curvature2(N);
536
  CImg<float> L=laplacian(u);
537
  float term=0;
538

    
539
  cimg_forXYZ(u,x,y,z)
540
    {
541
      term=0;
542
      if (diracU(x,y,z)!=0)
543
        {
544
          //weighted length term
545
          if(lam!=0)
546
            {term=( gg(0,x,y,z)*N(0,x,y,z) + gg(1,x,y,z)*N(1,x,y,z) + gg(2,x,y,z)*N(2,x,y,z) + (g(x,y,z)*K(x,y,z))) *lam;}
547
          //length term
548
          if(beta!=0)
549
            {term=term + K(x,y,z)*beta;}
550
          //weighted area term
551
          if(alf!=0)
552
            {term=term + h(x,y,z)*alf;}
553
          //regularization
554
          term=term*diracU(x,y,z);
555
          //penalizing term
556
          term=term + (L(x,y,z)-K(x,y,z))*mu;
557
        }
558
      else
559
        {
560
          //penalizing term
561
          term=(L(x,y,z)-K(x,y,z))*mu;
562
        }
563
      
564
      u(x,y,z)=u(x,y,z) + term*dt;
565
    }
566
  return u;
567
}
568

    
569
//Evolution AK2 contour cells
570
//-------------------------------------------------------------------------
571
CImg<float> evolution_AK2_contour_cells(CImg<float> u, CImg<float> const & g, CImgList<float> const & gg, CImg<float> const & h, int lam, float mu, float alf, int beta, float epsilon, int dt, vector<int> min_list)
572
{
573
  CImg<float> diracU=Dirac(u,epsilon); 
574
  CImgList<float> N=normal_vector(u);
575
  CImg<float> K=curvature2(N);
576
  CImg<float> L=laplacian(u);
577
  float term=0;
578
  int xmax=u._width;
579
  int ymax=u._height;
580
  int zmax=u._depth;
581
  int c0=-4;
582

    
583
  cimg_forXYZ(u,x,y,z)
584
    {
585
      int xb=x+min_list[0];
586
      int yb=y+min_list[1];
587
      int zb=z+min_list[2];
588
      term=0;
589
      if (diracU(x,y,z)!=0)
590
        {
591
          //weighted length term
592
          if(lam!=0)
593
            {term=( gg(0,xb,yb,zb)*N(0,x,y,z) + gg(1,xb,yb,zb)*N(1,x,y,z) + gg(2,xb,yb,zb)*N(2,x,y,z) + (g(xb,yb,zb)*K(x,y,z))) *lam;}
594
          //length term
595
          if(beta!=0)
596
            {term=term + K(x,y,z)*beta;}
597
          //weighted area term
598
          if(alf!=0)
599
            {term=term + h(xb,yb,zb)*alf;}            
600
          //regularization
601
          term=term*diracU(x,y,z);
602
          //penalizing term
603
          term=term + (L(x,y,z)-K(x,y,z))*mu;
604
        }
605
      else
606
        {
607
          //penalizing term
608
          term=(L(x,y,z)-K(x,y,z))*mu;
609
        }
610
      // computing the evolution
611
      u(x,y,z)=u(x,y,z) + term*dt;
612
      // box boundary regularisation
613
      if ((x==0) or (x==xmax) or (x==1) or (x==xmax-1) or(y==0) or (y==ymax)or(y==1) or (y==ymax-1) or (z==0) or (z==zmax)or (z==1) or (z==zmax-1))
614
      {u(x,y,z)=c0;}
615
    }
616
  return u;
617
}