00001 #ifndef rrel_estimation_problem_h_ 00002 #define rrel_estimation_problem_h_ 00003 //: 00004 // \file 00005 // \author Chuck Stewart 00006 // \date March 2001 00007 // \brief Base class for an estimation problem in the robust estimation library. 00008 00009 #include <vcl_vector.h> 00010 #include <vnl/vnl_fwd.h> 00011 00012 class rrel_wls_obj; 00013 00014 //: Base class for (robust) estimation problems. 00015 // A fundamental design decision is that the objective function to be 00016 // minimized is not tied to the class. This allows different robust 00017 // objective functions to be used with the same data and function 00018 // model. A disadvantage is that computing the derivative of the 00019 // objective with respect to the data or the model parameters is not 00020 // straightforward. So far this hasn't proven to be a problem. 00021 // 00022 // A second design decision is that functions are provided for 00023 // indirect access to the data for residual and weight calculation and 00024 // to support random sampling operations. Only a few key functions are 00025 // pure virtual; others will cause an abort (with an error message) 00026 // unless overridden. This allows errors to be detected (albeit at 00027 // run-time) if they are used improperly without requiring subclasses 00028 // to redefine unneeded functions. For example, if a derived class 00029 // does not implement compute_weights(), then attempting to solve that 00030 // problem with IRLS will cause an abort at runtime. 00031 00032 class rrel_estimation_problem 00033 { 00034 public: 00035 //: Type of scale information this problem provides. 00036 // NONE: problem does not provide any scale information. SINGLE: 00037 // problem provides a single prior scale (homoscedastic 00038 // data). MULTIPLE: problem provides a scale for each residual 00039 // (heteroscedastic data). 00040 enum scale_t { NONE = 0, SINGLE = 1, MULTIPLE = 2 }; 00041 00042 public: 00043 //: Constructor. 00044 // See the comments for param_dof() and num_samples_to_instantiate() 00045 // for the meaning of these two parameters. 00046 rrel_estimation_problem( unsigned int param_dof, 00047 unsigned int num_samples_for_fit ); 00048 00049 //: Constructor. 00050 // Derived classes using this _must_ call set_dof() and set_num_samples_for_fit(). 00051 rrel_estimation_problem( ); 00052 00053 //: Destructor. 00054 virtual ~rrel_estimation_problem(); 00055 00056 //: The degrees of freedom in the parameter set. 00057 unsigned int param_dof() const { return dof_; } 00058 00059 //: Minimum number of samples required to uniquely instantiate a fit. 00060 // dof()/num_samples_to_instantiate() gives the number of constraints per sample. 00061 unsigned int num_samples_to_instantiate( ) const { return num_samples_for_fit_; } 00062 00063 //: The number of samples. 00064 virtual unsigned int num_samples( ) const = 0; 00065 00066 //: The degrees of freedom in the residual. 00067 // Most of the time, this would be 1 since the residual comes from 00068 // a single random variable. In some problems, however, the error 00069 // is the combination of more than one random variable. (For 00070 // example, if the residual is a 2d Euclidean distance with 00071 // possible error in both coordinates, the degrees of freedom in 00072 // the error will be 2.) 00073 virtual unsigned int residual_dof() const { return 1; } 00074 00075 //: The number of "unique" samples. 00076 // In most problems, this equals num_samples. With estimation 00077 // problems involving non-unique correspondences, however, the total 00078 // number of possible correspondences (= num_samples()) generally 00079 // much greater than the number of "unique samples" (which would be 00080 // the number of points from one image). 00081 // 00082 // This is used by random sampling techniques to determine the 00083 // number of samples required to get a given probability of success. 00084 virtual unsigned int num_unique_samples( ) const { return num_samples(); } 00085 00086 //: Generate a parameter vector from a minimal sample set. 00087 // The \a point_indices vector are indices into the data set, and 00088 // must be filled in with num_samples_to_instantiate() indices. 00089 // Returns true if and only if the points resulted in a unique 00090 // parameter vector. 00091 virtual bool fit_from_minimal_set( const vcl_vector<int>& /* point_indices */, 00092 vnl_vector<double>& /* params */ ) const = 0; 00093 00094 //: Compute the residuals relative to the given parameter vector. 00095 // The number of residuals must be equal to the value returned 00096 // by num_samples(). 00097 // 00098 // This is a deterministic procedure, in that multiple calls with a 00099 // given parameter vector must return the same residuals (in the 00100 // same order). 00101 virtual void compute_residuals( const vnl_vector<double>& params, 00102 vcl_vector<double>& residuals ) const = 0; 00103 00104 //: Compute the weights for the given residuals. 00105 // The residuals are essentially those returned by 00106 // compute_residuals(). The default behaviour is to apply obj->wgt() 00107 // to each residual. Some problems, however, many need to augment 00108 // the weights. Such problems should override this function (but 00109 // may want to call this to compute the "basic" weights). 00110 virtual void compute_weights( const vcl_vector<double>& residuals, 00111 const rrel_wls_obj* obj, 00112 double scale, 00113 vcl_vector<double>& weights ) const; 00114 00115 //: Type of scale information the problem provides. 00116 virtual scale_t scale_type() const { return scale_type_; } 00117 00118 //: The prior scale vector, if available. 00119 // The call is valid only if scale_type() == MULTIPLE. 00120 virtual const vcl_vector<double>& prior_multiple_scales() const; 00121 00122 //: The prior scale, if available. 00123 // The call is valid only if scale_type() == SINGLE. 00124 virtual double prior_scale() const; 00125 00126 //: Sets the scales for heteroscedastic data. 00127 // Side effect: set scale_type() = MULTIPLE. 00128 virtual void set_prior_multiple_scales( const vcl_vector<double>& scales ); 00129 00130 //: Sets the scale for homoscedastic data. 00131 // Side effect: set scale_type() = SINGLE. 00132 virtual void set_prior_scale( double scale ); 00133 00134 //: Removes the scale information for the problem. 00135 // Side effect: set scale_type() = NONE. 00136 virtual void set_no_prior_scale( ); 00137 00138 //: Set similarity weights 00139 // Currently it is only used in wgted random sampling search 00140 void set_similarity_weights( const vcl_vector<double>& wgts ) 00141 { similarity_weights_ = wgts; } 00142 00143 //: Get similarity weights 00144 const vcl_vector<double>& similarity_weights() const 00145 { return similarity_weights_; } 00146 00147 //: Compute the parameter vector and the normalised covariance matrix. 00148 // (Multiplying this matrix by the variance in the measurements 00149 // gives the covariance matrix.) 00150 // 00151 // If the weights are provided they are used in the process. Note 00152 // that if the weights are in fact given, the number of weights 00153 // (num_wgts) MUST be equal to "num_residuals" returned by the 00154 // compute_residuals function. If some of the residuals should be 00155 // ignored as outliers (e.g. as explicitly identified as such by 00156 // Least Median of Squares), then their weights should just be set 00157 // to 0. 00158 virtual bool weighted_least_squares_fit( vnl_vector<double>& params, 00159 vnl_matrix<double>& norm_covar, 00160 const vcl_vector<double>* weights=0 ) const = 0; 00161 00162 protected: 00163 //: Set the degrees of freedom. 00164 void set_param_dof( unsigned int dof ) { dof_ = dof; } 00165 00166 //: Set the number of samples needed for a unique fit. 00167 void set_num_samples_for_fit( unsigned int num_samp ) { num_samples_for_fit_ = num_samp; } 00168 00169 //: Set the type of prior scale. 00170 void set_scale_type( scale_t t ) { scale_type_ = t; } 00171 00172 private: 00173 unsigned int dof_; 00174 unsigned int num_samples_for_fit_; 00175 scale_t scale_type_; 00176 double single_scale_; 00177 vcl_vector<double>* multiple_scales_; 00178 vcl_vector<double> similarity_weights_; 00179 }; 00180 00181 #endif