Switch to unified view

a b/Thoracic Organs Segmentation code/TwoPhaseLevel Sets/Combination.asv
1
/*/////////////////////////////////////////////////////////////////////////////////////
2
                            2 phase level set method
3
 0-input image
4
 1-initial phi1
5
 2-dt=>time-step of iteration
6
 3-kappa =>coefficient of the weighted length term L(phi1)
7
 4-lambda1 =>coefficient of insice C term
8
 5-lambda2 =>coefficient of outside C term
9
 6-lambda=>coefficient of the weighted length term L(phi2)
10
 7-mu => coefficient of the internal (penalizing) energy term P(phi1),P(phi2)
11
 8-v=>coefficient of the weighted area term A(phi2)
12
 9-iterations
13
 10-g=>edge indicator
14
/*/////////////////////////////////////////////////////////////////////////////////////
15
#include <mex.h>
16
#include <mat.h>
17
#include <matrix.h>
18
19
#define cimg_plugin "cimgmatlab.h"
20
21
#include "CImg.h"
22
#include <iostream>
23
#include <string>
24
#include <math.h>
25
26
using namespace cimg_library;
27
using namespace std;
28
29
//globa values
30
const double  epsilon=0.8; // the papamater smooth Dirac function (default value 1.5);
31
const float precision=0.009f;//precision of the error estimation
32
33
//functions
34
CImg<double> DiracU( CImg<double>& u0) ;
35
CImg<double> Heaviside(CImg<double>& u0);
36
CImg<double> ExtractContour(CImg<double> LevelSet);
37
CImg<unsigned char> get_level0(const CImg<>& img);
38
CImg<unsigned char> InitialLevelSet(CImg<double>&Img);
39
CImg<double> DiracF(CImg<double>& u1,CImg<double>& u2); 
40
CImg<double>Heaviside1(CImg<double>& u0);
41
42
//-----------------
43
// Main-MexFunction
44
//-----------------
45
46
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
47
   if (nrhs < 13) mexErrMsgTxt("No enough input arguments.");
48
   if (nrhs >13) mexErrMsgTxt("Too many input arguments.");
