Switch to unified view

a b/Thoracic Organs Segmentation code/OpticalFlow3D/OpticalFlow3D.asv
1
/*-----------------------------------------------------------------------
2
3
--------------------------------------------------------------------------*/
4
5
#include <mex.h>
6
#include <mat.h>
7
#include <matrix.h>
8
9
#define cimg_plugin "cimgmatlab.h"
10
11
#include "CImg.h"
12
#include <iostream>
13
#include <string>
14
15
using namespace cimg_library;
16
using namespace std;
17
18
// The lines below are necessary when using a non-standard compiler as visualcpp6.
19
#ifdef cimg_use_visualcpp6
20
#define std
21
#endif
22
#ifdef min
23
#undef min
24
#undef max
25
#endif
26
27
#ifndef cimg_imagepath
28
#define cimg_imagepath "img/"
29
#endif
30
31
//global constants
32
const float smooth = 0.1f;//"Flow Smoothness"
33
const float precision = 0.09f;//"Convergence precision"
34
const unsigned int nb=110;//"Number of warped frames"
35
const unsigned int nbscale = 0 ;//"Number of scales (0=auto)");
36
37
const bool normalize = true; //"Histogram normalization of the images"
38
const bool morph = true;//"Morphing mode"
39
const bool imode  = true;//"Complete interpolation (or last frame is missing)"
40
const bool dispflag = true;//"Visualization"
41
//Functions
42
CImg<> optmonoflow(const CImg<>& I1, const CImg<>& I2, const CImg<>& u0,
43
                   const float smooth, const float precision, CImgDisplay& disp);
44
CImg<> optflow(const CImg<>& xsrc, const CImg<>& xdest,
45
               const float smooth, const float precision, const unsigned int pnb_scale, CImgDisplay& disp);
46
                
47
//mex function
48
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
49
  if (nrhs < 2) mexErrMsgTxt("No enough input arguments.");
50
  if (nrhs > 2) mexErrMsgTxt("Too many input arguments.");
51
  if (nrhs == 2){
52
                CImg<> src_blur(prhs[0],false), dest_blur(prhs[1],false);//2 Input Volumes
53
                //Input images preprocessing
54
                 src_blur = normalize?src_blur.get_blur(0.5f).equalize(256):src_blur.get_blur(0.5f),
55
                 dest_blur  = normalize?dest_blur.get_blur(0.5f).equalize(256):dest_blur.get_blur(0.5f);
56
                 CImgDisplay disp;
57
                 const CImg<> u = optflow(src_blur,dest_blur,smooth,precision,nbscale,disp);
58
                CImgDisplay disp2(src_blur);
59
                 
60
                 plhs[0] = u.toMatlab();
61
                      
62
                }
63
  return;
64
     
