00001 #ifndef EQUATION_GEODESICACTIVECONTOURSTEP_H
00002 #define EQUATION_GEODESICACTIVECONTOURSTEP_H
00003
00004 #include <core/utilities.hpp>
00005 #include <fem/equation/SimpleEquationInterface.hpp>
00006 #include <boost/shared_ptr.hpp>
00007
00008 namespace imaging
00009 {
00033 template<class fem_types>
00034 class GeodesicActiveContourStep : public SimpleEquationInterface<fem_types>
00035 {
00036 boost::shared_ptr< ublas::vector<float_t> > _edges_ptr;
00037 boost::shared_ptr< ublas::vector<float_t> > _initial_function_ptr;
00038 float_t _step_size;
00039 float_t _epsilon;
00040 float_t _edge_parameter;
00041 float_t _balloon_force;
00042
00043 float_t regularized_abs(const ublas::fixed_vector<float_t, fem_types::data_dimension > & gradient) const
00044 {
00045 return sqrt(square(_epsilon) + inner_prod(gradient, gradient));
00046 }
00047
00048 public:
00049 typedef ublas::fixed_matrix<float_t, fem_types::data_dimension, fem_types::data_dimension> matrix_coefficient_t;
00050
00052 const ublas::vector<float_t> & edges() const { return *_edges_ptr; }
00053
00055 void set_edges(boost::shared_ptr< ublas::vector<float_t> > edges_ptr) { _edges_ptr = edges_ptr; }
00056
00058 const ublas::vector<float_t> & initial_function() const { return *_initial_function_ptr; }
00059
00061 void set_initial_function(boost::shared_ptr< ublas::vector<float_t> > initial_function_ptr) { _initial_function_ptr = initial_function_ptr; }
00062
00064 float_t step_size() const { return _step_size; }
00065
00067 void set_step_size(float_t step_size) { _step_size = step_size; }
00068
00070 float_t epsilon() const { return _epsilon;}
00071
00073 void set_epsilon(float_t epsilon) { _epsilon = epsilon; }
00074
00076 float_t edge_parameter() const { return _edge_parameter;}
00077
00079 void set_edge_parameter(float_t edge_parameter) { _edge_parameter = edge_parameter; }
00080
00082 float_t balloon_force() const { return _balloon_force;}
00083
00085 void set_balloon_force(float_t balloon_force) { _balloon_force = balloon_force; }
00086
00087 static const size_t boundary_data_type = SimpleEquationInterface<fem_types>::NO_BOUNDARY_DATA;
00088
00089 static const bool a_active = false;
00090 static const bool b_active = false;
00091 static const bool c_active = true;
00092 static const bool f_active = true;
00093 static const bool g_active = false;
00094
00095 void stiffness_matrix(std::size_t integrator_node,
00096 const FemKernel<fem_types> & kernel,
00097 matrix_coefficient_t & A,
00098 ublas::fixed_vector<float_t, fem_types::data_dimension> & a,
00099 ublas::fixed_vector<float_t, fem_types::data_dimension> & b,
00100 float_t & c) const
00101 {
00102 float_t local_edge;
00103 ublas::fixed_vector<float_t, fem_types::data_dimension > local_gradient;
00104
00105 kernel.grid().interpolate_value(integrator_node, *_edges_ptr, kernel, local_edge);
00106 kernel.grid().interpolate_gradient(integrator_node, *_initial_function_ptr, kernel, local_gradient);
00107
00108 A = _step_size * exp(- _edge_parameter * square(local_edge)) / regularized_abs(local_gradient) *
00109 ublas::identity_matrix<float_t>(fem_types::data_dimension);
00110
00111 c = 1.0 / regularized_abs(local_gradient);
00112
00113 }
00114
00115 void force_vector(std::size_t integrator_node,
00116 const FemKernel<fem_types> & kernel,
00117 float_t & f,
00118 ublas::fixed_vector<float_t, fem_types::data_dimension> & g) const
00119 {
00120
00121 float_t local_edge, local_value;
00122 ublas::fixed_vector<float_t, fem_types::data_dimension > local_gradient;
00123
00124 kernel.grid().interpolate_value(integrator_node, *_edges_ptr, kernel, local_edge);
00125 kernel.grid().interpolate_value(integrator_node, *_initial_function_ptr, kernel, local_value);
00126 kernel.grid().interpolate_gradient(integrator_node, *_initial_function_ptr, kernel, local_gradient);
00127
00128 f = local_value / regularized_abs(local_gradient) + _step_size * exp(- _edge_parameter * square(local_edge)) * _balloon_force;
00129 }
00130
00131 bool sanity_check_stiffness_matrix(const FemKernel<fem_types> & kernel, std::string & error_message) const
00132 {
00133 if(! (_edges_ptr && _initial_function_ptr))
00134 return false;
00135
00136 if(_edges_ptr->size() != kernel.grid().n_nodes())
00137 return false;
00138
00139 if(_initial_function_ptr->size() != kernel.grid().n_nodes())
00140 return false;
00141
00142 return true;
00143 }
00144
00145 bool sanity_check_force_vector(const FemKernel<fem_types> & kernel, std::string & error_message) const
00146 {
00147 if(! (_edges_ptr && _initial_function_ptr))
00148 return false;
00149
00150 if(_edges_ptr->size() != kernel.grid().n_nodes())
00151 return false;
00152
00153 if(_initial_function_ptr->size() != kernel.grid().n_nodes())
00154 return false;
00155
00156 return true;
00157 }
00158 };
00159
00160 }
00161
00162
00163 #endif