49
   if (nrhs == 13){
50
         
51
       //Input Parameters ( inputs)
52
       CImg<double>  Img(prhs[0],true);         //input image
53
       CImg<double>  phi1(prhs[1],true);       //Rib cage approximation
54
       CImg<double> phi2(prhs[2],true);
55
       CImg<int>VolumeMask(prhs[3],true);
56
       const double dt= mxGetScalar( prhs[4]);       //time-step of iteration
57
       const double kappa = mxGetScalar(prhs[5]);     //coefficient of the weighted length term L(phi1)
58
       const double lambda1 = mxGetScalar(prhs[6]);//coefficient of insice C term
59
       const double lambda2 = mxGetScalar(prhs[7]);//coefficient of outside C term
60
       const double lambda = mxGetScalar(prhs[8]); //coefficient of the weighted length term L(phi2)
61
       const double mu = mxGetScalar(prhs[9]);    // coefficient of the internal (penalizing) energy term P(u)
62
       const double v = mxGetScalar(prhs[10]);     //coefficient of the weighted area term A(u)
63
       const unsigned int nb_iter = mxGetScalar(prhs[11]);
64
       CImg<double> g(prhs[12],true);
65
       //////////////////////////////////////////////////////////////////////////////////////////////////
66
       
67
      unsigned char col1[2]={0,255}, col2[2]={200,255}, col3[2]={255,255};//colors filling
68
      CImg<double>f(phi1.dimx(),phi1.dimy());
69
      cimg_forXY(phi1,x,y) {if(phi1(x,y)==1) phi1(x,y)=200;}
70
      phi1.draw_fill(0,0,col3);
71
      cimg_forXY(phi2,x,y) {if(phi2(x,y)==1) phi2(x,y)=200;}
72
      phi2.draw_fill(0,0,col3);
73
      
74
         cimg_forXY(phi1,x,y){
75
           if(phi1(x,y)==200) f(x,y)=0;
76
          if(phi1(x,y)==0) f(x,y)=-5;
77
          if(phi1(x,y)==255) f(x,y)=5;
78
      }
79
      cimg_forXY(phi1,x,y){
80
        phi1(x,y)=floor(phi1(x,y)-phi2(x,y));
81
          if(phi1(x,y)<0) phi1(x,y)=-1;
82
          if(phi1(x,y)==0) phi1(x,y)=1;
83
          if(phi1(x,y)==-55 || phi1(x,y)==200) phi1(x,y)=0;
84
        
85
     }
86
     
87
  
88
    
89
       cimg_forXY(phi2,x,y){
90
           if(phi2(x,y)==200) phi2(x,y)=0;
91
           if(phi2(x,y)==0) phi2(x,y)=-5;
92
          if(phi2(x,y)==255) phi2(x,y)=5;
93
       }
94
     
95
       CImg<double>HeavisideF10= Heaviside1(f);
96
    
97
  
98
  // cimg_forXY(phi1,x,y){ phi1(x,y)=phi1(x,y)*phi2(x,y);} 
99
      //   if (phi1(x,y)*phi2(x,y)>0) phi1(x,y)=-5;
100
        // if (phi1(x,y)*phi2(x,y)==0)phi1(x,y)=0;
101
         //if (phi1(x,y)*phi2(x,y)<0)phi1(x,y)=5;
102
     //}
103
     
104
    
105
   //    phi1.normalize(-1,1); 
106
    //   CImgDisplay disp2(phi2,"Image",0);
107
     phi1.distance_hamilton(5);//distance function
108
     // phi2.distance_hamilton(30);//distance function
109
      // CImgDisplay disp1(phi1,"Image",0);
110
    
111
        //Initializations
112
      CImg<double> dphi1(Img.dimx(),Img.dimy(),2); //derivatives of phi
113
       CImg<double> veloc1(phi1.dimx(),phi1.dimy());
114
       CImg<double> N_dphi1(phi1.dimx(),phi1.dimy(),2); //Normalize gradient of level set function phi1
115
       CImg<double> veloc2(phi2.dimx(),phi2.dimy());
116
       CImg<double> N_dphi2(phi2.dimx(),phi2.dimy(),2); //Normalize gradient of level set function phi2
117
       
118
       
119
      // const unsigned int nb_iter = 0;//Number of iterations  
120
       double c1=0, c2=0, Averagec1=0, Averagec2=0;
121
      
122
      //Edge indicator
123
      CImg<double>dg(g.dimx(),g.dimy(),1,2);
124
         cimg_for3XY(g,x,y){
125
              dg(x,y,0)=0.5*(g(_n1x,y)-g(_p1x,y)), 
126
              dg(x,y,1)=0.5*(g(x,_n1y)-g(x,_p1y));
127
       }
128
               
129
       
130
   //  CImg<double>HeavisideF10= Heaviside1(phi1);
131
      double E1=1e20f,E2=1e20f;//Initial energy
132
     double Eold1 = 0, Eold2=0;  
133
     veloc1.fill(0);
134
     veloc2.fill(0);
135
    
136
     //////////////////////////////////////////////////////////////////////////////////////////////
137
      //Main PDEs
138
     for (unsigned int iter=0; iter<=nb_iter; iter++) {
139
                
140
                                       
141
             CImg<double> diracF1=DiracU(phi1);
142
             CImg<double>HeavisideF1=Heaviside(phi1);
143
             CImg<double> diracF2=DiracU(phi2);
144
             CImg<double>HeavisideF2=Heaviside1(phi2);
145
          //   CImg<double> dirac = DiracF(phi1,phi2);
146
             cimg_for3XY(phi1,x,y)if (VolumeMask(x,y)==0){
147
                
148
                 //PHI1             
149
                 const double
150
                      phix1=0.5*(phi1(_n1x,y)-phi1(_p1x,y)),
151
                      phiy1=0.5*(phi1(x,_n1y)-phi1(x,_p1y));  //derivatives of phi(central)
152
153
                  const double Mag_dphi1= sqrt(pow(phix1,2)+ pow(phiy1,2)+1e-10); //magnitude of grad(phi)
154
                      N_dphi1(x,y,0)=phix1/Mag_dphi1;
155
                      N_dphi1(x,y,1)=phiy1/Mag_dphi1;
156
157
                 c1+=HeavisideF1(x,y)* Img(x,y);
158
                 c2+=(1-HeavisideF1(x,y))*Img(x,y);
159
                 Averagec1+=HeavisideF1(x,y);
160
                 Averagec2+=HeavisideF1(x,y);
161
                 /////////////////////////////////////////////////////////////////////////////////////
162
                 //PHI2
163
                 const double
164
                      phix2=0.5*(phi2(_n1x,y)-phi2(_p1x,y)),
165
                      phiy2=0.5*(phi2(x,_n1y)-phi2(x,_p1y));  //derivatives of phi2
166
167
                  const double Mag_dphi2= sqrt(pow(phix2,2)+ pow(phiy2,2)+1e-10); //magnitude of grad(phi2)
168
                      N_dphi2(x,y,0)=phix2/Mag_dphi2;
169
                      N_dphi2(x,y,1)=phiy2/Mag_dphi2;
170
              }
171
172
             c1/=(Averagec1+1e-5);
173
             c2/=(Averagec2+1e-5);
174
                          
175
             
176
           
177
                  cimg_for3XY(Img,x,y)if (VolumeMask(x,y)==0){
178
                     
179
                  //Chan-Vese level set function 
180
                  const double
181
                     dN_phix1=0.5*(N_dphi1(_n1x,y,0)-N_dphi1(_p1x,y,0)),
182
                     dN_phiy1=0.5*(N_dphi1(x,_n1y,1)-N_dphi1(x,_p1y,1)),
183
                     Laplac_phi1=(phi1(_n1x,y) + phi1(_p1x,y) + phi1(x,_n1y) + phi1(x,_p1y))-4*phi1(x,y),
184
                     K1=dN_phix1+dN_phiy1;
185
                  const double
186
                     phixx1=(phi1(_n1x,y)+phi1(_p1x,y)-2*phi1(x,y)),
187
                     phiyy1=(phi1(x,_n1y)+phi1(x,_p1y)-2*phi1(x,y)),
188
                     phix1 =0.5*(phi1(_n1x,y)-phi1(_p1x,y)),
189
                     phiy1 =0.5*(phi1(x,_n1y)-phi1(x,_p1y)),
190
                     Mag_dphi1 = sqrt(pow(phix1,2)+ pow(phiy1,2)+1e-10); 
191
                      
192
                     veloc1(x,y)=kappa*diracF1(x,y)*(dg(x,y,0)* N_dphi1(x,y,0) +dg(x,y,1)* N_dphi1(x,y,1)+g(x,y)*K1)+mu*(Laplac_phi1-K1)-lambda1* diracF1(x,y)* pow(Img(x,y)-c1,2)+lambda2*diracF1(x,y)*pow(Img(x,y)-c2,2);//+35*diracF1(x,y);//0.01*diracF1(x,y)*(1-HeavisideF1(x,y))*pow(1-HeavisideF2(x,y),2);//-0.8*diracF2(x,y)*(HeavisideF1(x,y)-1);
193
                    // veloc1(x,y)=(1-HeavisideF2(x,y))*veloc1(x,y);
194
                     E1+=lambda1*HeavisideF1(x,y)*pow(Img(x,y)-c1,2);//+lambda2*(1-HeavisideF1(x,y))*pow(Img(x,y)-c2,2);  
195
                
196
                     //front propagation level set function
197
                  const double
198
                     dN_phix2=0.5*(N_dphi2(_n1x,y,0)-N_dphi2(_p1x,y,0)),
199
                     dN_phiy2=0.5*(N_dphi2(x,_n1y,1)-N_dphi2(x,_p1y,1)),
200
                     Laplac_phi2=(phi2(_n1x,y) + phi2(_p1x,y) + phi2(x,_n1y) + phi2(x,_p1y))-4*phi2(x,y),
201
                     K2=dN_phix2+dN_phiy2;
202
                  const double
203
                     phixx2=(phi2(_n1x,y)+phi2(_p1x,y)-2*phi2(x,y)),
204
                     phiyy2=(phi2(x,_n1y)+phi2(x,_p1y)-2*phi2(x,y)),
205
                     phix2 =0.5*(phi2(_n1x,y)-phi2(_p1x,y)),
206
                     phiy2 =0.5*(phi2(x,_n1y)-phi2(x,_p1y)),//derivatives of u
207
                     Mag_dphi2 = sqrt(pow(phix2,2)+ pow(phiy2,2)+1e-10); //magnitude of grad(u)
208
                //if (HeavisideF10(x,y)-HeavisideF2(x,y)>0 && HeavisideF1(x,y)>0){ 
209
                  veloc2(x,y)=lambda* diracF2(x,y)*( dg(x,y,0)* N_dphi2(x,y,0) +dg(x,y,1)* N_dphi2(x,y,1) + g(x,y)*K2)+mu*(Laplac_phi2-K2)+v*g(x,y)*diracF2(x,y);
210
                 //}
211
                // else veloc2(x,y)=0;
212
                  veloc2(x,y)=veloc2(x,y)*HeavisideF10(x,y)*HeavisideF1(x,y);
213
                //Energy estimation(functionals)
214
                 E2+=v*HeavisideF2(x,y)*g(x,y); 
215
               //   E2+=lambda*g(x,y)*diracF2(x,y)* Mag_dphi2+1/2*mu*pow( Mag_dphi2-1,2)+v*HeavisideF2(x,y)*g(x,y);
216
                  
217
                  
218
                  }
219
         
220
            phi1+=dt*veloc1;
221
          
222
           phi2+=dt*veloc2;
223
           
224
          if ((abs(Eold1-E1)<0.001f) && (abs(Eold2-E2)<0.001f)) break; 
225
          
226
          /* if (!(iter%8)) {
227
                  get_level0(phi1).resize(disp1.dimx(),disp1.dimy()).draw_grid(20,20,0,0,false,false,col3,0.4f,0xCCCCCCCC,0xCCCCCCCC).
228
                  draw_text(5,5,"Iteration %d",col3,0,1,11,iter).display(disp1);
229
                  get_level0(phi2).resize(disp2.dimx(),disp2.dimy()).draw_grid(20,20,0,0,false,false,col3,0.4f,0xCCCCCCCC,0xCCCCCCCC).
230
                  draw_text(5,5,"Iteration %d",col3,0,1,11,iter).display(disp2);
231
            }*/
232
             //printf ("Energy functional E1: %d \n",E1);
233
             //printf ("Energy functional E2: %d \n",E2);
234
           //  printf("E1-Eold1=%d\n",abs(Eold1-E1));
235
            // printf("E2-Eold2=%d\n",abs(E2-Eold2));
236
          //  if (!(iter%550)) phi2.distance_hamilton(1,3);//  phi1.distance_hamilton(1,10);;
237
             c1=0,Averagec1=0;
238
             c2=0,Averagec2=0;
239
             Eold1 = E1, Eold2=E2;
240
             E1=0;E2=0;
241
      
242
     }
243
  //  phi2.distance_hamilton(1,10),  phi1.distance_hamilton(1,10);
244
    //CImg<double>Contour1 = ExtractContour(phi1);
245
    //CImg<double>Contour2 = ExtractContour(phi2);
246
     // phi2.distance_hamilton(1,3);
247
    //  phi1.distance_hamilton(1,3);
248
    
249
      plhs[0]=  phi1.toMatlab();
250
    plhs[1]=  phi2.toMatlab();
251
     
252
  
253
                   
254
  } 
