Statistiques
| Révision :

root / src / lsm_lib.h @ 21

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

1
#include <iostream>
2
#include <math.h>
3
#include <sstream>
4
#include <vector>
5
#include <fstream>
6
#include <algorithm>
7

    
8
#include "CImg.h"
9

    
10
using namespace cimg_library;
11
using namespace std;
12

    
13

    
14
//**************************************** GLOBAL IMAGE *************************************************************************
15

    
16
//Invert the image
17
//----------------------------------------------------------------------------
18
CImg<unsigned char> invert_image(CImg<unsigned char> const & img)
19
{
20
  CImg<unsigned char> unity(img._width,img._height,img._depth,1,1);
21
  CImg<unsigned char> inverted = unity - img;
22
  return inverted;
23
}
24

    
25
//Add black slices on each side of the image
26
//----------------------------------------------------------------------------
27
CImg<float> add_side_slices(CImg<float> const & img, int side)
28
{
29
  int s=side*2;
30
  CImg<float> newImg(img._width+s,img._height+s,img._depth+s,1,1);
31

    
32
  cimg_forXYZ(img,x,y,z)
33
    {
34
      newImg(x+side,y+side,z+side)=img(x,y,z);   
35
    }
36
  return newImg;
37
}
38

    
39
//Remove slices
40
//----------------------------------------------------------------------------
41
CImg<float> remove_side_slices(CImg<float> const & img, int side)
42
{
43
  int s=side*2;
44
  CImg<float> newImg(img._width-s,img._height-s,img._depth-s,1,0);
45

    
46
  cimg_forXYZ(newImg,x,y,z)
47
    {
48
      newImg(x,y,z)=img(x+side,y+side,z+side);   
49
    }
50
  return newImg;
51
}
52

    
53
//Threshold linear along Z   1:background  0:cells
54
//----------------------------------------------------------------------------
55
CImg<unsigned char> threshold_linear_alongZ(CImg<float> const & img, int t1, int t2)
56
{
57
  CImg<unsigned char> outside(img._width,img._height,img._depth,1,0);
58
  for(int z=0; z<img._depth ; z++)
59
    {
60
      cimg_forXY(outside,x,y)
61
        {
62
          float thresh = t1 + (t2-t1)*(z*1.0/img._depth);
63
          if(img(x,y,z)<thresh)
64
            {outside(x,y,z)=1;}        
65
        }
66
    }
67
  outside.label();
68
  cimg_forXYZ(outside,x,y,z)
69
    {
70
      if(outside(x,y,z)>0) {outside(x,y,z)=0;}
71
      else {outside(x,y,z)=1;}
72
    }
73
  return outside;
74
}
75

    
76
//LSM contour init +c0 background, -c0 cells
77
//--------------------------------------------------------------------------
78
CImg<float> lsm_contour_init(CImg<unsigned char> const & region,int c0)
79
{
80
  CImg<float> initLSM(region._width,region._height,region._depth,1,c0);
81
  initLSM=initLSM-2*c0*region;
82
  return initLSM;
83
}
84

    
85
//Gradient 3D with central finite differences
86
//----------------------------------------------------------------------------
87
CImgList<float> gradient(CImg<float> const & img)
88
{
89
  //List of 3 images the same size as img
90
  CImgList<float> grad(3,img._width,img._height,img._depth,1,0);
91

    
92
  //Image loop with a 3*3*3 neighborhood
93
  CImg_3x3x3(I,float);
94
  cimg_for3x3x3(img,x,y,z,0,I,float)
95
    {
96
      grad(0,x,y,z) = (Incc - Ipcc)/2; //grad x = (img(x+1,y,z)-img(x-1,y,z))/2
97
      grad(1,x,y,z) = (Icnc - Icpc)/2; //grad y
98
      grad(2,x,y,z) = (Iccn - Iccp)/2; //grad z
99
    }
100
  return grad;
101
}
102

    
103
//Norm of the gradient
104
//---------------------------------------------------------------------------
105
CImg<float> gradient_norm(CImg<float> const & img)
106
{
107
  CImgList<float> grad = gradient(img);
108
  CImg<float> res(grad[0]._width,grad[0]._height,grad[0]._depth,1,0);
109
  float f=0;
110
  cimg_forXYZ(res,x,y,z)
111
    {
112
      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);
113
      res(x,y,z)=sqrt(f);
114
    }
115
  return res;
