MumfordShahEnergy.hpp

00001 // This file is part of the imaging2 class library.
00002 //
00003 // University of Innsbruck, Infmath Imaging, 2009.
00004 // http://infmath.uibk.ac.at
00005 //
00006 // All rights reserved.
00007 
00008 
00009 #ifndef ENERGY_MUMFORDSHAH_H
00010 #define ENERGY_MUMFORDSHAH_H
00011 
00012 #include <image/Image.hpp>
00013 #include <image/ScalarImage.hpp>
00014 #include <image/utilities.hpp>
00015 #include <shape/BoundaryDiscretizer.hpp>
00016 #include <shape/ShapeStatistics.hpp>
00017 #include <shape/ShapeEnergyInterface.hpp>
00018 #include <minimize/DifferentiableEnergyInterface.hpp>
00019 
00020 
00021 namespace imaging 
00022 {
00049   template <class shape_t>
00050   class MumfordShahEnergy : public DifferentiableEnergyInterface, public ShapeEnergyInterface<shape_t>
00051   {
00052     const static std::size_t N = shape_t::SHAPE_DIMENSION;
00053     
00054     Image<N, ublas::fixed_vector<float_t, N> > _contrast_vector_field;
00055     Image<N, ublas::fixed_vector<float_t, N> > _squared_contrast_vector_field;
00056     Image<N, ublas::fixed_vector<float_t, N> > _volume_vector_field;
00057     Image<N, float_t> _image;
00058     float_t _beta;
00059     std::size_t _n_integration_points;
00060     
00061     ublas::vector<float_t> _current_argument;
00062     ublas::vector<float_t> _current_gradient;
00063     float_t _current_energy;
00064     shape_t _current_shape;
00065     shape_t _initial_shape;
00066     
00067     float_t _image_volume;
00068     float_t _image_contrast;
00069     float_t _squared_image_contrast;
00070     
00071     void compute_energy(float_t & u_1, float_t & u_2, float_t & energy);
00072        
00073   public:
00074   
00076     template <class const_accessor_t>
00077     MumfordShahEnergy(const const_accessor_t & image,
00078                 const shape_t & initial_shape,
00079                 float_t beta,
00080                 std::size_t n_integration_points);
00081     
00082     ublas::vector<float_t> & current_argument() { return _current_argument; }
00083     float_t current_energy() const { return _current_energy; }
00084     std::size_t dimension() const { return _initial_shape.dimension(); }
00085     const shape_t & current_shape() const { return _current_shape; }
00086 
00087     const ublas::vector<float_t> & current_gradient() const { return _current_gradient; }
00088     
00089     void set_argument();
00090     void set_argument_with_gradient();
00091   };
00092   
00093   template <class shape_t>
00094   template <class const_accessor_t>
00095   MumfordShahEnergy<shape_t>::MumfordShahEnergy(const const_accessor_t & image,
00096                 const shape_t & initial_shape,
00097                 float_t beta,
00098                 std::size_t n_integration_points) :
00099     _beta(beta),
00100     _initial_shape(initial_shape),
00101     _current_shape(initial_shape),
00102     _n_integration_points(n_integration_points),
00103     _current_argument(ublas::scalar_vector<float_t>(initial_shape.dimension(), 0.0)),
00104     _current_gradient(initial_shape.dimension()),
00105     _contrast_vector_field(image.size()),
00106     _squared_contrast_vector_field(image.size()),
00107     _volume_vector_field(image.size()),
00108     _image(image)
00109   {
00110     Image<N, float_t> squared_image(_image.size());
00111     ublas::fixed_vector<size_t, N> index;
00112     index.assign(0);
00113     do
00114     {
00115       squared_image[index] = square(_image[index]);
00116     }
00117     while(increment_index(_image.size(), index));
00118   
00119     compute_divergence_field(image, _contrast_vector_field);
00120     compute_divergence_field(squared_image, _squared_contrast_vector_field);
00121     compute_divergence_field(ScalarImage<N, float_t>(image.size(), 1.0), _volume_vector_field);
00122     
00123     _image_volume = 1.0;
00124     
00125     for(std::size_t i = 0; i < N; ++i)
00126       _image_volume *= float_t(image.size()(i));
00127       
00128     _image_contrast = 0.0;
00129     _squared_image_contrast = 0.0;
00130     
00131     index.assign(0);
00132     do
00133     {
00134       _image_contrast += _image[index];
00135       _squared_image_contrast += squared_image[index];
00136     }
00137     while(increment_index(_image.size(), index));
00138                                                         
00139     set_argument_with_gradient();
00140   }
00141   
00142   template <class shape_t>
00143   void MumfordShahEnergy<shape_t>::set_argument()
00144   {
00145     float_t u_1, u_2;
00146     
00147     compute_energy(u_1, u_2, _current_energy);
00148   }
00149   
00150   
00151   template <class shape_t>
00152   void MumfordShahEnergy<shape_t>::set_argument_with_gradient()
00153   {
00154     shape_t perturbed_shape;
00155     ublas::vector<float_t> perturbed_argument(dimension());
00156     ublas::vector<float_t> statistics_gradient(dimension());
00157     const float_t FINITE_H = 0.001;
00158     ublas::fixed_vector<float_t, shape_t::SHAPE_DIMENSION> point, normal;
00159     float_t u_1, u_2;
00160     
00161     perturbed_argument = _current_argument;
00162     _current_gradient = ublas::scalar_vector<float_t>(dimension(), 0.0);
00163     
00164     compute_energy(u_1, u_2, _current_energy);
00165     
00166     std::auto_ptr< BoundaryDiscretizer<shape_t::SHAPE_DIMENSION> > discretizer = _current_shape.boundary_discretizer(_n_integration_points);
00167 
00168     for(std::size_t k = 0; k < dimension(); ++k)
00169     {
00170       perturbed_argument(k) += FINITE_H;
00171       
00172       _initial_shape.exponential(perturbed_argument, perturbed_shape);
00173       
00174       std::auto_ptr< BoundaryDiscretizer<shape_t::SHAPE_DIMENSION> > perturbed_discretizer = perturbed_shape.boundary_discretizer(_n_integration_points);
00175 
00176       ublas::fixed_vector<float_t, shape_t::SHAPE_DIMENSION> perturbed_point, perturbed_normal, shape_derivative, shape_normal_derivative;
00177       float_t image_value;
00178   
00179       for(std::size_t j = 0; j < _n_integration_points; ++j)
00180       {
00181         perturbed_point = (*perturbed_discretizer)(j, perturbed_normal);
00182         point = (*discretizer)(j, normal);
00183         
00184         shape_derivative = 1.0 / FINITE_H * (perturbed_point - point);
00185         shape_normal_derivative = 1.0 / FINITE_H * (perturbed_normal - normal);
00186         
00187         // explicit cast of floating point values in "point" to pixel position!
00188         ublas::fixed_vector<size_t, N> pixel_position = ublas::fixed_vector<size_t, N>(point);   
00189         bool is_valid_pixel = true;
00190         
00191         for(std::size_t i = 0; i < N; ++i)
00192         {
00193           if( ! ( pixel_position(i) < _image.size()(i) ) )
00194           {
00195             is_valid_pixel = false;
00196             break;
00197           }
00198         }
00199         
00200         if(is_valid_pixel)
00201         {
00202         
00203           image_value = _image[pixel_position];
00204           
00205           _current_gradient(k) += ( square(u_1 - image_value) - square(u_2 - image_value) ) *
00206                                   inner_prod(normal, shape_derivative) * sqrt(norm_2(normal));
00207         }
00208         _current_gradient(k) += 2.0 * _beta * inner_prod(normal, shape_normal_derivative);
00209       }  
00210         
00211       perturbed_argument(k) -= FINITE_H;   
00212     }
00213   }
00214   
00215   template <class shape_t>
00216   void MumfordShahEnergy<shape_t>::compute_energy(float_t & u_1, float_t & u_2, float_t & energy)
00217   {
00218     _current_gradient = ublas::scalar_vector<float_t>(dimension(), 0.0);
00219     
00220     _initial_shape.exponential(_current_argument, _current_shape);
00221     
00222     float_t inner_contrast, outer_contrast;
00223     float_t inner_squared_contrast, outer_squared_contrast;
00224     float_t inner_volume, outer_volume;
00225     
00226     std::auto_ptr< BoundaryDiscretizer<shape_t::SHAPE_DIMENSION> > discretizer = _current_shape.boundary_discretizer(_n_integration_points);
00227     
00228     inner_contrast = discretizer->integrate_vector_field(_contrast_vector_field);
00229     inner_squared_contrast = discretizer->integrate_vector_field(_squared_contrast_vector_field);
00230     inner_volume = discretizer->integrate_vector_field(_volume_vector_field);
00231     
00232     outer_contrast = _image_contrast - inner_contrast;
00233     outer_squared_contrast = _squared_image_contrast - outer_squared_contrast;
00234     outer_volume = _image_volume - inner_volume;
00235     
00236     u_1 = inner_contrast / inner_volume;
00237     u_2 = outer_contrast / outer_volume;
00238     
00239     float_t shape_boundary_energy = 0.0;
00240     ublas::fixed_vector<float_t, shape_t::SHAPE_DIMENSION> point, normal;
00241     for(std::size_t j = 0; j < _n_integration_points; ++j)
00242     {
00243       point = (*discretizer)(j, normal);
00244       shape_boundary_energy += inner_prod(normal, normal);
00245     }
00246         
00247     energy = square(u_1) * inner_volume - 2 * u_1 * inner_contrast + inner_squared_contrast +
00248                       square(u_2) * outer_volume - 2 * u_2 * outer_contrast + outer_squared_contrast +
00249                       _beta * shape_boundary_energy;
00250   
00251   }
00252 
00253 }
00254 
00255 
00256 #endif

Generated on Tue Feb 10 10:01:30 2009 for imaging2 by  doxygen 1.5.5