Jerome Piovano

Research in Medical Imaging and Computer Vision

/home/jpiovano/src/Odyssee++/trunk/Libs/LevelSet/src/SegmentationModule/GeodesicActiveContourModule.h

Go to the documentation of this file.
00001 
00009 #ifndef GEODESICACTIVECONTOURMODULE_H
00010 #define GEODESICACTIVECONTOURMODULE_H
00011 
00012 #include <SegmentationModule/SegmentationModule.h>
00013 #include <DericheFilter.h>
00014 
00015 namespace segmentation {
00016 
00017 
00025         template <unsigned DIM, typename Pixel, typename PixelImage = float> 
00026         class GeodesicActiveContourModule : public SegmentationModule<DIM, Pixel>
00027         {
00028         public:
00029 
00030                 typedef          SegmentationModule<DIM, Pixel>  base;
00031                 typedef typename base::LevelSet                  LevelSet;
00032                 typedef typename base::Index                     Index;
00033                 typedef          DericheFilter<DIM, PixelImage>  DericheFilter;
00034 
00035                 typedef          BaseImage<DIM, PixelImage>      ImageType;
00036                 typedef          BaseImage<DIM, float>           ImageFloat;
00037 
00040 
00042                 GeodesicActiveContourModule(ImageType *  _data,             
00043                                             float        _weight = 1.f,     
00044                                             float        _v = 0.f,          
00045                                             float        _smooth = 3.0f     
00046                                             );
00047 
00049                 virtual ~GeodesicActiveContourModule();
00050 
00052 
00054 
00056                 void compute_metric(ImageType * _data, float _smooth = 3.0f);
00058                 void set_metric(const ImageFloat & g, ImageFloat * g_deriv = NULL);
00060                 float& balloon();
00062                 const ImageFloat & metric();
00063 
00065 
00067 
00069                 float value(const LevelSet & phi, const Index & ind);
00071                 float energy(const LevelSet & phi, const Index & ind);
00073                 void init(const LevelSet & phi);
00075                 void save_result(const LevelSet & phi, std::string evodir, int iter);
00076 
00078 
00079         protected:      
00080 
00081                 inline float _g(float v, float p)
00082                 {
00083                         return 1/(1+pow(v,p));
00084                 }
00085 
00088 
00089                 ImageFloat   m_g;             
00090                 ImageFloat   m_g_deriv[DIM];  
00091                 float        m_v;             
00092 
00094 
00095         };
00096 
00097 
00101 
00102         // Constructors - Destructor
00103 
00104 
00105         template <unsigned DIM, typename Pixel, typename PixelImage>
00106                 GeodesicActiveContourModule<DIM, Pixel, PixelImage>::GeodesicActiveContourModule(ImageType * _data, float _weight, float _v, float _smooth)
00107                 :SegmentationModule<DIM, Pixel>(_weight, false), m_g(_data->shape()), m_v(_v)
00108         { 
00109                 for (int i=0 ; i<DIM ; i++)
00110                         m_g_deriv[i].resize(_data->shape());
00111 
00112                 compute_metric(_data, _smooth);
00113         }
00114 
00115         template <unsigned DIM, typename Pixel, typename PixelImage>
00116                 GeodesicActiveContourModule<DIM, Pixel, PixelImage>::~GeodesicActiveContourModule() 
00117         { }
00118 
00119 
00121         // Modify/Access member data
00122 
00123 
00124         template <unsigned DIM, typename Pixel, typename PixelImage>
00125                 void GeodesicActiveContourModule<DIM, Pixel, PixelImage>::compute_metric(ImageType * _data, float _smooth)
00126         {
00127                 // smoothed image 
00128                 ImageType image_smooth(_data->shape());
00129                 image_smooth = _data->copy();
00130                 DericheFilter deriche(_smooth);
00131                 deriche.filter(image_smooth);
00132 
00133                 // metric computation : g = 1 / (1 + sqrt(|grad I|) )
00134                 if (m_g.shape() != _data->shape()) m_g.resize(_data->shape());
00135                 for (typename ImageFloat::template iterator<domain> ind=m_g.begin() ; ind!=m_g.end() ; ++ind )
00136                         m_g(ind) = _g(Schemes<DIM,PixelImage>::norm_gradient(image_smooth, ind.position()), 0.5f);
00137 
00138                 // -0.2 to assure a range of value where the metric is 0
00139                 Globals::normalize<DIM, PixelImage>(m_g, -0.2f, 1);
00140                 Globals::cut<DIM, PixelImage>(m_g, 0, 1);
00141 
00142                 // directional derivative of the metric
00143                 for (int i=0 ; i<DIM ; i++)
00144                         if (m_g_deriv[i].shape() != _data->shape()) m_g_deriv[i].resize(_data->shape());
00145 
00146                 PixelImage grad[DIM];
00147                 for (typename ImageFloat::template iterator<domain> ind=m_g.begin() ; ind!=m_g.end() ; ++ind ){
00148                         Schemes<DIM, float>::gradient(m_g, ind.position(), grad);
00149                         for (int i=0 ; i<DIM ; i++)
00150                                 m_g_deriv[i](ind.position()) = grad[i];
00151                 }
00152 
00153         }
00154 
00155         template <unsigned DIM, typename Pixel, typename PixelImage>
00156                 void GeodesicActiveContourModule<DIM, Pixel, PixelImage>::set_metric(const ImageFloat & g, ImageFloat * g_deriv)
00157         {
00158                 m_g = g;
00159 
00160                 if (g_deriv != NULL)
00161                         for (int i=0 ; i<DIM ; i++)
00162                                 m_g_deriv[i] = g_deriv[i];
00163                         
00164                 else {
00165                         // directional derivative of the metric
00166                         for (int i=0 ; i<DIM ; i++)
00167                                 if (m_g_deriv[i].shape() != m_g.shape()) m_g_deriv[i].resize(m_g.shape());
00168 
00169                         PixelImage grad[DIM];
00170                         for (typename ImageFloat::template iterator<domain> ind=m_g.begin() ; ind!=m_g.end() ; ++ind ){
00171                                 Schemes<DIM, float>::gradient(m_g, ind.position(), grad);
00172                                 for (int i=0 ; i<DIM ; i++)
00173                                         m_g_deriv[i](ind.position()) = grad[i];
00174                         }
00175                 }
00176         }
00177 
00178         template <unsigned DIM, typename Pixel, typename PixelImage>
00179                 float& GeodesicActiveContourModule<DIM, Pixel, PixelImage>::balloon()
00180         {
00181                 return m_v;
00182         }
00183 
00184         template <unsigned DIM, typename Pixel, typename PixelImage>
00185                 const typename GeodesicActiveContourModule<DIM, Pixel, PixelImage>::ImageFloat & GeodesicActiveContourModule<DIM, Pixel, PixelImage>::metric()
00186         {
00187                 return m_g;
00188         }
00189 
00190 
00192         // Member functions
00193 
00194 
00195         template <unsigned DIM, typename Pixel, typename PixelImage>
00196                 float GeodesicActiveContourModule<DIM, Pixel, PixelImage>::value(const LevelSet & phi, const Index & ind)
00197         {
00198                 Pixel grad[DIM];
00199                 Pixel gnorm = 0;
00200 
00201                 Schemes<DIM,Pixel>::gradient(phi, ind, grad);
00202                 for (int i=0 ; i<DIM ; i++)
00203                         gnorm += Maths::sqr(grad[i]);
00204                 gnorm = sqrt(gnorm);
00205 
00206                 float result = m_g(ind)*gnorm*(Schemes<DIM,Pixel>::mean_curvature(phi,ind) - m_v);
00207                 for (int i=0 ; i<DIM ; i++)
00208                         result += grad[i]*m_g_deriv[i](ind);
00209 
00210                 return result;
00211         }        
00212 
00213         template <unsigned DIM, typename Pixel, typename PixelImage>
00214                 float GeodesicActiveContourModule<DIM, Pixel, PixelImage>::energy(const LevelSet & phi, const Index & ind)
00215         {
00216                 return m_g(ind) * Globals::delta(phi(ind));
00217         }
00218 
00219         template <unsigned DIM, typename Pixel, typename PixelImage>
00220                 void GeodesicActiveContourModule<DIM, Pixel, PixelImage>::init(const LevelSet & phi)
00221         {
00222                 base::init(phi);
00223 
00224                 if (m_g.shape() != phi.shape()) {
00225                         std::cerr << "Error : Shape of the Level Set and shape of the metric don't match"  << std::endl;
00226                         exit(1);
00227                 }
00228         }
00229 
00230         template <unsigned DIM, typename Pixel, typename PixelImage>
00231                 void GeodesicActiveContourModule<DIM, Pixel, PixelImage>::save_result(const LevelSet & phi, std::string evodir, int iter)
00232         {
00233                 if (iter == 0){
00234                         std::ostringstream name;
00235                         name.str("");
00236                         name << evodir << "Metric.inr";
00237                         std::ofstream file(name.str().c_str());
00238                         file << format("inrimage") << m_g ;
00239                         std::cout <<  " - Saved " << name.str() << " ..."  << std::endl;
00240                         for (int i=0 ; i<DIM ; i++){
00241                                 name.str("");
00242                                 name << evodir << "Metric_" << i << ".inr";
00243                                 std::ofstream file(name.str().c_str());
00244                                 file << format("inrimage") << m_g_deriv[i] ;
00245                                 std::cout <<  " - Saved " << name.str() << " ..."  << std::endl;
00246                         }
00247                 }
00248         }
00249 
00250 }
00251 
00252 #endif // GEODESICACTIVECONTOURMODULE_H

For further information, please contact Jerome Piovano - Last update 2008-02-08