ShapeStatistics.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 SHAPE_SHAPESTATISTICS_H
00010 #define SHAPE_SHAPESTATISTICS_H
00011 
00012 #include <shape/ShapeInterface.hpp>
00013 #include <lapack/linear_algebra.hpp>
00014 #include <core/distribution_utilities.hpp>
00015 
00016 #include <map>
00017 #include <boost/shared_ptr.hpp>
00018 
00019 
00020 namespace imaging
00021 {
00022   namespace shape_statistics_impl
00023   {
00024     void constructor(const std::vector<const ShapeInterface*> shape_ptrs, ShapeInterface & mean_shape, ublas::matrix<float_t> & covariance);
00025     void compute_statistics(const std::map<std::size_t, float_t> & manual_modes, const ublas::matrix<float_t> & covariance, ublas::matrix<float_t> & root_of_covariance);
00026   }
00027 
00037   template <class shape_t>
00038   class ShapeStatistics
00039   {
00040     const static std::size_t SHAPE_DIMENSION = shape_t::SHAPE_DIMENSION;
00041     
00042     ublas::matrix<float_t> _covariance;
00043     ublas::matrix<float_t> _root_of_covariance;
00044     
00045     shape_t _mean_shape;
00046     
00047     std::map<std::size_t, float_t> _manual_modes;
00048      
00049   public:
00050   
00052     ShapeStatistics(const shape_t & mean_shape) : 
00053       _mean_shape(mean_shape),
00054       _covariance(ublas::identity_matrix<float_t>(mean_shape.dimension())),
00055       _root_of_covariance(ublas::identity_matrix<float_t>(mean_shape.dimension())) {}
00056     
00058     ShapeStatistics(const std::vector<shape_t> & shapes)
00059     {
00060       std::vector<const ShapeInterface *> shape_ptrs(shapes.size());
00061       for(size_t i = 0; i < shapes.size(); ++i)
00062         shape_ptrs[i] = &(shapes[i]);
00063       
00064       shape_statistics_impl::constructor(shape_ptrs, _mean_shape, _covariance);
00065     }
00066     
00068     ShapeStatistics(const std::vector< boost::shared_ptr<shape_t> > & shapes)
00069     {
00070       std::vector<const ShapeInterface *> shape_ptrs(shapes.size());
00071       for(size_t i = 0; i < shapes.size(); ++i)
00072         shape_ptrs[i] = shapes[i].get();
00073       
00074       shape_statistics_impl::constructor(shape_ptrs, _mean_shape, _covariance);
00075     }
00076     
00078     void set_mode_manually(std::size_t mode, float_t deviation)
00079     {
00080       _manual_modes.insert(std::pair<std::size_t, float_t>(mode, deviation));
00081     }
00082     
00084     void compute_statistics()
00085     {
00086       shape_statistics_impl::compute_statistics(_manual_modes, _covariance, _root_of_covariance);
00087     }
00088     
00090     void shape_vector(const ublas::vector<float_t> & coefficients, ublas::vector<float_t> & vector) const
00091     {
00092       vector.resize(dimension());
00093       vector = prod(_root_of_covariance, coefficients);
00094     }
00095     
00097     void shape_vector(const ublas::vector<float_t> & coefficients, ublas::vector<float_t> & vector, float_t & squared_distance) const
00098     {
00099       vector.resize(dimension());
00100       vector = prod(_root_of_covariance, coefficients);
00101       
00102       squared_distance = 0.0;
00103       for(std::size_t i = 0; i < coefficients.size(); ++i)
00104         if(_manual_modes.count(i) == 0)
00105           squared_distance += square(coefficients(i));
00106     }
00107   
00109     void shape_sample(const ublas::vector<float_t> & coefficients, shape_t & out_shape) const
00110     {
00111       float_t squared_distance;
00112       shape_sample(coefficients, out_shape, squared_distance);
00113     }
00114 
00116     void shape_sample(const ublas::vector<float_t> & coefficients, shape_t & out_shape, float_t & squared_distance) const
00117     { 
00118       ublas::vector<float_t> sample_vector(_mean_shape.dimension());
00119       shape_vector(coefficients, sample_vector, squared_distance);
00120   
00121       _mean_shape.exponential(sample_vector, out_shape);
00122     }  
00123     
00125     void gradient(const ublas::vector<float_t> & coefficients, ublas::vector<float_t> & gradient) const
00126     { 
00127       gradient.resize(_mean_shape.dimension());
00128       
00129       gradient = 2 * coefficients;
00130       
00131       for(std::map<std::size_t, float_t>::const_iterator iter = _manual_modes.begin(); iter != _manual_modes.end(); ++iter)
00132         gradient(iter->first) = 0.0;
00133     }
00134     
00136     void random_shape_sample(float_t sample_radius, shape_t & out_shape, float_t & squared_distance) const
00137     {
00138       ublas::vector<float_t> coefficients(_covariance.size1());
00139       
00140       for(std::size_t i = 0; i < coefficients.size(); ++i)
00141       {
00142         if(_manual_modes.count(i) > 0)
00143           coefficients(i) = symmetric_uniform_distribution();
00144         else
00145           coefficients(i) = sample_radius * normal_distribution();
00146       }
00147           
00148       shape_sample(coefficients, out_shape, squared_distance);
00149     }
00150     
00152     const shape_t & mean_shape() const { return _mean_shape; }
00153     
00155     shape_t & mode_shape(std::size_t mode, float_t offset, shape_t & out_shape) const
00156     {
00157       float_t distance_from_mean;
00158       
00159       ublas::vector<float_t> coefficients(_covariance.size1());
00160       
00161       coefficients = ublas::scalar_vector<float_t>(coefficients.size(), 0.0);
00162         
00163       coefficients(mode) = offset;
00164       
00165       shape_sample(coefficients, out_shape, distance_from_mean);
00166       
00167       return out_shape;
00168     }
00169     
00171     size_t dimension() const
00172     {
00173       return _mean_shape.dimension();
00174     }
00175     
00176   };
00177   
00178 }
00179 
00180 
00181 #endif

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