Statistiques
| Révision :

root / src / lsm_lib.h @ 1

Historique | Voir | Annoter | Télécharger (15,99 ko)

1 1 akiss
/*
2 1 akiss
       Copyright 2016 ENS de Lyon
3 1 akiss

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

7 1 akiss
       See accompanying file LICENSE.txt
8 1 akiss
*/
9 1 akiss
10 1 akiss
#include <iostream>
11 1 akiss
#include <math.h>
12 1 akiss
#include <sstream>
13 1 akiss
#include <vector>
14 1 akiss
#include <fstream>
15 1 akiss
#include <algorithm>
16 1 akiss
17 1 akiss
#include "CImg.h"
18 1 akiss
19 1 akiss
using namespace cimg_library;
20 1 akiss
using namespace std;
21 1 akiss
22 1 akiss
23 1 akiss
//**************************************** GLOBAL IMAGE *************************************************************************
24 1 akiss
25 1 akiss
//Invert the image
26 1 akiss
//----------------------------------------------------------------------------
27 1 akiss
CImg<unsigned char> invert_image(CImg<unsigned char> const & img)
28 1 akiss
{
29 1 akiss
  CImg<unsigned char> unity(img._width,img._height,img._depth,1,1);
30 1 akiss
  CImg<unsigned char> inverted = unity - img;
31 1 akiss
  return inverted;
32 1 akiss
}
33 1 akiss
34 1 akiss
//Add black slices on each side of the image
35 1 akiss
//----------------------------------------------------------------------------
36 1 akiss
CImg<float> add_side_slices(CImg<float> const & img, int side)
37 1 akiss
{
38 1 akiss
  int s=side*2;
39 1 akiss
  CImg<float> newImg(img._width+s,img._height+s,img._depth+s,1,1);
40 1 akiss
41 1 akiss
  cimg_forXYZ(img,x,y,z)
42 1 akiss
    {
43 1 akiss
      newImg(x+side,y+side,z+side)=img(x,y,z);
44 1 akiss
    }
45 1 akiss
  return newImg;
46 1 akiss
}
47 1 akiss
48 1 akiss
//Remove slices
49 1 akiss
//----------------------------------------------------------------------------
50 1 akiss
CImg<float> remove_side_slices(CImg<float> const & img, int side)
51 1 akiss
{
52 1 akiss
  int s=side*2;
53 1 akiss
  CImg<float> newImg(img._width-s,img._height-s,img._depth-s,1,0);
54 1 akiss
55 1 akiss
  cimg_forXYZ(newImg,x,y,z)
56 1 akiss
    {
57 1 akiss
      newImg(x,y,z)=img(x+side,y+side,z+side);
58 1 akiss
    }
59 1 akiss
  return newImg;
60 1 akiss
}
61 1 akiss
62 1 akiss
//Threshold linear along Z   1:background  0:cells
63 1 akiss
//----------------------------------------------------------------------------
64 1 akiss
CImg<unsigned char> threshold_linear_alongZ(CImg<float> const & img, int t1, int t2)
65 1 akiss
{
66 1 akiss
  CImg<unsigned char> outside(img._width,img._height,img._depth,1,0);
67 1 akiss
  for(int z=0; z<img._depth ; z++)
68 1 akiss
    {
69 1 akiss
      cimg_forXY(outside,x,y)
70 1 akiss
        {
71 1 akiss
          float thresh = t1 + (t2-t1)*(z*1.0/img._depth);
72 1 akiss
          if(img(x,y,z)<thresh)
73 1 akiss
            {outside(x,y,z)=1;}
74 1 akiss
        }
75 1 akiss
    }
76 1 akiss
  outside.label();
77 1 akiss
  cimg_forXYZ(outside,x,y,z)
78 1 akiss
    {
79 1 akiss
      if(outside(x,y,z)>0) {outside(x,y,z)=0;}
80 1 akiss
      else {outside(x,y,z)=1;}
81 1 akiss
    }
82 1 akiss
  return outside;
83 1 akiss
}
84 1 akiss
85 1 akiss
//LSM contour init +c0 background, -c0 cells
86 1 akiss
//--------------------------------------------------------------------------
87 1 akiss
CImg<float> lsm_contour_init(CImg<unsigned char> const & region,int c0)
88 1 akiss
{
89 1 akiss
  CImg<float> initLSM(region._width,region._height,region._depth,1,c0);
90 1 akiss
  initLSM=initLSM-2*c0*region;
91 1 akiss
  return initLSM;
92 1 akiss
}
93 1 akiss
94 1 akiss
//Gradient 3D with central finite differences
95 1 akiss
//----------------------------------------------------------------------------
96 1 akiss
CImgList<float> gradient(CImg<float> const & img)
97 1 akiss
{
98 1 akiss
  //List of 3 images the same size as img
99 1 akiss
  CImgList<float> grad(3,img._width,img._height,img._depth,1,0);
100 1 akiss
101 1 akiss
  //Image loop with a 3*3*3 neighborhood
102 1 akiss
  CImg_3x3x3(I,float);
103 1 akiss
  cimg_for3x3x3(img,x,y,z,0,I,float)
104 1 akiss
    {
105 1 akiss
      grad(0,x,y,z) = (Incc - Ipcc)/2; //grad x = (img(x+1,y,z)-img(x-1,y,z))/2
106 1 akiss
      grad(1,x,y,z) = (Icnc - Icpc)/2; //grad y
107 1 akiss
      grad(2,x,y,z) = (Iccn - Iccp)/2; //grad z
108 1 akiss
    }
109 1 akiss
  return grad;
110 1 akiss
}
111 1 akiss
112 1 akiss
//Norm of the gradient
113 1 akiss
//---------------------------------------------------------------------------
114 1 akiss
CImg<float> gradient_norm(CImg<float> const & img)
115 1 akiss
{
116 1 akiss
  CImgList<float> grad = gradient(img);
117 1 akiss
  CImg<float> res(grad[0]._width,grad[0]._height,grad[0]._depth,1,0);
118 1 akiss
  float f=0;
119 1 akiss
  cimg_forXYZ(res,x,y,z)
120 1 akiss
    {
121 1 akiss
      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);
122 1 akiss
      res(x,y,z)=sqrt(f);
123 1 akiss
    }
