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