Statistiques
| Révision :

root / src / lsm_lib.h @ 9

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