65
}
66
/////////////////////////////////////////////////////////////////////////////////
67
68
CImg<> optflow(const CImg<>& xsrc, const CImg<>& xdest,
69
               const float smooth, const float precision, const unsigned int pnb_scale, CImgDisplay& disp) {
70
  const CImg<>
71
    src  = xsrc.get_pointwise_norm(1).resize(xdest.dimx(),xdest.dimy(),xdest.dimz()).normalize(0,1),
72
    dest = xdest.get_pointwise_norm(1).resize(xdest.dimx(),xdest.dimy(),xdest.dimz()).normalize(0,1);
73
    CImg<> u =  CImg<>(src.dimx(),src.dimy(),src.dimz(),3,1).fill(0);
74
       
75
  //multi-scalling 
76
    const unsigned int nb_scale = pnb_scale>0?pnb_scale:(unsigned int)(2*log((double)(max(max(src.dimx(),src.dimy()),src.dimz()))));
77
  //const unsigned int nb_scale = pnb_scale>0?pnb_scale:(unsigned int)(2*std::log((double)(cimg::max(src.dimx(),src.dimy()))));
78
  for (int scale=nb_scale-1; scale>=0; scale--) {
79
       const CImg<> I1 = src.get_resize((int)(src.dimx()/std::pow(1.5,scale)), (int)(src.dimy()/std::pow(1.5,scale)) ,(int)(ceil(src.dimz()/std::pow(1.5,scale))));
80
       const CImg<> I2 = dest.get_resize((int)(src.dimx()/std::pow(1.5,scale)), (int)(src.dimy()/std::pow(1.5,scale)) ,(int)(ceil(src.dimz()/std::pow(1.5,scale))));
81
       u*=1.5;
82
       u = optmonoflow(I1,I2,u,smooth,(float)(precision/std::pow(2.25,1+scale)),disp);//apply optical flow algorithm for different scales
83
    
84
  }
85
 return u;
86
}
87
88
// optmonoflow() : estimate optical flow for one scale ( semi-implicite PDE scheme ) between I2->I1
89
//---------------
90
CImg<> optmonoflow(const CImg<>& I1, const CImg<>& I2, const CImg<>& u0,
91
                   const float smooth, const float precision, CImgDisplay& disp) {
92
93
 CImg<float> u = u0.get_resize(I1.dimx(),I1.dimy(),I1.dimz(),3);
94
 CImg<float> dI(I2.dimx(),I2.dimy(),I2.dimz(),3);
95
  dI.fill(0);
96
 //CImg_3x3x3(I,float);
97
  float dt=2,E=1e20f;
98
99
  // compute first derivatives of I2
100
    cimg_for3XYZ(dI,x,y,z){
101
              dI(x,y,z,0) = 0.5*(I2(_n1x,y,z)-I2(_p1x,y,z));//derivatives of I2
102
              dI(x,y,z,1) = 0.5*(I2(x,_n1y,z)-I2(x,_p1y,z));
103
              dI(x,y,z,2) = 0.5*(I2(x,y,_n1z)-I2(x,y,_p1z));
104
                          
105
     }
106
   
107
// Main PDE iteration
108
for (unsigned int iter=0; iter<10000; iter++) {
109
    std::fprintf(stderr,"\r- Iteration %d - E = %g",iter,E); std::fflush(stderr);
110
    const float Eold = E;
111
    E = 0;
112
    cimg_for3XYZ(u,x,y,z) { //3x3 neighborhood  
113
      const float
114
        X = x + u(x,y,z,0),
115
        Y = y + u(x,y,z,1),
116
        Z = z + u(x,y,z,2),
117
        deltaI = (float)(I2.linear_atXYZ(X,Y,Z) - I1(x,y,z));// partial derivative over time-dI/dt
118
      float tmpf = 0;
119
      cimg_forV(u,k) {
120
        const float
121
          ux  = 0.5f*(u(_n1x,y,z,k)-u(_p1x,y,z,k)),//derivatives of velocity(displacemenet)
122
          uy  = 0.5f*(u(x,_n1y,z,k)-u(x,_p1y,z,k)),
123
          uz  = 0.5f*(u(x,y,_n1z,k)-u(x,y,_p1z,k)); 
124
          u(x,y,z,k) = (float)( u(x,y,z,k) +
125
                            dt*(
126
                                -deltaI*dI.linear_atXYZ(X,Y,Z,k) +
127
                                smooth* ( u(_n1x,y,z,k) + u(_p1x,y,z,k) + u(x,_n1y,z,k) + u(x,_p1y,z,k)+  u(x,y,_n1z,k) + u(x,y,_p1z,k)-6*u(x,y,z,k))
128
                                )/(1+4*smooth*dt)
129
                              );
130
      tmpf += ux*ux + uy*uy + uz*uz;
131
     
132
      }
133
      E += deltaI*deltaI + smooth * tmpf;
134
    }
135
    if (cimg::abs(Eold-E)<precision) break;
136
    if (Eold<E) dt*=0.5;
137
 
138
}
139
  return  I1;
140
}
141
142