contrib/rpl/rgrl/rgrl_feature_point.cxx
Go to the documentation of this file.
00001 #include "rgrl_feature_point.h"
00002 //:
00003 // \file
00004 // \author Amitha Perera
00005 // \date   Feb 2003
00006 
00007 #include <vnl/vnl_math.h>
00008 
00009 #include <rgrl/rgrl_cast.h>
00010 #include <rgrl/rgrl_transformation.h>
00011 #include <rgrl/rgrl_util.h>
00012 
00013 #include <vcl_cassert.h>
00014 
00015 #if 0 // unused static function
00016 static
00017 vnl_matrix<double> const&
00018 identity_matrix( unsigned size )
00019 {
00020   static vnl_matrix<double> matrices[5] = { vnl_matrix<double>(0, 0, vnl_matrix_identity ),
00021                                             vnl_matrix<double>(1, 1, vnl_matrix_identity ),
00022                                             vnl_matrix<double>(2, 2, vnl_matrix_identity ),
00023                                             vnl_matrix<double>(3, 3, vnl_matrix_identity ),
00024                                             vnl_matrix<double>(4, 4, vnl_matrix_identity ) };
00025   assert( size < 5 );
00026   return matrices[size];
00027 }
00028 #endif // 0
00029 
00030 rgrl_feature_point::
00031 rgrl_feature_point( vnl_vector<double> const& loc )
00032   : rgrl_feature( loc )
00033 {
00034 }
00035 
00036 rgrl_feature_point::
00037 rgrl_feature_point( vnl_vector<double> const& loc, double scale )
00038   : rgrl_feature( loc, scale )
00039 {
00040 }
00041 
00042 rgrl_feature_point::
00043 rgrl_feature_point( unsigned size )
00044 : rgrl_feature()
00045 {
00046   location_.set_size( size );
00047 }
00048 
00049 
00050 unsigned int
00051 rgrl_feature_point::
00052 num_constraints() const
00053 {
00054   return location_.size();
00055 }
00056 
00057 vnl_matrix<double> const&
00058 rgrl_feature_point::
00059 error_projector() const
00060 {
00061   if(scale_ == 0){
00062     WarningMacro( "The scale is zero." );
00063   }
00064   if ( !err_proj_.size() )
00065   {
00066     const unsigned m = location_.size();
00067     err_proj_.set_size( m, m );
00068     err_proj_.set_identity();
00069     err_proj_ /= vnl_math_sqr( scale_ );
00070   }
00071 
00072   return err_proj_;
00073 }
00074 
00075 vnl_matrix<double> const&
00076 rgrl_feature_point::
00077 error_projector_sqrt() const
00078 {
00079   if(scale_ == 0){
00080     WarningMacro( "The scale is zero." );
00081   }
00082   if ( !err_proj_sqrt_.size() )
00083   {
00084     const unsigned m = location_.size();
00085     err_proj_sqrt_.set_size( m, m );
00086     err_proj_sqrt_.set_identity();
00087     err_proj_sqrt_ /= scale_;
00088   }
00089 
00090   return err_proj_sqrt_;
00091 }
00092 
00093 rgrl_feature_sptr
00094 rgrl_feature_point::
00095 transform( rgrl_transformation const& xform ) const
00096 {
00097   rgrl_feature_point* result = new rgrl_feature_point( location_.size() );
00098 
00099   // capture the allocation into a smart pointer for exception safety.
00100   rgrl_feature_sptr result_sptr = result;
00101 
00102   // Transform the location
00103   //
00104   xform.map_location( this->location_, result->location_ );
00105   if ( this->scale_ > 0.0 )
00106     result->scale_ = this->transform_scale( xform );
00107 
00108   return result_sptr;
00109 }
00110 
00111 double
00112 rgrl_feature_point::
00113 transform_scale( rgrl_transformation const& xform ) const
00114 {
00115 #if 1 /*old method, rely on scaling factors*/
00116   // transform scale
00117   vnl_vector<double> const& scaling = xform.scaling_factors();
00118   const unsigned dim = this->location_.size();
00119   // use default value of 1.0
00120   double scale = 1.0;
00121 
00122   if ( this->scale_ > 0.0 && scaling.size() == dim )
00123   {
00124     // "average" them
00125     if ( dim == 2 )
00126       scale = vcl_sqrt( scaling[0]*scaling[1] ) * this->scale_;
00127     else {
00128       double prod_scale=1;
00129       for ( unsigned i=0; i < dim; ++i )
00130         prod_scale *= scaling[i];
00131       scale = vcl_exp( vcl_log(prod_scale) / double(dim) ) * this->scale_;
00132     }
00133   } else if ( this-> scale_ != 1.0 ) {
00134     WarningMacro( "This feature has non-zero scale value, but transformation has no scaling factors."
00135                   << "The scale of transformed features is NOT set." );
00136   }
00137   return scale;
00138 
00139 #else  /*new method, though Jacobian of the transformation*/
00140 
00141   const unsigned dim = this->location_.size();
00142 
00143   // get jacobian
00144   vnl_matrix<double> jac;
00145   xform.jacobian_wrt_loc( jac, this->location() );
00146   assert( jac.cols() == dim );
00147 
00148   // each column in this jac matrix represents the change
00149   // on fixed image coordindate given one change on one of the axes of
00150   // the moving image.
00151   // Thus, the magnitude of this column vector represents the scale change
00152   // on this particular axis.
00153   // Take the average of magnitude on all the axes
00154   double cumulative_scale_change = 0.0;
00155   for ( unsigned i=0; i<jac.cols(); ++i ) {
00156 
00157     double sqr_mag = 0.0;
00158     for ( unsigned j=0; j<jac.rows(); ++j )
00159       sqr_mag += vnl_math_sqr( jac(j,i) );
00160 
00161     cumulative_scale_change += vcl_sqrt( sqr_mag );
00162   }
00163   cumulative_scale_change /= jac.cols();
00164 
00165   return cumulative_scale_change * this->scale();
00166 #endif
00167 }
00168 
00169 //:  Compute the signature weight between two features.
00170 double
00171 rgrl_feature_point::
00172 absolute_signature_weight( rgrl_feature_sptr other ) const
00173 {
00174   //if other is invalid
00175   if ( !other )  return 0.0;
00176 
00177   rgrl_feature_point* pt_ptr = rgrl_cast<rgrl_feature_point*>(other);
00178   assert( pt_ptr );
00179 
00180   double scale_wgt = 1;
00181   if ( this->scale_ && pt_ptr->scale_ ) {
00182     if ( this->scale_ >= pt_ptr->scale_ )
00183       scale_wgt = pt_ptr->scale_ / this->scale_;
00184     else
00185       scale_wgt = this->scale_ / pt_ptr->scale_;
00186     // the weight change is too gradual, make it more steep
00187     // scale_wgt = scale_wgt * scale_wgt;
00188   }
00189 
00190   return  vcl_sqrt(scale_wgt);
00191 }
00192 
00193 //: write out feature
00194 void
00195 rgrl_feature_point::
00196 write( vcl_ostream& os ) const
00197 {
00198   // tag
00199   os << "POINT" << vcl_endl;
00200 
00201   // dim
00202   os << location_.size() << vcl_endl;
00203 
00204   // atributes
00205   os << location_ << "    " << scale_ << vcl_endl;
00206 }
00207 
00208 //: read in feature
00209 bool
00210 rgrl_feature_point::
00211 read( vcl_istream& is, bool skip_tag )
00212 {
00213   if ( !skip_tag )
00214   {
00215     // skip empty lines
00216     rgrl_util_skip_empty_lines( is );
00217 
00218     vcl_string str;
00219     vcl_getline( is, str );
00220 
00221     // The token should appear at the beginning of line
00222     if ( str.find( "POINT" ) != 0 ) {
00223       WarningMacro( "The tag is not POINT. reading is aborted.\n" );
00224       return false;
00225     }
00226   }
00227 
00228   // get dim
00229   int dim=-1;
00230   is >> dim;
00231 
00232   if ( !is || dim<=0 )
00233     return false;    // cannot get dimension
00234 
00235   // get location
00236   location_.set_size( dim );
00237   is >> location_;
00238 
00239   if ( !is )
00240     return false;   // cannot read location
00241 
00242   // get scale
00243   is >> scale_;
00244 
00245   if ( !is )
00246     return false;   // cannot read scale
00247 
00248   return true;
00249 }
00250 
00251 rgrl_feature_sptr
00252 rgrl_feature_point::
00253 clone() const
00254 {
00255   return new rgrl_feature_point(*this);
00256 }