255
      
256
   return;    
257
 
258
}
259
  
260
261
262
   
263
CImg<double> DiracU(CImg<double>& u0) {
264
265
  CImg<double> u(u0.dimx(),u0.dimy());
266
  u.fill(0);
267
   cimg_forXY(u0,x,y) { 
268
                  
269
       if (u0(x,y)<=epsilon && u0(x,y)>=-epsilon){
270
       u(x,y)=(double)1/(2*epsilon)*(1+cos(3.14*u0(x,y)/epsilon));
271
       }
272
  
273
   }
274
    return u;
275
}
276
     
277
CImg<double> Heaviside(CImg<double>& u0) {
278
279
  CImg<double> u(u0.dimx(),u0.dimy());
280
  u.fill(0);
281
/*cimg_forXY(u0,x,y){
282
    u(x,y)=1/2*(1+2/3.14*atan(u(x,y)/epsilon));
283
}*/  
284
 cimg_forXY(u0,x,y) { 
285
                  
286
       if (u0(x,y)>=-epsilon && u0(x,y)<=epsilon){
287
       u(x,y)=(double) 1/2+u0(x,y)/(2*epsilon)+1/(2*3.14)*sin(3.14*u0(x,y)/epsilon);
288
       }
289
       if (u0(x,y)>epsilon) u(x,y)=1;
290
  
291
   }
292
    return u;
293
} 
294
295
296
/*******************************************************************************/
297
CImg<double> ExtractContour(CImg<double> LevelSet)
298
{
299
 CImg<double> Contour(LevelSet.dimx(),LevelSet.dimy(),1,1);
300
 Contour.fill(0);
301
302
 CImg_3x3(I,double);
303
 cimg_for3x3(LevelSet,x,y,0,0,I)
304
 {
305
  if(Icc*Icp<=0 || Icc*Icn<=0 || Icc*Ipc<=0 || Icc*Inc<=0)
306
   Contour(x,y) = 1;
307
 }
308
 return Contour;
309
}
310
CImg<double> Heaviside1(CImg<double>& u0) {
311
312
  CImg<double> u(u0.dimx(),u0.dimy());
313
  u.fill(0);
314
   cimg_forXY(u0,x,y) { 
315
                  
316
       if (u0(x,y)<=epsilon && u0(x,y)>=-epsilon){
317
       u(x,y)=(double) 1/2-u0(x,y)/(2*epsilon)+1/(2*3.14)*sin(-3.14*u0(x,y)/epsilon);
318
       }
319
       if (u0(x,y)<-epsilon) u(x,y)=1;
320
  
321
   }
322
    return u;
323
}
324
//////////////////////////////////////////////////////////////////////////////////////////////
325
// get_level0() : Retrieve the curve corresponding to the zero level set of the distance function
326
//-------------
327
CImg<unsigned char> get_level0(const CImg<>& img) {
328
  CImg<unsigned char> dest(img);
329
  CImg_2x2(I,float); Inn = 0;
330
  cimg_for2x2(img,x,y,0,0,I) if (Icc*Inc<0 || Icc*Icn<0) dest(x,y) = 255; else dest(x,y) = Icc<0?100:0;
331
  return dest;
332
}
333
334
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
335
// // Create a user-defined closed curve (Initial level set fuction)
336
CImg<unsigned char> InitialLevelSet(CImg<double>&Img){
337
       CImg<unsigned char> curve(Img.dimx(),Img.dimy(),Img.dimz(),2,0);
338
       unsigned char col1[2]={0,255}, col2[2]={200,255}, col3[2]={255,255};//colors
339
       curve.draw_grid(20,20,0,0,false,false,col1,0.4f,0xCCCCCCCC,0xCCCCCCCC).
340
       draw_text(5,5,"Please draw your curve\nin the middle of this window\n(Use your mouse)\n-heart initial curve",col1);
341
      CImgDisplay disp(curve,"Image",0);
342
       CImg<double> tempImg(Img);
343
344
       int xo=-1,yo=-1,x0=-1,y0=-1,x1=-1,y1=-1;
345
       while (!disp.is_closed && (x0<0 || disp.button)) {
346
        if (disp.button && disp.mouse_x>=0 && disp.mouse_y>=0) {
347
             if (x0<0) { xo = x0 = disp.mouse_x; yo = y0 = disp.mouse_y; } else {
348
                 x1 = disp.mouse_x; y1 = disp.mouse_y;
349
                 curve.draw_line(x0,y0,x1,y1,col2);//.display(disp);
350
                
351
                  tempImg.draw_point(x1,y1,col1).display(disp);
352
                 x0 = x1; y0 = y1;
353
              }
354
         }
355
         disp.wait();
356
        if (disp.is_resized) disp.resize(disp);
357
       }
358
 curve.draw_line(x1,y1,xo,yo,col2).channel(0).draw_fill(0,0,col3);
359
return curve;
360
}
361
362
       
363
        //////////////////////////////////////////////////////////////////////////////////////////////
364
365
366
        
367
   
368
  
369
     
370
371
  
372
373
374