116
}
117

    
118

    
119
//Edge indicator
120
//---------------------------------------------------------------------------
121
CImg<float> edge_indicator(CImgList<float> const & grad)
122
{
123
  CImg<float> res(grad[0]._width,grad[0]._height,grad[0]._depth,1,0);
124
  float f=0;
125
  cimg_forXYZ(res,x,y,z)
126
    {
127
      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);
128
      res(x,y,z)=1.0/(1.0+f);
129
      //res(x,y,z)=exp(-f);
130
    }
131
  return res;
132
}
133

    
134
//Edge indicator 1 (gradient)
135
//---------------------------------------------------------------------------
136
CImg<float> edge_indicator1(CImg<float> const & img)
137
{
138
  CImgList<float> grad;
139
  grad = gradient(img);
140
  CImg<float> res(img._width,img._height,img._depth,1,0);
141
  float f=0;
142
  cimg_forXYZ(res,x,y,z)
143
    {
144
      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);
145
      res(x,y,z)=1.0/(1.0+f);
146
    }
147
  return res;
148
}
149

    
150
CImg<float> edge_indicator1(CImg<float> const & img, float gamma)
151
{
152
  CImgList<float> grad;
153
  grad = gradient(img);
154
  CImg<float> res(img._width,img._height,img._depth,1,0);
155
  float f=0;
156
  cimg_forXYZ(res,x,y,z)
157
    {
158
      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);
159
      res(x,y,z)=1.0/(1.0+f/gamma/gamma);
160
    }
161
  return res;