124 1 akiss
  return res;
125 1 akiss
}
126 1 akiss
127 1 akiss
128 1 akiss
//Edge indicator
129 1 akiss
//---------------------------------------------------------------------------
130 1 akiss
CImg<float> edge_indicator(CImgList<float> const & grad)
131 1 akiss
{
132 1 akiss
  CImg<float> res(grad[0]._width,grad[0]._height,grad[0]._depth,1,0);
133 1 akiss
  float f=0;
134 1 akiss
  cimg_forXYZ(res,x,y,z)
135 1 akiss
    {
136 1 akiss
      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);
137 1 akiss
      res(x,y,z)=1.0/(1.0+f);
138 1 akiss
      //res(x,y,z)=exp(-f);
139 1 akiss
    }
140 1 akiss
  return res;
141 1 akiss
}
142 1 akiss
143 1 akiss
//Edge indicator 1 (gradient)
144 1 akiss
//---------------------------------------------------------------------------
145 1 akiss
CImg<float> edge_indicator1(CImg<float> const & img)
146 1 akiss
{
147 1 akiss
  CImgList<float> grad;
148 1 akiss
  grad = gradient(img);
149 1 akiss
  CImg<float> res(img._width,img._height,img._depth,1,0);
150 1 akiss
  float f=0;
151 1 akiss
  cimg_forXYZ(res,x,y,z)
152 1 akiss
    {
153 1 akiss
      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);
154 1 akiss
      res(x,y,z)=1.0/(1.0+f);
155 1 akiss
    }
156 1 akiss
  return res;
157 1 akiss
}
158 1 akiss
159 1 akiss
CImg<float> edge_indicator1(CImg<float> const & img, float gamma)
160 1 akiss
{
161 1 akiss
  CImgList<float> grad;
162 1 akiss
  grad = gradient(img);
163 1 akiss
  CImg<float> res(img._width,img._height,img._depth,1,0);
164 1 akiss
  float f=0;
165 1 akiss
  cimg_forXYZ(res,x,y,z)
166 1 akiss
    {
167 1 akiss
      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);
168 1 akiss
      res(x,y,z)=1.0/(1.0+f/gamma/gamma);
169 1 akiss
    }
170 1 akiss
  return res;