162
}
163

    
164
//Edge indicator 2 (hessienne, computed without smoothing)
165
//---------------------------------------------------------------------------
166
CImg<float> edge_indicator2(CImg<float> const & img)
167
{
168
  CImg<float> res(img._width,img._height,img._depth,1,0); 
169
  float f=0;
170
  cimg_forXYZ(res,x,y,z)
171
    {
172
    int xp=x-1;
173
        if (x==0){xp=x;}
174
        int xn=x+1;
175
        if (x==img._width-1){xn=x;}
176
        int yp=y-1;
177
        if (y==0){yp=y;}
178
        int yn=y+1;
179
        if (y==img._height-1){yn=y;}
180
        int zp=z-1;
181
        if (z==0){zp=z;}
182
        int zn=z+1;
183
        if (z==img._depth-1){zn=z;}
184

    
185
        CImg<float> hess(3,3,1,1,0);
186
        hess(0,0) = img(xp,y,z) + img(xn,y,z) - 2*img(x,y,z);          // Hxx
187
        hess(1,1) = img(x,yp,z) + img(x,yn,z) - 2*img(x,y,z);          // Hyy
188
        hess(2,2) = img(x,y,zp) + img(x,y,zn) - 2*img(x,y,z);          // Hzz
189
        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
190
        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
191
        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
192
        
193
        //val : 3 eigen values as an array, decreasing order
194
        //vec : 3 eigen vectors as a 3*3 image
195
        //have to be double or create NaN
196
        CImg<double> val,vec;
197
        hess.symmetric_eigen(val,vec);
198
        if (val[2]>0) val[2]=0;
199
        val[2]=-val[2];
200
        //res(x,y,z)=1.0/(1.0 +val[2]*(50/3.));  //h=g test4
201
    //res(x,y,z)=1.0/(1.0 +val[2]*val[2]*(50/3.)*(50/3.) );
202
    //res(x,y,z)=1.0/(1.0 +exp(-val[2]));
203
    //res(x,y,z)=exp(-val[2]);
204
    //res(x,y,z)=exp(-val[2]*val[2]);
205
    res(x,y,z)=1.0/(1.0 +val[2]*val[2]);
206
    }
207
  return res;
208
}
209

    
210
//Edge indicator 2 (hessienne, computed with smoothing)
211
//---------------------------------------------------------------------------
212
CImg<float> edge_indicator2s(CImg<float> const & img, float gamma)
213
{
214
  CImg<float> res(img._width,img._height,img._depth,1,0);
215
    
216
  // make a minimal blur before taking derivatives
217
  CImg<float> imgBlur=img.get_blur(2);
218
  
219
  float f=0;
220
  cimg_forXYZ(res,x,y,z)
221
    {
222
    int xp=x-1;
223
        if (x==0){xp=x;}
224
        int xn=x+1;
225
        if (x==img._width-1){xn=x;}
226
        int yp=y-1;
227
        if (y==0){yp=y;}
228
        int yn=y+1;
229
        if (y==img._height-1){yn=y;}
230
        int zp=z-1;
231
        if (z==0){zp=z;}
232
        int zn=z+1;
233
        if (z==img._depth-1){zn=z;}
234

    
235
        CImg<float> hess(3,3,1,1,0);
236
        hess(0,0) = imgBlur(xp,y,z) + imgBlur(xn,y,z) - 2*imgBlur(x,y,z);          // Hxx
237
        hess(1,1) = imgBlur(x,yp,z) + imgBlur(x,yn,z) - 2*imgBlur(x,y,z);          // Hyy
238
        hess(2,2) = imgBlur(x,y,zp) + imgBlur(x,y,zn) - 2*imgBlur(x,y,z);          // Hzz
239
        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
240
        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
241
        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
242
        
243
        //val : 3 eigen values as an array, decreasing order
244
        //vec : 3 eigen vectors as a 3*3 image
245
        //have to be double or create NaN
246
        CImg<double> val,vec;
247
        hess.symmetric_eigen(val,vec);
248
        if (val[2]>0) val[2]=0;
249
        val[2]=-val[2];
250
    res(x,y,z)=1.0/(1.0 +val[2]*val[2]/gamma/gamma);
251
    }
252
  return res;
253
}
254

    
255

    
256
CImg<float> edge_indicator2(CImg<float> const & img, float gamma)
257
{
258
  CImg<float> res(img._width,img._height,img._depth,1,0);
259
  float f=0;
260
  cimg_forXYZ(res,x,y,z)
261
    {
262
    int xp=x-1;
263
        if (x==0){xp=x;}
264
        int xn=x+1;
265
        if (x==img._width-1){xn=x;}
266
        int yp=y-1;
267
        if (y==0){yp=y;}
268
        int yn=y+1;
269
        if (y==img._height-1){yn=y;}
270
        int zp=z-1;
271
        if (z==0){zp=z;}
272
        int zn=z+1;
273
        if (z==img._depth-1){zn=z;}
274

    
275
        CImg<float> hess(3,3,1,1,0);
276
        hess(0,0) = img(xp,y,z) + img(xn,y,z) - 2*img(x,y,z);          // Hxx
277
        hess(1,1) = img(x,yp,z) + img(x,yn,z) - 2*img(x,y,z);          // Hyy
278
        hess(2,2) = img(x,y,zp) + img(x,y,zn) - 2*img(x,y,z);          // Hzz
279
        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
280
        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
281
        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
282
        
283
        //val : 3 eigen values as an array, decreasing order
284
        //vec : 3 eigen vectors as a 3*3 image
285
        //have to be double or create NaN
286
        CImg<double> val,vec;
287
        hess.symmetric_eigen(val,vec);
288
        if (val[2]>0) val[2]=0;
289
        //val[2]=-val[2];
290
    res(x,y,z)=1.0/(1.0 +val[2]*val[2]/gamma/gamma);
291
    }
292
  return res;
293
}
294

    
295
//Edge indicator 3 (image based)
296
//---------------------------------------------------------------------------
297
CImg<float> edge_indicator3(CImg<float> const & img)
298
{
299
  CImg<float> res(img._width,img._height,img._depth,1,0);
300
  cimg_forXYZ(res,x,y,z)
301
    {
302
      res(x,y,z)=1.0/(1.0+img(x,y,z)*img(x,y,z));
303
    }
304
  return res;
305
}
306

    
307
CImg<float> edge_indicator3(CImg<float> const & img, float gamma)
308
{
309
  CImg<float> res(img._width,img._height,img._depth,1,0);
310
  cimg_forXYZ(res,x,y,z)
311
    {
312
                res(x,y,z)=1.0/(1.0+(img(x,y,z)/gamma)*(img(x,y,z)/gamma));
313
    }
314
  return res;
315
}
316

    
317
//Edge image (based on lambda3 of the hessien)
318
//---------------------------------------------------------------------------
319
CImg<float> edge_lambda3(CImg<float> const & img)
320
{
321
  CImg<float> res(img._width,img._height,img._depth,1,0);
322
  float f=0;
323
  cimg_forXYZ(res,x,y,z)
324
    {
325
    int xp=x-1;
326
        if (x==0){xp=x;}
327
        int xn=x+1;
328
        if (x==img._width-1){xn=x;}
329
        int yp=y-1;
330
        if (y==0){yp=y;}
331
        int yn=y+1;
332
        if (y==img._height-1){yn=y;}
333
        int zp=z-1;
334
        if (z==0){zp=z;}
335
        int zn=z+1;
336
        if (z==img._depth-1){zn=z;}
337

    
338
        CImg<float> hess(3,3,1,1,0);
339
        hess(0,0) = img(xp,y,z) + img(xn,y,z) - 2*img(x,y,z);          // Hxx
340
        hess(1,1) = img(x,yp,z) + img(x,yn,z) - 2*img(x,y,z);          // Hyy
341
        hess(2,2) = img(x,y,zp) + img(x,y,zn) - 2*img(x,y,z);          // Hzz
342
        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
343
        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
344
        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
345
        
346
        //val : 3 eigen values as an array, decreasing order
347
        //vec : 3 eigen vectors as a 3*3 image
348
        //have to be double or create NaN
349
        CImg<double> val,vec;
350
        hess.symmetric_eigen(val,vec);
351
        if (val[2]>0) val[2]=0;
352
    res(x,y,z)=-val[2];
353
    }
354
  return res;
355
}
356

    
357

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

    
370
//Dirac function
371
//-------------------------------------------------------------------------
372
CImg<float> Dirac(CImg<float> const & img, float sigma)
373
{
374
  CImg<float> fImg(img._width,img._height,img._depth,1,0);
375
  float f=0;
376
  cimg_forXYZ(img,x,y,z)
377
    {
378
      if(abs(img(x,y,z))<=sigma)
379
        {
380
          f=(1.0/(2*sigma))*(1+cos(M_PI*img(x,y,z)/sigma));
381
        }
382
      else {f=0;}
383
      fImg(x,y,z)=f;
384
    }
385
  return fImg;
386
} 
387

    
388
//Normal vector
389
//------------------------------------------------------------------------
390
CImgList<float> normal_vector(CImg<float> const & img)
391
{
392
  CImgList<float> normal_vector(3,img._width,img._height,img._depth,1,0); 
393

    
394
  CImg_3x3x3(I,float);        
395
  cimg_for3x3x3(img,x,y,z,0,I,float) 
396
    {
397
      float nx = (Incc-Ipcc)/2.0;    
398
      float ny = (Icnc-Icpc)/2.0;   
399
      float nz = (Iccn-Iccp)/2.0;
400
      //border
401
      if((x==0)or(y==0)or(z==0))
402
        {nx=ny=nz=0;}
403
      if((x==img.width()-1)or(y==img.height()-1)or(z==img.depth()-1))
404
        {nx=ny=nz=0;}
405

    
406
      float norm=1;
407
      if((nx!=0)or(ny!=0)or(nz!=0))
408
        {norm = sqrt(nx*nx+ny*ny+nz*nz);}
409
 
410
      normal_vector(0,x,y,z)=nx/norm;
411
      normal_vector(1,x,y,z)=ny/norm;
412
      normal_vector(2,x,y,z)=nz/norm;
413
    }
414
  return normal_vector;
415
}
416

    
417

    
418
//Curvature
419
//------------------------------------------------------------------------
420
CImg<float> curvature2(CImgList<float> const & N)
421
{
422
  CImg<float> K(N[0]._width,N[0]._height,N[0]._depth,1,0);
423
  cimg_forXYZ(N[0],x,y,z)
424
    {
425
      float kx=0;
426
      float ky=0;
427
      float kz=0;
428
      if(x==0)
429
        {kx=N[0](x+1,y,z)-N[0](x,y,z);}
430
      else if(x==N[0]._width-1)
431
        {kx=N[0](x,y,z)-N[0](x-1,y,z);}
432
      else
433
        {kx=(N[0](x+1,y,z)-N[0](x-1,y,z))/2.0;}
434

    
435
     if(y==0)
436
        {ky=N[1](x,y+1,z)-N[1](x,y,z);}
437
      else if(y==N[1]._height-1)
438
        {ky=N[1](x,y,z)-N[1](x,y-1,z);}
439
      else
440
        {ky=(N[1](x,y+1,z)-N[1](x,y-1,z))/2.0;}
441

    
442
     if(z==0)
443
        {kz=N[2](x,y,z+1)-N[2](x,y,z);}
444
      else if(z==N[2]._depth-1)
445
        {kz=N[2](x,y,z)-N[2](x,y,z-1);}
446
      else
447
        {kz=(N[2](x,y,z+1)-N[2](x,y,z-1))/2.0;}
448

    
449
     K(x,y,z)=kx+ky+kz;
450
    }
451
  return K;
452
}
453

    
454
// Compute image laplacian
455
//--------------------------------------------------------------------
456
CImg<float> laplacian(CImg<float> const & img)
457
{
458
  CImg<float> laplacian(img._width,img._height,img._depth,1,0);
459
  CImg_3x3x3(I,float);
460
  cimg_for3x3x3(img,x,y,z,0,I,float)
461
    {
462
      laplacian(x,y,z) =Incc+Ipcc+Icnc+Icpc+Iccn+Iccp - 6*Iccc;
463
    }
464
  return laplacian;
465
}
466

    
467
//Evolution AK2 contour
468
//-------------------------------------------------------------------------
469
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)
470
{
471
  CImg<float> diracU=Dirac(u,epsilon); 
472
  CImgList<float> N=normal_vector(u);
473
  CImg<float> K=curvature2(N);
474
  CImg<float> L=laplacian(u);
475
  float term=0;
476

    
477
  cimg_forXYZ(u,x,y,z)
478
    {
479
      term=0;
480
      if (diracU(x,y,z)!=0)
481
        {
482
          //weighted length term
483
          if(lam!=0)
484
            {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;}
485
          //length term
486
          if(beta!=0)
487
            {term=term + K(x,y,z)*beta;}
488
          //weighted area term
489
          if(alf!=0)
490
            {term=term + h(x,y,z)*alf;}
491
          //regularization
492
          term=term*diracU(x,y,z);
493
          //penalizing term
494
          term=term + (L(x,y,z)-K(x,y,z))*mu;
495
        }
496
      else
497
        {
498
          //penalizing term
499
          term=(L(x,y,z)-K(x,y,z))*mu;
500
        }
501
      
502
      u(x,y,z)=u(x,y,z) + term*dt;
503
    }
504
  return u;
505
}
506

    
507
//Evolution AK2 contour cells
508
//-------------------------------------------------------------------------
509
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)
510
{
511
  CImg<float> diracU=Dirac(u,epsilon); 
512
  CImgList<float> N=normal_vector(u);
513
  CImg<float> K=curvature2(N);
514
  CImg<float> L=laplacian(u);
515
  float term=0;
516

    
517

    
518
  cimg_forXYZ(u,x,y,z)
519
    {
520
      int xb=x+min_list[0];
521
      int yb=y+min_list[1];
522
      int zb=z+min_list[2];
523
      term=0;
524
      if (diracU(x,y,z)!=0)
525
        {
526
          //weighted length term
527
          if(lam!=0)
528
            {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;}
529
          //length term
530
          if(beta!=0)
531
            {term=term + K(x,y,z)*beta;}
532
          //weighted area term
533
          if(alf!=0)
534
            {term=term + h(xb,yb,zb)*alf;}            
535
          //regularization
536
          term=term*diracU(x,y,z);
537
          //penalizing term
538
          term=term + (L(x,y,z)-K(x,y,z))*mu;
539
        }
540
      else
541
        {
542
          //penalizing term
543
          term=(L(x,y,z)-K(x,y,z))*mu;
544
        }
545
      
546
      u(x,y,z)=u(x,y,z) + term*dt;
547
    }
548
  return u;
549
}
550

    
551
//Evolution AK2 contour INTERRACT
552
//-------------------------------------------------------------------------
553
CImg<float> evolution_AK2_contour_interact(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, CImg<unsigned char> const & free, vector<int>min_list)
554
{
555
  CImg<float> diracU=Dirac(u,epsilon); 
556
  CImgList<float> N=normal_vector(u);
557
  CImg<float> K=curvature2(N);
558
  CImg<float> L=laplacian(u);
559
  float term=0;
560

    
561
  cimg_forXYZ(u,x,y,z)
562
    {
563
      int xb=x+min_list[0];
564
      int yb=y+min_list[1];
565
      int zb=z+min_list[2];
566
      term=0;
567
      if(free(xb,yb,zb)==0)
568
        {
569
          if (diracU(x,y,z)!=0)
570
            {
571
              //weighted length term
572
              if(lam!=0)
573
                {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;}
574
              //length term
575
              if(beta!=0)
576
                {term=term + K(x,y,z)*beta;}
577
              //weighted area term
578
              if(alf!=0)
579
                {term=term + h(xb,yb,zb)*alf;}
580
              //regularization
581
              term=term*diracU(x,y,z);
582
              //penalizing term
583
              term=term + (L(x,y,z)-K(x,y,z))*mu;
584
            }
585
          else
586
            {
587
              //penalizing term
588
              term=(L(x,y,z)-K(x,y,z))*mu;
589
            }        
590
          u(x,y,z)=u(x,y,z) + term*dt;
591
        }
592
    }
593
  return u;
594
}