171 1 akiss
}
172 1 akiss
173 1 akiss
//Edge indicator 2 (hessienne, computed without smoothing)
174 1 akiss
//---------------------------------------------------------------------------
175 1 akiss
CImg<float> edge_indicator2(CImg<float> const & img)
176 1 akiss
{
177 1 akiss
  CImg<float> res(img._width,img._height,img._depth,1,0);
178 1 akiss
  float f=0;
179 1 akiss
  cimg_forXYZ(res,x,y,z)
180 1 akiss
    {
181 1 akiss
    int xp=x-1;
182 1 akiss
        if (x==0){xp=x;}
183 1 akiss
        int xn=x+1;
184 1 akiss
        if (x==img._width-1){xn=x;}
185 1 akiss
        int yp=y-1;
186 1 akiss
        if (y==0){yp=y;}
187 1 akiss
        int yn=y+1;
188 1 akiss
        if (y==img._height-1){yn=y;}
189 1 akiss
        int zp=z-1;
190 1 akiss
        if (z==0){zp=z;}
191 1 akiss
        int zn=z+1;
192 1 akiss
        if (z==img._depth-1){zn=z;}
193 1 akiss
194 1 akiss
        CImg<float> hess(3,3,1,1,0);
195 1 akiss
        hess(0,0) = img(xp,y,z) + img(xn,y,z) - 2*img(x,y,z);          // Hxx
196 1 akiss
        hess(1,1) = img(x,yp,z) + img(x,yn,z) - 2*img(x,y,z);          // Hyy
197 1 akiss
        hess(2,2) = img(x,y,zp) + img(x,y,zn) - 2*img(x,y,z);          // Hzz
198 1 akiss
        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
199 1 akiss
        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
200 1 akiss
        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
201 1 akiss
202 1 akiss
        //val : 3 eigen values as an array, decreasing order
203 1 akiss
        //vec : 3 eigen vectors as a 3*3 image
204 1 akiss
        //have to be double or create NaN
205 1 akiss
        CImg<double> val,vec;
206 1 akiss
        hess.symmetric_eigen(val,vec);
207 1 akiss
        if (val[2]>0) val[2]=0;
208 1 akiss
        val[2]=-val[2];
209 1 akiss
        //res(x,y,z)=1.0/(1.0 +val[2]*(50/3.));  //h=g test4
210 1 akiss
    //res(x,y,z)=1.0/(1.0 +val[2]*val[2]*(50/3.)*(50/3.) );
211 1 akiss
    //res(x,y,z)=1.0/(1.0 +exp(-val[2]));
212 1 akiss
    //res(x,y,z)=exp(-val[2]);
213 1 akiss
    //res(x,y,z)=exp(-val[2]*val[2]);
214 1 akiss
    res(x,y,z)=1.0/(1.0 +val[2]*val[2]);
215 1 akiss
    }
216 1 akiss
  return res;
217 1 akiss
}
218 1 akiss
219 1 akiss
//Edge indicator 2 (hessienne, computed with smoothing)
220 1 akiss
//---------------------------------------------------------------------------
221 1 akiss
CImg<float> edge_indicator2s(CImg<float> const & img, float gamma)
222 1 akiss
{
223 1 akiss
  CImg<float> res(img._width,img._height,img._depth,1,0);
224 1 akiss
225 1 akiss
  // make a minimal blur before taking derivatives
226 1 akiss
  CImg<float> imgBlur=img.get_blur(2);
227 1 akiss
228 1 akiss
  float f=0;
229 1 akiss
  cimg_forXYZ(res,x,y,z)
230 1 akiss
    {
231 1 akiss
    int xp=x-1;
232 1 akiss
        if (x==0){xp=x;}
233 1 akiss
        int xn=x+1;
234 1 akiss
        if (x==img._width-1){xn=x;}
235 1 akiss
        int yp=y-1;
236 1 akiss
        if (y==0){yp=y;}
237 1 akiss
        int yn=y+1;
238 1 akiss
        if (y==img._height-1){yn=y;}
239 1 akiss
        int zp=z-1;
240 1 akiss
        if (z==0){zp=z;}
241 1 akiss
        int zn=z+1;
242 1 akiss
        if (z==img._depth-1){zn=z;}
243 1 akiss
244 1 akiss
        CImg<float> hess(3,3,1,1,0);
245 1 akiss
        hess(0,0) = imgBlur(xp,y,z) + imgBlur(xn,y,z) - 2*imgBlur(x,y,z);          // Hxx
246 1 akiss
        hess(1,1) = imgBlur(x,yp,z) + imgBlur(x,yn,z) - 2*imgBlur(x,y,z);          // Hyy
247 1 akiss
        hess(2,2) = imgBlur(x,y,zp) + imgBlur(x,y,zn) - 2*imgBlur(x,y,z);          // Hzz
248 1 akiss
        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
249 1 akiss
        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
250 1 akiss
        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
251 1 akiss
252 1 akiss
        //val : 3 eigen values as an array, decreasing order
253 1 akiss
        //vec : 3 eigen vectors as a 3*3 image
254 1 akiss
        //have to be double or create NaN
255 1 akiss
        CImg<double> val,vec;
256 1 akiss
        hess.symmetric_eigen(val,vec);
257 1 akiss
        if (val[2]>0) val[2]=0;
258 1 akiss
        val[2]=-val[2];
259 1 akiss
    res(x,y,z)=1.0/(1.0 +val[2]*val[2]/gamma/gamma);
260 1 akiss
    }
261 1 akiss
  return res;
262 1 akiss
}
263 1 akiss
264 1 akiss
265 1 akiss
CImg<float> edge_indicator2(CImg<float> const & img, float gamma)
266 1 akiss
{
267 1 akiss
  CImg<float> res(img._width,img._height,img._depth,1,0);
268 1 akiss
  float f=0;
269 1 akiss
  cimg_forXYZ(res,x,y,z)
270 1 akiss
    {
271 1 akiss
    int xp=x-1;
272 1 akiss
        if (x==0){xp=x;}
273 1 akiss
        int xn=x+1;
274 1 akiss
        if (x==img._width-1){xn=x;}
275 1 akiss
        int yp=y-1;
276 1 akiss
        if (y==0){yp=y;}
277 1 akiss
        int yn=y+1;
278 1 akiss
        if (y==img._height-1){yn=y;}
279 1 akiss
        int zp=z-1;
280 1 akiss
        if (z==0){zp=z;}
281 1 akiss
        int zn=z+1;
282 1 akiss
        if (z==img._depth-1){zn=z;}
283 1 akiss
284 1 akiss
        CImg<float> hess(3,3,1,1,0);
285 1 akiss
        hess(0,0) = img(xp,y,z) + img(xn,y,z) - 2*img(x,y,z);          // Hxx
286 1 akiss
        hess(1,1) = img(x,yp,z) + img(x,yn,z) - 2*img(x,y,z);          // Hyy
287 1 akiss
        hess(2,2) = img(x,y,zp) + img(x,y,zn) - 2*img(x,y,z);          // Hzz
288 1 akiss
        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
289 1 akiss
        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
290 1 akiss
        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
291 1 akiss
292 1 akiss
        //val : 3 eigen values as an array, decreasing order
293 1 akiss
        //vec : 3 eigen vectors as a 3*3 image
294 1 akiss
        //have to be double or create NaN
295 1 akiss
        CImg<double> val,vec;
296 1 akiss
        hess.symmetric_eigen(val,vec);
297 1 akiss
        if (val[2]>0) val[2]=0;
298 1 akiss
        //val[2]=-val[2];
299 1 akiss
    res(x,y,z)=1.0/(1.0 +val[2]*val[2]/gamma/gamma);
300 1 akiss
    }
301 1 akiss
  return res;
302 1 akiss
}
303 1 akiss
304 1 akiss
//Edge indicator 3 (image based)
305 1 akiss
//---------------------------------------------------------------------------
306 1 akiss
CImg<float> edge_indicator3(CImg<float> const & img)
307 1 akiss
{
308 1 akiss
  CImg<float> res(img._width,img._height,img._depth,1,0);
309 1 akiss
  cimg_forXYZ(res,x,y,z)
310 1 akiss
    {
311 1 akiss
      res(x,y,z)=1.0/(1.0+img(x,y,z)*img(x,y,z));
312 1 akiss
    }
313 1 akiss
  return res;
314 1 akiss
}
315 1 akiss
316 1 akiss
CImg<float> edge_indicator3(CImg<float> const & img, float gamma)
317 1 akiss
{
318 1 akiss
  CImg<float> res(img._width,img._height,img._depth,1,0);
319 1 akiss
  cimg_forXYZ(res,x,y,z)
320 1 akiss
    {
321 1 akiss
                res(x,y,z)=1.0/(1.0+(img(x,y,z)/gamma)*(img(x,y,z)/gamma));
322 1 akiss
    }
323 1 akiss
  return res;
324 1 akiss
}
325 1 akiss
326 1 akiss
//Edge image (based on lambda3 of the hessien)
327 1 akiss
//---------------------------------------------------------------------------
328 1 akiss
CImg<float> edge_lambda3(CImg<float> const & img)
329 1 akiss
{
330 1 akiss
  CImg<float> res(img._width,img._height,img._depth,1,0);
331 1 akiss
  float f=0;
332 1 akiss
  cimg_forXYZ(res,x,y,z)
333 1 akiss
    {
334 1 akiss
    int xp=x-1;
335 1 akiss
        if (x==0){xp=x;}
336 1 akiss
        int xn=x+1;
337 1 akiss
        if (x==img._width-1){xn=x;}
338 1 akiss
        int yp=y-1;
339 1 akiss
        if (y==0){yp=y;}
340 1 akiss
        int yn=y+1;
341 1 akiss
        if (y==img._height-1){yn=y;}
342 1 akiss
        int zp=z-1;
343 1 akiss
        if (z==0){zp=z;}
344 1 akiss
        int zn=z+1;
345 1 akiss
        if (z==img._depth-1){zn=z;}
346 1 akiss
347 1 akiss
        CImg<float> hess(3,3,1,1,0);
348 1 akiss
        hess(0,0) = img(xp,y,z) + img(xn,y,z) - 2*img(x,y,z);          // Hxx
349 1 akiss
        hess(1,1) = img(x,yp,z) + img(x,yn,z) - 2*img(x,y,z);          // Hyy
350 1 akiss
        hess(2,2) = img(x,y,zp) + img(x,y,zn) - 2*img(x,y,z);          // Hzz
351 1 akiss
        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
352 1 akiss
        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
353 1 akiss
        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
354 1 akiss
355 1 akiss
        //val : 3 eigen values as an array, decreasing order
356 1 akiss
        //vec : 3 eigen vectors as a 3*3 image
357 1 akiss
        //have to be double or create NaN
358 1 akiss
        CImg<double> val,vec;
359 1 akiss
        hess.symmetric_eigen(val,vec);
360 1 akiss
        if (val[2]>0) val[2]=0;
361 1 akiss
    res(x,y,z)=-val[2];
362 1 akiss
    }
363 1 akiss
  return res;
364 1 akiss
}
365 1 akiss
366 1 akiss
367 1 akiss
//Wall indicator
368 1 akiss
//---------------------------------------------------------------------------
369 1 akiss
CImg<float> wall_indicator(CImg<float> const & img)
370 1 akiss
{
371 1 akiss
  CImg<float> res(img._width,img._height,img._depth,1,0);
372 1 akiss
  cimg_forXYZ(res,x,y,z)
373 1 akiss
    {
374 1 akiss
      res(x,y,z)=1.0/(1.0+(img(x,y,z)*img(x,y,z)));
375 1 akiss
    }
376 1 akiss
  return res;
377 1 akiss
}
378 1 akiss
379 1 akiss
//Dirac function
380 1 akiss
//-------------------------------------------------------------------------
381 1 akiss
CImg<float> Dirac(CImg<float> const & img, float sigma)
382 1 akiss
{
383 1 akiss
  CImg<float> fImg(img._width,img._height,img._depth,1,0);
384 1 akiss
  float f=0;
385 1 akiss
  cimg_forXYZ(img,x,y,z)
386 1 akiss
    {
387 1 akiss
      if(abs(img(x,y,z))<=sigma)
388 1 akiss
        {
389 1 akiss
          f=(1.0/(2*sigma))*(1+cos(M_PI*img(x,y,z)/sigma));
390 1 akiss
        }
391 1 akiss
      else {f=0;}
392 1 akiss
      fImg(x,y,z)=f;
393 1 akiss
    }
394 1 akiss
  return fImg;
395 1 akiss
}
396 1 akiss
397 1 akiss
//Normal vector
398 1 akiss
//------------------------------------------------------------------------
399 1 akiss
CImgList<float> normal_vector(CImg<float> const & img)
400 1 akiss
{
401 1 akiss
  CImgList<float> normal_vector(3,img._width,img._height,img._depth,1,0);
402 1 akiss
403 1 akiss
  CImg_3x3x3(I,float);
404 1 akiss
  cimg_for3x3x3(img,x,y,z,0,I,float)
405 1 akiss
    {
406 1 akiss
      float nx = (Incc-Ipcc)/2.0;
407 1 akiss
      float ny = (Icnc-Icpc)/2.0;
408 1 akiss
      float nz = (Iccn-Iccp)/2.0;
409 1 akiss
      //border
410 1 akiss
      if((x==0)or(y==0)or(z==0))
411 1 akiss
        {nx=ny=nz=0;}
412 1 akiss
      if((x==img.width()-1)or(y==img.height()-1)or(z==img.depth()-1))
413 1 akiss
        {nx=ny=nz=0;}
414 1 akiss
415 1 akiss
      float norm=1;
416 1 akiss
      if((nx!=0)or(ny!=0)or(nz!=0))
417 1 akiss
        {norm = sqrt(nx*nx+ny*ny+nz*nz);}
418 1 akiss
419 1 akiss
      normal_vector(0,x,y,z)=nx/norm;
420 1 akiss
      normal_vector(1,x,y,z)=ny/norm;
421 1 akiss
      normal_vector(2,x,y,z)=nz/norm;
422 1 akiss
    }
423 1 akiss
  return normal_vector;
424 1 akiss
}
425 1 akiss
426 1 akiss
427 1 akiss
//Curvature
428 1 akiss
//------------------------------------------------------------------------
429 1 akiss
CImg<float> curvature2(CImgList<float> const & N)
430 1 akiss
{
431 1 akiss
  CImg<float> K(N[0]._width,N[0]._height,N[0]._depth,1,0);
432 1 akiss
  cimg_forXYZ(N[0],x,y,z)
433 1 akiss
    {
434 1 akiss
      float kx=0;
435 1 akiss
      float ky=0;
436 1 akiss
      float kz=0;
437 1 akiss
      if(x==0)
438 1 akiss
        {kx=N[0](x+1,y,z)-N[0](x,y,z);}
439 1 akiss
      else if(x==N[0]._width-1)
440 1 akiss
        {kx=N[0](x,y,z)-N[0](x-1,y,z);}
441 1 akiss
      else
442 1 akiss
        {kx=(N[0](x+1,y,z)-N[0](x-1,y,z))/2.0;}
443 1 akiss
444 1 akiss
     if(y==0)
445 1 akiss
        {ky=N[1](x,y+1,z)-N[1](x,y,z);}
446 1 akiss
      else if(y==N[1]._height-1)
447 1 akiss
        {ky=N[1](x,y,z)-N[1](x,y-1,z);}
448 1 akiss
      else
449 1 akiss
        {ky=(N[1](x,y+1,z)-N[1](x,y-1,z))/2.0;}
450 1 akiss
451 1 akiss
     if(z==0)
452 1 akiss
        {kz=N[2](x,y,z+1)-N[2](x,y,z);}
453 1 akiss
      else if(z==N[2]._depth-1)
454 1 akiss
        {kz=N[2](x,y,z)-N[2](x,y,z-1);}
455 1 akiss
      else
456 1 akiss
        {kz=(N[2](x,y,z+1)-N[2](x,y,z-1))/2.0;}
457 1 akiss
458 1 akiss
     K(x,y,z)=kx+ky+kz;
459 1 akiss
    }
460 1 akiss
  return K;
461 1 akiss
}
462 1 akiss
463 1 akiss
// Compute image laplacian
464 1 akiss
//--------------------------------------------------------------------
465 1 akiss
CImg<float> laplacian(CImg<float> const & img)
466 1 akiss
{
467 1 akiss
  CImg<float> laplacian(img._width,img._height,img._depth,1,0);
468 1 akiss
  CImg_3x3x3(I,float);
469 1 akiss
  cimg_for3x3x3(img,x,y,z,0,I,float)
470 1 akiss
    {
471 1 akiss
      laplacian(x,y,z) =Incc+Ipcc+Icnc+Icpc+Iccn+Iccp - 6*Iccc;
472 1 akiss
    }
473 1 akiss
  return laplacian;
474 1 akiss
}
475 1 akiss
476 1 akiss
//Evolution AK2 contour
477 1 akiss
//-------------------------------------------------------------------------
478 1 akiss
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)
479 1 akiss
{
480 1 akiss
  CImg<float> diracU=Dirac(u,epsilon);
481 1 akiss
  CImgList<float> N=normal_vector(u);
482 1 akiss
  CImg<float> K=curvature2(N);
483 1 akiss
  CImg<float> L=laplacian(u);
484 1 akiss
  float term=0;
485 1 akiss
486 1 akiss
  cimg_forXYZ(u,x,y,z)
487 1 akiss
    {
488 1 akiss
      term=0;
489 1 akiss
      if (diracU(x,y,z)!=0)
490 1 akiss
        {
491 1 akiss
          //weighted length term
492 1 akiss
          if(lam!=0)
493 1 akiss
            {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;}
494 1 akiss
          //length term
495 1 akiss
          if(beta!=0)
496 1 akiss
            {term=term + K(x,y,z)*beta;}
497 1 akiss
          //weighted area term
498 1 akiss
          if(alf!=0)
499 1 akiss
            {term=term + h(x,y,z)*alf;}
500 1 akiss
          //regularization
501 1 akiss
          term=term*diracU(x,y,z);
502 1 akiss
          //penalizing term
503 1 akiss
          term=term + (L(x,y,z)-K(x,y,z))*mu;
504 1 akiss
        }
505 1 akiss
      else
506 1 akiss
        {
507 1 akiss
          //penalizing term
508 1 akiss
          term=(L(x,y,z)-K(x,y,z))*mu;
509 1 akiss
        }
510 1 akiss
511 1 akiss
      u(x,y,z)=u(x,y,z) + term*dt;
512 1 akiss
    }
513 1 akiss
  return u;
514 1 akiss
}
515 1 akiss
516 1 akiss
//Evolution AK2 contour cells
517 1 akiss
//-------------------------------------------------------------------------
518 1 akiss
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)
519 1 akiss
{
520 1 akiss
  CImg<float> diracU=Dirac(u,epsilon);
521 1 akiss
  CImgList<float> N=normal_vector(u);
522 1 akiss
  CImg<float> K=curvature2(N);
523 1 akiss
  CImg<float> L=laplacian(u);
524 1 akiss
  float term=0;
525 1 akiss
  int xmax=u._width;
526 1 akiss
  int ymax=u._height;
527 1 akiss
  int zmax=u._depth;
528 1 akiss
  int c0=-4;
529 1 akiss
530 1 akiss
  cimg_forXYZ(u,x,y,z)
531 1 akiss
    {
532 1 akiss
      int xb=x+min_list[0];
533 1 akiss
      int yb=y+min_list[1];
534 1 akiss
      int zb=z+min_list[2];
535 1 akiss
      term=0;
536 1 akiss
      if (diracU(x,y,z)!=0)
537 1 akiss
        {
538 1 akiss
          //weighted length term
539 1 akiss
          if(lam!=0)
540 1 akiss
            {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;}
541 1 akiss
          //length term
542 1 akiss
          if(beta!=0)
543 1 akiss
            {term=term + K(x,y,z)*beta;}
544 1 akiss
          //weighted area term
545 1 akiss
          if(alf!=0)
546 1 akiss
            {term=term + h(xb,yb,zb)*alf;}
547 1 akiss
          //regularization
548 1 akiss
          term=term*diracU(x,y,z);
549 1 akiss
          //penalizing term
550 1 akiss
          term=term + (L(x,y,z)-K(x,y,z))*mu;
551 1 akiss
        }
552 1 akiss
      else
553 1 akiss
        {
554 1 akiss
          //penalizing term
555 1 akiss
          term=(L(x,y,z)-K(x,y,z))*mu;
556 1 akiss
        }
557 1 akiss
      // computing the evolution
558 1 akiss
      u(x,y,z)=u(x,y,z) + term*dt;
559 1 akiss
      // box boundary regularisation
560 1 akiss
      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))
561 1 akiss
      {u(x,y,z)=c0;}
562 1 akiss
    }
563 1 akiss
  return u;
564 1 akiss
}